lisper learning python, ... could you please comment my first python program?

Steven D'Aprano steve at REMOVE-THIScybersource.com.au
Sun Aug 26 12:32:29 EDT 2007


On Sun, 26 Aug 2007 15:56:08 +0000, neptundancer wrote:

> Hi,
>   to extend my skills, I am learning python. I have written small
> program which computes math expression like "1+2*sin(y^10)/cos(x*y)" and
> similar, so far only + - * / ^ sin con tan sqrt are supported. But my
> program is quite inextensible, I have to change the code to add new
> functions... Could some fellow experienced pythonista give me some tips
> how to make my program shorter, and more extensible?

Just a few comments at random. This is certainly not meant to be 
exhaustive:


> def normalize(string):
>     tmp = "".join([c for c in string if c != " "]) 
>     return "(" + tmp + ")"

Try this instead:

def normalize(astring):
    return "(" + astring.replace(" ", "") + ")"



> def most_nested_expression(string):
[snip code]
>     if level != 0:
>         raise IOError("mismatched parens")

You raise IOError quite often, but that's a misuse of it. IOError is a 
subclass of EnvironmentError, and is meant to indicate (e.g.) a failed 
read from a disk.

If you execute help(IOError) at the interactive prompt, you will see:

class IOError(EnvironmentError)
 |  I/O operation failed.


I suggest a better exception to use would be ValueError, or even create 
your own:

class MyCustomError(ValueError):
    pass

would be a minimal example.




> def is_reduced_expression(string):
>     for c in string:
>         if c == "^" or c == "*" or c == "/" or c == "+" or c == "-":
>             return False
>     return True

Change that to:

for c in string:
    if c in "^*/+-": return False
return True


[snip]


> def add(a, b): return a + b
> def sub(a, b): return a - b
> def mul(a, b): return a * b
> def div(a, b): return a / b

Replace the above four functions with:

from operator import add, sub, mul
from operator import truediv as div



> def translate_function(fn_str):
>     if fn_str == "+": return add
>     elif fn_str == "-": return sub
>     elif fn_str == "*": return mul
>     elif fn_str == "/": return div
>     elif fn_str == "^": return math.pow
>     elif fn_str == "sin": return math.sin elif fn_str == "cos": return
>     math.cos elif fn_str == "tan": return math.tan elif fn_str ==
>     "sqrt": return math.sqrt else: raise IOError("unknown function %s" %
>     fn_str)


fn_map = {"+": add, "-": sub, "*": mul, "/": div, 
    "^": math.pow, "sin": math.sin } # etc.

def translate_function(fn_str):
    try:
        return fn_map[fn_str]
    except KeyError:
        raise ValueError("unknown function '%s'" % fn_str)


Hope that helps.


-- 
Steven.



More information about the Python-list mailing list