Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Coding style

Reply
Thread Tools

Coding style

 
 
Erik Max Francis
Guest
Posts: n/a
 
      07-18-2006
tac-tics wrote:

> I'm well aware that both of these snippets does the same thing. I'm
> just spouting my opinion that lists and integers are not tests, ...


No, but testing their Boolean nature _is_ a test. Aggregate objects in
Python are true if they are non-empty, and false if they are empty.
That is reasonable, not uncommon a convention, and quite useful for
exactly the situations you were talking about. That convention exists
_so that_ writing::

if aContainer:
... container is not empty ...

is meaningful and convenient. So the answer to the original question
was, "The first one." Feel free to write it the other way with an
explicit test, but it's not Pythonic.

--
Erik Max Francis && && http://www.alcyone.com/max/
San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
Life is a toy made of glass; it appears to be of inestimable price,
but in reality it is very cheap. -- Pietro Aretino, 1537
 
Reply With Quote
 
 
 
 
Patrick Maupin
Guest
Posts: n/a
 
      07-18-2006
PTY wrote:

> It looks like there are two crowds, terse and verbose. I thought terse
> is perl style and verbose is python style. BTW, lst = [] was not what
> I was interested in I was asking whether it was better style to
> use len() or not.


It's not canonical Python to use len() in this case. From PEP 8:

- For sequences, (strings, lists, tuples), use the fact that empty
sequences are false.

Yes: if not seq:
if seq:

No: if len(seq)
if not len(seq)

The whole reason that a sequence supports testing is exactly for this
scenario. This is not an afterthought -- it's a fundamental design
decision of the language.

Regards,
Pat

 
Reply With Quote
 
 
 
 
Carl Banks
Guest
Posts: n/a
 
      07-18-2006

PTY wrote:
> Which is better?
>
> lst = [1,2,3,4,5]
>
> while lst:
> lst.pop()
>
> OR
>
> while len(lst) > 0:
> lst.pop()


I'm going to go against general opinion and suggest using "len(lst)>0",
though this is not a good example of why I think that.

In practice, I'd say the former is less generic. No, that's not a
typo.

If you were to write a function that expects a list (and actually uses
the list interface, indexing and such, rather than merely passing it
off to another function), the function would almost certainly fail if
you were to pass in an integer or some other non-sequence type.
However, functions expecting a list have a decent chance of working if
you were to pass in a numpy array.

But if you were to write "if lst" instead of "if len(lst)>0", then
you've just ensured your function will fail for numpy arrays. But you
get no benefit in genericity, because non-sequence types almost
certainly wouldn't work anyways.

Therefore, the only time I'd recommend using "if lst" is if all you're
doing is passing it to other functions.


Carl Banks

 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      07-18-2006

Patrick Maupin wrote:
> PTY wrote:
>
> > It looks like there are two crowds, terse and verbose. I thought terse
> > is perl style and verbose is python style. BTW, lst = [] was not what
> > I was interested in I was asking whether it was better style to
> > use len() or not.

>
> It's not canonical Python to use len() in this case. From PEP 8:
>
> - For sequences, (strings, lists, tuples), use the fact that empty
> sequences are false.
>
> Yes: if not seq:
> if seq:
>
> No: if len(seq)
> if not len(seq)
>
> The whole reason that a sequence supports testing is exactly for this
> scenario. This is not an afterthought -- it's a fundamental design
> decision of the language.


That might have made sense when Python and string, list, tuple were the
only sequence types around.

Nowadays, Python has all kinds of spiffy types like numpy arrays,
interators, generators, etc., for which "empty sequence is false" just
doesn't make sense. If Python had been designed with these types in
mind, I'm not sure "empty list is false" would have been part of the
language, let alone recommend practice.


Carl Banks

 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      07-18-2006
PTY wrote:
> Which is better?
>
> lst = [1,2,3,4,5]
>
> while lst:
> lst.pop()
>
> OR
>
> while len(lst) > 0:
> lst.pop()



Here's another reason not to use "if lst". Say you have a function
that looks like this:

def process_values(lst):
if not lst:
return
do_expensive_initialization_step()
for item in lst:
do_something_with(item)
do_expensive_finalization_step()

That works, right? No problem, right?

What if you called the function like this:

process_values(x.strip() for x in values_lst)

Oops, now we've just gone through an expensive initialization and
finalization for nothing (since values_lst was empty). Maybe some
subtle bugs introduced. If we're lucky, the finalization step will
throw an exception.

If we had used "if len(list)>0", we'd have gotten a nice exception
telling us that a generator is not welcome. Then we'd have changed the
argument to a list comprehension, or better, changed the function to
work for any iterator.


Carl Banks

 
Reply With Quote
 
Paul Rubin
Guest
Posts: n/a
 
      07-18-2006
"Carl Banks" <> writes:
> What if you called the function like this:
>
> process_values(x.strip() for x in values_lst)
>
> Oops, now we've just gone through an expensive initialization and
> finalization for nothing (since values_lst was empty). Maybe some
> subtle bugs introduced. If we're lucky, the finalization step will
> throw an exception.


You've got a function written to take a list arg and are passing it
something other than a list. Why do you expect it to work?
As soon as the function uses lst[3] for something, it will crash
if you pass it a sequence like that. Your example is mainly an
argument for static type checking.
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      07-18-2006
Paul Rubin wrote:
> "Carl Banks" <> writes:
> > What if you called the function like this:
> >
> > process_values(x.strip() for x in values_lst)
> >
> > Oops, now we've just gone through an expensive initialization and
> > finalization for nothing (since values_lst was empty). Maybe some
> > subtle bugs introduced. If we're lucky, the finalization step will
> > throw an exception.

