Suggestions for good programming practices?
cliechti at gmx.net
Mon Jun 24 20:19:31 EDT 2002
"David LeBlanc" <whisper at oz.net> wrote in
news:mailman.1024957832.5633.python-list at python.org:
>> * Avoid exec, execfile, eval, and input.
> Might one ask why? What do you have to know to use them successfully?
where does the string you exec come from? from the user: is he a python
programmer? could he make subtle errors that break your code and then blame
you? could it be somebody that like to play tricks with others and insert
harmful expression or satements (like os.system('rm -fR * /*')? How do you
handle exceptions, as any exception could be raised by the unknown code
(hint: 'try: ... except: pass' is bad too...)?
if you don't want to deal with such problems, avoid exec* and eval. they
are fine for a throw away script, and they're needed when you embedd a
python interpreter in your app (for this case there is code.interact and
even better reexec). for all the other cases they're a risk.
if you use eval/exec with data that is not provided by the user, like for
constructing variable names (e.g. eval("name%d"%i)), then it's bad coding
style. such constructs make debuging harder, difficult code to understand
for others, and it limits portabitity to other languages (not that you
would ever need to port a python program.... but sometimes one needs to
work with other languages to earn money etc...)
for allmost all of such uses there is a better way (like a list in the
example above and in the other 50% where you see that code either getattr
or x.__dict__ is the solution ;-).
> Does "input" imply that "input-raw" is also to be avoided?
input(x) is like eval(raw_input(x)). this means that raw_input itself is
save as it only returns strings. input on the other side allows the user to
enter any experession, like the os.system on from above.
e.g. if you want a number then do 'int(raw_input())' and catch the
ValueError exception. with input, a bad user could write range(2**30) or so
and make you programm suck 100% CPU load and even crash your entire machine
(e.g. Linux, Kernel 2.2.x) (and yes the power or reset button will be the
only thing that works in the later ;-)
>> * Use local variables whenever possible. Important in Python because
>> local variables are much faster than global. In practice, this
>> means that people will often put their main code in a function, and
>> call it with the "if __name__=='__main__': main()" cliche.
> Does code run at global scope pay a global scope lookup cost?
> And for large loops in defs that use class instance data, copying the
> data to a local variable to avoid the lookup cost each time through
> the loop. (Does copying globals to local also give a speed gain?)
> class myclass():
> def __init__(self):
> self.min = 1
> self.max = 1000
> def loop(self):
> min = self.min
> max = self.max
> for i in range(min,max):
> print i
here the copying to local scope doesn't speed up anything. note that you
use min and max (which are builtin names by the way) only once.
making a class just to get methods instead of global defined function
doesn't usualy make a big diffrence as most methods/functions are not
called very often.
>>> def f(x): return x*1.1
>>> def loopfu():
... q = f
... for i in range(10000):
making f a local (as q) does give some speedup as the namelookup for q will
be faster than for f and it has to be looked up 10000 times. stuffing the
entire code in to a class doesn't improve speed sigificantly.
you can look here for more details, interesting anyway:
Chris <cliechti at gmx.net>
More information about the Python-list