I'm fairly new to python, coming from a perl background, and was wondering
if anyone has a list of things that they consider as good programming
practice in Python (I thought this might be an interesting topic for
discussion, anyway)
For example, in perl you obviously are always encouraged to use strict, and
we always use eval around our main code to pick up any unexpected errors. I
presume the equivalent in python is the try statement. Would you suggest
that this should be used, or would that be redundant here? Any other tips
that you would suggest a new python user should be always doing as a good
programming practice?
Thanks
Di
While it's not quite an answer to the question you asked, you should
read this:
http://www.python.org/doc/essays/styleguide.html
I would say in addition to that, that unlike many other languages you
don't need to worry too much about other good programming practices
if you just write simple, clean Python code. Make your goal to
write the most readable and maintainable code you can, and all else
will follow.
As for try/except... if you want you could put a non-specific
try/except around the entire application, but all that would be good
for is to mask fatal errors and prevent the interpreter from printing
them properly to show you what went wrong. Not sure why you'd want
to do that in smaller programs at all, though in large ones you might
catch the exceptions and write them to an error file for later analysis.
-Peter
> I [...] was wondering if anyone has a list of things that they consider
> as good programming practice in Python (I thought this might be an
> interesting topic for discussion, anyway)
I've seen many ideas expressed on this list. Being rather maniacal on
details, I surely gave many programming rules to myself which I try to
follow. Maybe I should take the time and formalise these into some Web page.
On the other hand, style may always be the source of heated debates!
Despite Python is simple, I try to _not_ even use all of it. For example,
`print' is strictly reserved for debugging purposes, I never use `print'
for production scripts. I also completely avoided `input' so far. It is
exceptional that I use `exec' or `eval', and I almost never use `global'.
Python has evolved fastly in recent times. You might also want to decide
for which Python version you aim your code, and choose to _not_ take
advantage of all the features of the latest Python available. This is
especially useful if you move between machines, or have a user base.
> For example, in perl you obviously are always encouraged to use strict, and
> we always use eval around our main code to pick up any unexpected errors.
Python is pretty exceptional in that it catches and reports errors
automatically, unless you do take special action to prevent it of doing so.
In C or Perl, this is a constant burden for any programmer who takes style
seriously. I see this as one of the important reliefs brought by Python.
I also much like `assert' as an expedient way to report consistency
errors, and even usage errors. I do not mind tracebacks in such cases,
even if they are not much useful in case of usage errors. With `assert',
the second argument is often a tuple containing all variables which are
meaningfully dumped to understand why the `assert' was triggered.
> Any other tips that you would suggest a new python user should be always
> doing as a good programming practice?
Peter Hansen already suggested the Guido style guide, which hold many
good ideas.
All my executable scripts use similar conventions about how to organise
calling of the main function, decoding options, providing help, etc.
My projects are also structured in similar ways (`Makefile', `setup.py',
etc.) and installable without having to be `root'. I gave a fair amount
of thought before deciding how those things are best done. My co-workers
adopted very similar conventions, so we can more easily share development.
The key point of all this is that it pays being consistent between all
one's Python works. My suggestion is that you should actively develop a
style that suits you, and reasonably be faithful to your own style. :-)
--
François Pinard http://www.iro.umontreal.ca/~pinard
Python has relatively few of these. I've been racking my brain to
think of any, but could only think of one really serious issue we face
in Python. Python is a cautious language, and if you overlook
something there's a good chance you'll see a stack trace.
Anyways, the really important issue is:
* Do not mix spaces and tabs for indentation. Choose one or the other
and stick with it. It helps to have an editor that indents
intelligently and does nothing funny with the indents.
There's other stuff, but the same ideas apply to languages other than
Python.
* Avoid exec, execfile, eval, and input.
* 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.
* Learn how references and the object system work as soon as possible.
You should not be surprised when you do this:
a = [1,2,3]
b = a
b[0] = 100
print a
And it prints "[100,2,3]"
--
CARL BANKS http://www.aerojockey.com
"Nullum mihi placet tamquam provocatio magna. Hoc ex eis non est."
ObBrokenRecord: "bindings", not "references".
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/
Project Vote Smart: http://www.vote-smart.org/
Of course, you are free to call it whatever you want.
Here's one...
When evaluating whether a variable is None, don't compare it like this:
if x == None:
instead, use:
if x:
or:
if not x:
The encourages a polymorphic approach. If you must compare to None, use the
identify operator rather than equality:
if x is None:
or:
if x is not None:
// mark
-
David LeBlanc
Seattle, WA USA
I'm curious to know how this encourages polymorphism, and how making a
conditional test implicit rather then explicit is good practice?
Regards,
Dave LeBlanc
Seattle, WA USA
Your question reveals my lack of understanding and clarity. Let me try
again:
If you compare to None with equality, your tests may fail for objects that
overload the comparison functions and don't anticipate other being None. An
example I encountered was using Tim Peters' FixedPoint for currency values.
It doesn't make sense to do this:
x = FixedPoint(None)
and yet that's what will happen if you try to do this:
x = FixedPoint(1.00)
...
if x == None:
In other words, this raises an error. I think the intention behind that
comparison is really to see whether x is None, is in the specific identity
sense. This, of course, is contrary to my statement about if x being
preferable to if x is not None.
Anyway, I gave an example of why you might not want to use this, but maybe
it seems too convoluted:
if x == None:
How do you choose between these:
if x is None:
if x:
The latter is what you'd use if you wanted to work with instances that
defined __nonzero__ and or __len__. In other words, you don't really care
what the type of x is, nor whether it's identity is zero, just whether it
considers itself nonzero.
Is one more or less polymorphic than the other? I don't really know. But
it sure does sound good.
Cheers,
// mark
-
one of the mantras you will hear on this list is:
the simpler the code the better
you hear this on style issues, on optimization issues, and well practically
everywhere. Usually the simple, clean approach yields the best possible python
-- both in your time and in runtime. So if you find yourself saying "man, why
is this so complex" you should stop and rethink the problem.
As a side item, tu...@python.org is a GREAT place to hang out and read about
other people learning python. You can really pick up a lot of the niceties and
sublties of the language there.
Might one ask why? What do you have to know to use them successfully? Does
"input" imply that "input-raw" is also to be avoided?
Avoid "from foo import *"; this avoids unnecessary namespace pollution and
other forms of confusion.
> * 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
> * Learn how references and the object system work as soon as possible.
> You should not be surprised when you do this:
>
> a = [1,2,3]
> b = a
> b[0] = 100
> print a
>
> And it prints "[100,2,3]"
The one that always gets me is "lat,lon,timezone = getLocation("seattle")".
I.E. the ability to return multiple distinct values as opposed to returning
multiple values in the form of a struct as in C or C++.
I would add to the list:
* Learn to think in OO and pattern concepts.
> --
> CARL BANKS http://www.aerojockey.com
> "Nullum mihi placet tamquam provocatio magna. Hoc ex eis non est."
Dave LeBlanc
Seattle, WA USA
" Curses! self.bdfl will never work! Back to the drawing board Pinky!"
David LeBlanc wrote:
> The one that always gets me is "lat,lon,timezone = getLocation("seattle")".
> I.E. the ability to return multiple distinct values as opposed to returning
> multiple values in the form of a struct as in C or C++.
I don't consider that a problem, I find it quite useful, because when
you want to use the returned values, you don't have to "rip them out" of
the struct. In an example such as above with the timezones, you might
later want to use the different results in different contexts, where in
my opinion a subscribed object from a struct makes the less readable.
It sometimes, however does make coding or reading code a tad more
error-prone insofar that at first sight you can't always be sure just
how many objects that call returns.
Greetings,
Dietmar
--
I haven't lost my mind -- it's backed up on tape somewhere.
> <snip>
>>
>> * 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):
... q()
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:
http://manatee.mojam.com/~skip/python/fastpython.html
chris
--
Chris <clie...@gmx.net>
I haven't had a record player for a while :-) so would you please
expand on that? I've adopted "references" without giving it any
thought. Why is that not as good as "bindings"?
Thanks.
-Peter
You _are_ returning them "in a struct". It's spelled "tuple"
but other than that what's the difference?
-Peter
I'll amend my previous claim to point to testing as a very useful
part of Python development. I don't mean running your code manually
after the fact, either. I mean proper unit testing, which exercises
as much of the code in small pieces as you possibly can.
Unlike with statically typed languages, Python cannot check that
you are not, for example, trying to pass an integer into a routine
that can only accept a string until you actually execute the code.
You don't get the error on compilation as with C for example.
It can become frustrating if you have to run the code manually
each time you make a change and possibly go through a large
sequence of steps before you get to the part you want to test.
Therefore, learn to make your code testable. Write it in small
modular pieces and have good tests for each. When you make
a change, run the tests again and they will tell you whether
you've screwed up anything. If something slips through and
you find a bug, go back and write another test that fails
on the same problem, then fix the code (making the test
pass).
No, not many people actually do this. I've found it highly
effective, however, and it more than makes up for any
limitations that might exist because of the dynamic nature
of Python compared to statically typed languages. This
all comes from Extreme Programming, of course, but you can
easily benefit from proper unit testing even without other
changes to your development process.
And most of this advice actually applies to any language,
but I think Python can take advantage of it even more than most.
-Peter
struct members are access by name while tuple elements are accessed
positionally.
Cheers,
Brian
Okay. So why is that a problem?
Or to ask it from the other side, what's stopping you from
returning items in an object?
class Struct:
pass
def returnStruct():
result = Struct()
result.anInt = 5
result.aString = 'foo bar baz'
result.spam = ('eggs', 'brian')
return result
-Peter
I'm not saying it is. I'm saying that tuples and structs are different.
Cheers,
Brian
BTW, struct is a module name :->
David LeBlanc
Seattle, WA USA
> --
> http://mail.python.org/mailman/listinfo/python-list
I suspect that exec, execfile and eval are useful programmatically for
executing external programs, especially when one is assembling the path/file
oneself. One might even find a use for creating and evaluating code on the
fly.
Good points about input though.
> > 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 ;-)
More good points about input
The example was contrived for the purpose of discussion. I'm sure willing to
bet that the numerous (well, several) times I've seen "self" variables
copied into methods where there for performance. Actually, I don't see a
huge difference between your example and mine wrt the idea of making "far"
things "near" to enhance performance. BTW, "min" and "max" are not builtins
in the example - they're instance variables of the class.
I would still be interested in knowing if global code paid a price for
accessing global variables since they're both running in the same scope?
> you can look here for more details, interesting anyway:
> http://manatee.mojam.com/~skip/python/fastpython.html
>
> chris
>
> --
> Chris <clie...@gmx.net>
Dave LeBlanc
Seattle, WA USA
Language lawyer should be shot, _then_ heard.
David LeBlanc
Seattle, WA USA
In Python 2.1.2 or higher, fire up the interactive interpreter and type
"import this".
Because unless you're using the C API, you can never access the
references directly. Python always hides the references from you:
>>> a = []
>>> b = a
>>> a.append(1)
>>> b
[1]
It's pretty clear that the assignment creates a reference to an object,
rather than having a variable contain the value. It should be equally
clear that the dereferencing is completely automatic -- so automatic, in
fact, that you *can't* get at the reference.
Saying "binding" instead of "reference" helps to remember the critical
semantic differences in Python's object model. It also helps when one
is trying to explain things like this:
def f(a, x=[]):
x.append(a)
print x
f(1)
f('foo')
L=[5]
f(9, L)
f(23)
Depends on what you're testing for. One of the big features of Python's
object model is that any "empty" object tests as false: None, 0, "", (),
[], and {}. Testing for a specific false value (such as 0 or None)
prevents you from easily changing the object being used. Rely on the
object to tell you whether it's true or false, and you'll be fine.
That's polymorphic.
Look at it this way:
a,b,c = func()
abc = func()
a = abc[0]
b = abc[1]
c = abc[2]
Which would you rather write? In C or C++ you have to use an analog of the
second way since the first way isn't an option. I _like_ this behavior of
Python.
It's a piddling point as to how Python returns the info - they come to rest
in discrete variables, not as elements of one aggregate variable. The
original point was about the flexibility of Python not some technical
hair-splitting about what Python might put on the stack.
David LeBlanc
Seattle, WA USA
> -----Original Message-----
> From: Peter Hansen [mailto:pe...@engcorp.com]
> Sent: Monday, June 24, 2002 19:28
> To: David LeBlanc
> Subject: Re: Suggestions for good programming practices?
>
>
> David LeBlanc wrote:
> >
> > They may be returned in a tuple, but they're PUT in discrete
> variables and
> > not kept in a tuple that I have to programmatically unpack.
> >
> > Language lawyer should be shot, _then_ heard.
>
> I don't understand the above at all. Sorry. :) Are you
> unhappy with this behaviour of Python? And I don't get
> the language lawyer part. (Pretend I'm really thick...it
> won't be far from the truth.)
>
> -Peter
It's like people: boys are people and girls are people, but if you try to
access a strange girl by position, you're apt to get your face smacked or
worse! ;-)
<tongue value='most firmly in cheek'/>
David LeBlanc
Seattle, WA USA
> -----Original Message-----
> From: python-l...@python.org
> [mailto:python-l...@python.org]On Behalf Of Brian Quinlan
> Sent: Monday, June 24, 2002 19:04
> To: 'Peter Hansen'; pytho...@python.org
> Subject: RE: Suggestions for good programming practices?
>
>
> Peter Hansen wrote:
> > Brian Quinlan wrote:
> > >
> > > Peter Hansen wrote:
> > > > You _are_ returning them "in a struct". It's spelled "tuple"
> > > > but other than that what's the difference?
> > >
> > > struct members are access by name while tuple elements are accessed
> > > positionally.
> >
> > Okay. So why is that a problem?
>
> I'm not saying it is. I'm saying that tuples and structs are different.
>
> Cheers,
> Brian
>
>
>
Don't be rude please. Your offline message pointed out that you
_like_ this behaviour, and so do I, but your original message
appeared to indicate you did not. I was trying to get at
why you didn't like it, not to be pedantic or anything.
David LeBlanc originally wrote:
> The one that always gets me is "lat,lon,timezone =
> getLocation("seattle")". I.E. the ability to return multiple
> distinct values as opposed to returning
> multiple values in the form of a struct as in C or C++.
Sorry for the confusion...
-Peter
>Grrrr!
>
>Look at it this way:
>
> a,b,c = func()
>
> abc = func()
> a = abc[0]
> b = abc[1]
> c = abc[2]
>
>Which would you rather write? In C or C++ you have to use an analog of the
>second way since the first way isn't an option. I _like_ this behavior of
>Python.
>
>It's a piddling point as to how Python returns the info - they come to rest
>in discrete variables, not as elements of one aggregate variable. The
>original point was about the flexibility of Python not some technical
>hair-splitting about what Python might put on the stack.
The 'a,b,c = func()'-style is good as far as there will be
no soon change to the number of variables.
I'd not advice using this style as I fight it now in my own
old scripts...
Now I am using dicts or instances to hold values:
it gives context information:
abc = func()
... use abc["first"]
abc["second"] ...
... abc["third"]
or (in the less trivial cases):
abc = func()
... use abc.first
abc.second ...
... abc.third
Or I am using 'constants' to access return:
FIRST,SECOND,THIRD = range(3)
...
abc = func()
... use abc[FIRST]
abc[SECOND] ...
... abc[THIRD]
- all these allow variable number of returned values thus
keeping compatibility. (for example, I can access old
and new logs by the same code).
Well, to be honest, I am also using this approach:
a,b,c,d,e = (func()+ (None,)*2)[:5]
when originally there were 3 vars and now I sometimes get
3, sometimes 5.
but it is not very nice...
- those my examples aren't probably good programming practices,
but they allow not to loose context when flexibility is needed.
>David LeBlanc
>Seattle, WA USA
Sincerely yours, Roman Suzi
--
r...@onego.ru =\= My AI powered by Linux RedHat 7.2
I've come to really dislike using tuples for data structures, and
instead create small data classes. Even if the class is no more
complicated than:
class myData:
def __init__ (self, foo, bar):
self.foo = foo
self.bar = bar
you've added quite a bit of functionality. First, the code becomes a
little more self-documenting. "power = ckt.volts * ckt.amps" is a lot
easier to read and understand than "power = ckt[0] * ckt[1]".
Secondly, it makes it easier to catch programming errors. I was working
with somebody the other day who was using tuples to store data. His
program was doing something strange. When I made him rewrite one of his
data structures as a simple data class instead of a tuple, the reason
instantly popped out. He had gotten confused and was using the wrong
piece of data. When he had everything as tuples, it just happily took
the i'th element of the wrong tuple and gave him garbage. But, when he
tried to access an attribute that didn't exist, it immediately raised an
exception.
Except ActiveState's
F:\Python22as>python
Python 2.2 (#28, Dec 21 2001, 12:21:22) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ImportError: No module named this
--
Emile van Sebille
em...@fenx.com
---------
Am I missing something?
F:\Python22>python
Python 2.2 (#28, Dec 21 2001, 12:21:22) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The ...
(the following applies most obviously to modern versions of python. I
use subclassing of builtin objects, __slots__ and zip(). Even so, the
myStruct class is useful in any version of Python back to at least 1.5,
if you make myStruct a regular class, and include a definition
of zip())
You can do even better (lower memory overhead) with
class myData(object):
__slots__ = ['foo', 'bar']
def __init__ (self, foo, bar):
self.foo = foo
self.bar = bar
you could go a little farther and make a superclass that has a __init__
that works for any subclass:
class myStruct(object):
def __init__(self, *args):
if len(args) != len(self.__slots__):
raise TypeError, \
"__init__() takes exactly %d arguments (%d given)" \
% (len(self.__slots__)+1, len(args)+1)
for name, arg in zip(self.__slots__, args):
setattr(self, name, arg)
class myData(myStruct):
__slots__ = ['foo', 'bar']
Jeff
Cheers,
Simon Brunning
TriSystems Ltd.
sbru...@trisystems.co.uk
-----------------------------------------------------------------------
The information in this email is confidential and may be legally privileged.
It is intended solely for the addressee. Access to this email by anyone else
is unauthorised. If you are not the intended recipient, any disclosure,
copying, distribution, or any action taken or omitted to be taken in
reliance on it, is prohibited and may be unlawful. TriSystems Ltd. cannot
accept liability for statements made which are clearly the senders own.
> >> * 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.
This view is a overly extreme. Rather than teaching people to fear certain
features like eval/exec, it's better to explain the risks so that they can
make informed decisions as to when it's wise to use them.
For example, eval/exec are incredibly useful in building mini-languages
based on Python, in which you execute user code in some dictionary that
includes your set of custom functions (you basically end up with a
context-specific superset of Python). I've found this to be very useful in
several production systems (not 'throw away script[s]') as well as in
creating programmable test harnesses for the QA department (the
non-programmer QA engineers aren't scared off because they don't realize
it's programming, and the more technical QA engineers are pleased that
you've built them such a "rich" test harness language...hehehe). Can
malicious users do malicious things? Of course! But that's like saying
Guido should disable os.system!
So... rather than teaching "avoid W!", let's say "be careful with W
because of X, Y, and Z". I still wouldn't use eval/exec on code posted
through a web form, for example, but there are times when they are very
useful and I can use them in good confidence because I understand their
risks.
-Dave
>>class myData:
>> def __init__ (self, foo, bar):
>> self.foo = foo
>> self.bar = bar
>>
>>you've added quite a bit of functionality. First, the code becomes a
>>little more self-documenting. "power = ckt.volts * ckt.amps" is a lot
>>easier to read and understand than "power = ckt[0] * ckt[1]".
>
>
> (the following applies most obviously to modern versions of python. I
> use subclassing of builtin objects, __slots__ and zip(). Even so, the
> myStruct class is useful in any version of Python back to at least 1.5,
> if you make myStruct a regular class, and include a definition
> of zip())
>
> You can do even better (lower memory overhead) with
> class myData(object):
> __slots__ = ['foo', 'bar']
> def __init__ (self, foo, bar):
> self.foo = foo
> self.bar = bar
You can also make it even more general:
class MyData:
def __init__(self, **args):
self.__dict__.update(args)
d = MyData(firstName='Max M', lastName='Rasmussen')
print d.firstName, d.lastName
>>> Max M Rasmussen
regards Max M
Exactly. I hardly ever use None to mean false, I tend to use it to mean,
well, "none", or nothing there, as it a value that is not defined yet or
doesn't exist.
> object model is that any "empty" object tests as false: None, 0, "", (),
> [], and {}.
That's part of the problem for me, when I am using numbers, 0 (or 0.0)
is as often as not a perfectly valid number, and should not be
interpreted as false. However as someone mentioned:
if x is None
is preferabale to
if x == None
What you want to know is whether x is bound to None so that's what you
should check for.
-Chris
--
Christopher Barker, Ph.D.
Oceanographer
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception
Interesting. That's an ActiveState bug, pure and simple; this.py is a
normal module in Lib/.
My preference is for
class MyData:
pass
d = MyData()
d.firstName = None
d.lastName = 'Aahz'
At the very least, I think you ought to rewrite your example as
d = MyData(
firstName = 'Max M',
lastName = 'Rasmussen
)
> At the very least, I think you ought to rewrite your example as
>
> d = MyData(
> firstName = 'Max M',
> lastName = 'Rasmussen
> )
I think rewriting it without the syntax error would be even better...
--
David Eppstein UC Irvine Dept. of Information & Computer Science
epps...@ics.uci.edu http://www.ics.uci.edu/~eppstein/
| This view is a overly extreme. Rather than teaching people to fear certain
| features like eval/exec, it's better to explain the risks so that they can
| make informed decisions as to when it's wise to use them.
It's not overly extreme! It's just about extreme enough.
| So... rather than teaching "avoid W!", let's say "be careful with W
| because of X, Y, and Z". I still wouldn't use eval/exec on code posted
| through a web form, for example, but there are times when they are very
| useful and I can use them in good confidence because I understand their
| risks.
But you weren't going to be deterred by that pronouncement anyway.
"Avoid exec, execfile, eval, and input" is good advice. Taken at face
value, it doesn't necessarily absolutely prohibit their use - if I said
"avoid walking in the road", you could reasonably reasonably assume I'm
saying something like "walk on the sidewalk when possible".
Someone whose software engineering skills have been honed by years
of wrestling with ugly code monsters will apply a different perspective
to that advice. A 1-week newbie could do worse than to follow that
advice religiously.
Donn Cave, do...@u.washington.edu
It's been fixed in the latest version.
-- bjorn
> | So... rather than teaching "avoid W!", let's say "be careful with W
> | because of X, Y, and Z". I still wouldn't use eval/exec on code posted
> | through a web form, for example, but there are times when they are very
> | useful and I can use them in good confidence because I understand their
> | risks.
>
> But you weren't going to be deterred by that pronouncement anyway.
>
> "Avoid exec, execfile, eval, and input" is good advice. Taken at face
> value, it doesn't necessarily absolutely prohibit their use - if I said
> "avoid walking in the road", you could reasonably reasonably assume I'm
> saying something like "walk on the sidewalk when possible".
If you mean the latter, say the latter. Neither newbies nor veterans have
to do any reading between the lines. Even better, say "walk on the
sidewalk when possible because ___".
> Someone whose software engineering skills have been honed by years
> of wrestling with ugly code monsters will apply a different perspective
> to that advice. A 1-week newbie could do worse than to follow that
> advice religiously.
I understand your point, but the OP is new to Python, not programming.
This isn't a big deal; I was simply pointing out that just saying "don't
use those!" (Why? Are they broken? Deprecated? What?) isn't as helpful as
explaining the risks.
In the specific case of exec/eval, people are quick to strike them down,
often citing the untrusted input example (what about os.system, .fork,
etc.?), but that's a pretty narrow and uncommon usage scenario. When I
first learned Python I used them in some of the "forbidden" ways because I
hadn't learned getattr/setattr yet. So what? My programs worked fine (a
little slow) and later I learned better ways and now use those instead.
If a person is new to programming altogether then what kind of a teacher
will draw attention to exec/eval in the first place anyway? Besides, the
people who understand the potential for problems with something tend to be
the ones that don't mishandle it (whether it be streets, guns, or Python
functions).
-Dave
>In article <mailman.102495153...@python.org>,
>David LeBlanc <whi...@oz.net> wrote:
>>Mark:
>>>
>>> When evaluating whether a variable is None, don't compare it like this:
>>>
>>> if x == None:
>>>
>>> instead, use:
>>>
>>> if x:
>>>
>>> or:
>>>
>>> if not x:
>>>
>>> The encourages a polymorphic approach. If you must compare to
>>> None, use the identify operator rather than equality:
>>>
>>> if x is None:
>>>
>>> or:
>>>
>>> if x is not None:
>>
>>I'm curious to know how this encourages polymorphism, and how making a
>>conditional test implicit rather then explicit is good practice?
>
>Depends on what you're testing for. One of the big features of Python's
>object model is that any "empty" object tests as false: None, 0, "", (),
>[], and {}. Testing for a specific false value (such as 0 or None)
>prevents you from easily changing the object being used. Rely on the
>object to tell you whether it's true or false, and you'll be fine.
>
>That's polymorphic.
This kind of usage seems common:
>>> def foo(x=None):
... if x: print "Aahz says we'll be fine with %s" % `x`
... else: print "But what about %s ?" % `x`
... if x is None: print "Here we know we were passed %s (maybe by default)" % `x`
...
>>> foo('something')
Aahz says we'll be fine with 'something'
>>> foo(0)
But what about 0 ?
>>> foo()
But what about None ?
Here we know we were passed None (maybe by default)
Do you recommend using def foo(*args) and testing len(args) instead?
Regards,
Bengt Richter
>They may be returned in a tuple, but they're PUT in discrete variables and
ITYM bound to discrete variable names
>not kept in a tuple that I have to programmatically unpack.
>
Right, it's programmatically done for you ;-)
>>> def foo(): return (1,2,3)
...
>>> a,b,c = foo()
>>> a
1
>>> b
2
>>> c
3
>>> import dis
>>> dis.dis(foo)
0 SET_LINENO 1
3 SET_LINENO 1
6 LOAD_CONST 1 (1)
9 LOAD_CONST 2 (2)
12 LOAD_CONST 3 (3)
15 BUILD_TUPLE 3
18 RETURN_VALUE
19 LOAD_CONST 0 (None)
22 RETURN_VALUE
>>> from miscutil import disex
>>> disex('a,b,c = foo()')
0 SET_LINENO 0
3 SET_LINENO 1
6 LOAD_NAME 0 (foo)
9 CALL_FUNCTION 0
12 UNPACK_SEQUENCE 3
15 STORE_NAME 1 (a)
18 STORE_NAME 2 (b)
21 STORE_NAME 3 (c)
24 LOAD_CONST 0 (None)
27 RETURN_VALUE
Note the "UNPACK_SEQUENCE" and "STORE_NAME"s.
>Language lawyer should be shot, _then_ heard.
Along with top-posters? ;-)
>
>David LeBlanc
>Seattle, WA USA
>
>> -----Original Message-----
>> From: python-l...@python.org
>> [mailto:python-l...@python.org]On Behalf Of Peter Hansen
>> Sent: Monday, June 24, 2002 18:03
>> To: pytho...@python.org
>> Subject: Re: Suggestions for good programming practices?
>>
>>
>> David LeBlanc wrote:
>> >
>> > The one that always gets me is "lat,lon,timezone =
>> getLocation("seattle")".
>> > I.E. the ability to return multiple distinct values as opposed
>> to returning
>> > multiple values in the form of a struct as in C or C++.
>>
>> You _are_ returning them "in a struct". It's spelled "tuple"
>> but other than that what's the difference?
>>
>> -Peter
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>
>
>
Regards,
Bengt Richter