>
> You've got a function written to take a list arg and are passing it
> something other than a list. Why do you expect it to work?


I don't expect it to work as is. Disregarding the test for emptiness
at the beginning, I would expect it to work for any iterable, even if
the author only intended it for a list. That's the problem: it looks
like it should work for any iterable, but it doesn't. I would think
it's a pretty easy mistake to make. (I suspect lots of programmers
don't even realize that empty generator expressions are true. Even if
they do, it's easy to overlook that test if you're not careful.)

> As soon as the function uses lst[3] for something,


Notice that the function I wrote never indexes the list. It only
iterates.

> it will crash
> if you pass it a sequence like that.


The particular function I wrote might crash. Or it might merely do
unnecessary work. Or it might have subtle bugs. (OTOH, if it had used
the "if len(lst)>0", it would crash right away; no subtle bugs.)

> Your example is mainly an
> argument for static type checking.


Not really. I'm merely putting forth one argument for using "if
len(lst)>0" rather than "if lst". ISTM the scenerio I described isn't
terribly rare: you write a function that iterates over an iterable, and
carelessly use a test ("if lst") that doesn't work for all iterables,
and the result could lead to subtle bugs. Which is not as bad as
carelessly using a test ("if len(lst)>0") that doesn't work for all
iterables, and the result is an immediate exception.

I've given two pretty good reasons for using "if len(lst)>0": it allows
functions to be written generically for lists and numpy arrays, and it
catches the rather plausible mistake of testing the truth value an
iterable (which can lead to subtle bugs). This is contrasted to the
good reasons for using "if lst", which are... um... hmm... saving a few
keystrokes?


Carl Banks

 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      07-18-2006
Carl Banks wrote:

> ****def*process_values(lst):
> ********if*not*lst:
> ************return
> ********do_expensive_initialization_step()
> ********for*item*in*lst:
> ************do_something_with(item)
> ********do_expensive_finalization_step()


> What if you called the function like this:
>
> ****process_values(x.strip()*for*x*in*values_lst)
>
> Oops, now we've just gone through an expensive initialization and
> finalization for nothing (since values_lst was empty).**Maybe*some
> subtle bugs introduced.**If*we're*lucky,*the*finalization*step*will
> throw an exception.


The good news is that the above has a 99 percent chance that it just works
with iterators/generators -- even though the writer may not have been aware
of them/they didn't exist when the code was written...

Peter
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      07-18-2006

Peter Otten wrote:
> Carl Banks wrote:
>
> > def process_values(lst):
> > if not lst:
> > return
> > do_expensive_initialization_step()
> > for item in lst:
> > do_something_with(item)
> > do_expensive_finalization_step()

>
> > What if you called the function like this:
> >
> > process_values(x.strip() for x in values_lst)
> >
> > Oops, now we've just gone through an expensive initialization and
> > finalization for nothing (since values_lst was empty). Maybe some
> > subtle bugs introduced. If we're lucky, the finalization step will
> > throw an exception.

>
> The good news is that the above has a 99 percent chance that it just works
> with iterators/generators -- even though the writer may not have been aware
> of them/they didn't exist when the code was written...


There's a litmus test I like to use when justifying something with
percentages: I imagine that I'm presenting it to my boss, and ask
myself if I still expect to have a job the next day.

Yes, I agree with you, it most cases I expect merely unnecessary work.
(Which is not the best news; the best news would be an exception right
away.) That's why I think this is only a "pretty good" reason to use
"if len(lst)>0", not a slam dunk.


Carl Banks

 
Reply With Quote
 
Steve Holden
Guest
Posts: n/a
 
      07-18-2006
tac-tics wrote:
> dwelch91 wrote:
>
>>tac-tics wrote:
>>
>>>I'd say the second one. Empty lists are not false. They are empty. Long
>>>live dedicated boolean data types.
>>>

>>
>>Uh, no, empty lists are False in a boolean context:
>>
>>http://docs.python.org/lib/truth.html
>>
>>-Don

>
>
> Perhaps I should have specified it like this:
>
>
>>>>empty_list = []
>>>>empty_list is not False

>
> True
>
> I'm well aware that both of these snippets does the same thing. I'm
> just spouting my opinion that lists and integers are not tests, and in
> an ideal world (Java??? X-) if statements support only boolean types.
>
> DISCLAIMER: I do not promote the use of Java.
>

You don't promote use of Python either if you deliberately ignore
programming paradigms that have stood the test of time. Under what set
of rules could it make sense to test a list for equality with a Boolean
value (note also that capital "B": the word is based on someone's name).

The

if lst:

metaphor is so well established as a means of guarding statements that
should be executed only when there are elements in the list (or other
container, come to that), promoting any other way to perform the test
will only lead to confusion: there should be one (and preferably only
one) obvious way to do it.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
general coding issues - coding style... calmar Python 11 02-21-2006 10:36 AM
Coding style for CPLD vs FPGA Analog Guy VHDL 3 03-14-2005 08:26 AM
Need help with Style conversion from Style object to Style key/value collection. Ken Varn ASP .Net Building Controls 0 04-26-2004 07:06 PM
Coding style to prioritize certain inputs Willem Oosthuizen VHDL 5 09-04-2003 05:17 PM
style for coding latches Paul Baxter VHDL 7 08-15-2003 06:19 PM



Advertisments