niXforums Forum Index
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   PreferencesPreferences   Log in to check your private messagesLog in to check your private messages   Log inLog in 
·  nixdoc.net ·  man pages ·  Linux HOWTOs ·  FreeBSD Tips ·  Forums
navigation Forum index » Programming » python
Coding style
Post new topic   Reply to topic Page 4 of 6 [86 Posts] View previous topic :: View next topic
Goto page:  Previous  1, 2, 3, 4, 5, 6 Next
Author Message
Donn Cave
*nix forums Guru Wannabe


Joined: 20 Feb 2005
Posts: 172

PostPosted: Tue Jul 18, 2006 5:07 pm    Post subject: Re: Coding style Reply with quote

In article <1153232735.118387.12130@75g2000cwc.googlegroups.com>,
"Carl Banks" <pavlovevidence@gmail.com> wrote:

Quote:
1. This is fine in a perfect world where all code clearly conforms to
expectation. Problem is, a lot doesn't. I think it's quite easy to
accidentally check something intended as an iterable for emptiness.
And, as I've explained in other posts, this can lead to subtle bugs.
Whereas if you check for emptiness using len, it throws an exception
right away, no bugs. It's safer to use len. (Safest of all is not to
check for emptiness at all.)

Yes, it's clearly more direct to catch IndexError, than to
try to anticipate it.

Donn Cave, donn@u.washington.edu
Back to top
Volker Grabsch
*nix forums beginner


Joined: 14 May 2005
Posts: 19

PostPosted: Tue Jul 18, 2006 5:09 pm    Post subject: Re: Coding style Reply with quote

Bruno Desthuilliers <onurb@xiludom.gro> schrieb:
Quote:
PTY wrote:
I was asking whether it was better style to
use len() or not.

FWIW, it's also more generic (you could have an object supporting
pop() but not __len__()), less error-prone,

While I agree with all other points, I don't think that it's less
error-prone. See my other posting where I worked out this a flaw
of Python.


Greets,

Volker

--
Volker Grabsch
---<<(())>>---
Administrator
NotJustHosting GbR
Back to top
Patrick Maupin
*nix forums beginner


Joined: 23 Jun 2005
Posts: 32

PostPosted: Tue Jul 18, 2006 7:57 pm    Post subject: Re: Coding style Reply with quote

Daniel Dittmar wrote:
Quote:

Premature generalization: the new 'premature optimization'.

Premature specialization: the new 'static typing'.

-- Pat
Back to top
David M. Cooke
*nix forums beginner


Joined: 03 Mar 2005
Posts: 29

PostPosted: Tue Jul 18, 2006 8:49 pm    Post subject: Re: Coding style Reply with quote

"Carl Banks" <pavlovevidence@gmail.com> writes:

Quote:
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 Smile 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.

Bruno's already mentioned that iterators and generators aren't
sequences. Numpy arrays act like the other sequence types:

Quote:
a = numpy.array([])
a
array([], dtype=int64)
len(a)
0
bool(a)
False


(0-dimensional numpy arrays are pathological anyways)

--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
Back to top
David M. Cooke
*nix forums beginner


Joined: 03 Mar 2005
Posts: 29

PostPosted: Tue Jul 18, 2006 8:58 pm    Post subject: Re: Coding style Reply with quote

cookedm+news@physics.mcmaster.ca (David M. Cooke) writes:
Quote:

Bruno's already mentioned that iterators and generators aren't
sequences. Numpy arrays act like the other sequence types:

a = numpy.array([])
a
array([], dtype=int64)
len(a)
0
bool(a)
False

(0-dimensional numpy arrays are pathological anyways)

*cough* as a Numpy developer I should know better. Numpy arrays that
have more than one element don't work in a boolean context:

Quote:
a = numpy.array([1,2])
bool(a)
Traceback (most recent call last):

File "<stdin>", line 1, in ?
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The reason for this is that it really was a common source of errors,
because of the rich comparision semantics used. If a and b are numpy
arrays, 'a == b' is an array of booleans.

Numpy arrays of one element act like scalars in boolean contexts:

Quote:
a = numpy.array([0])
bool(a)
False
a = numpy.array([1])
bool(a)
True


(this is partly because we define a comphensive hierarchy of scalar
types to match those available in C).

--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
Back to top
bearophileHUGS@lycos.com
*nix forums Guru Wannabe


Joined: 19 Feb 2005
Posts: 198

PostPosted: Tue Jul 18, 2006 9:23 pm    Post subject: Re: Coding style Reply with quote

Volker Grabsch wrote:
Quote:
IMHO, that flaw of Python should be documented in a PEP as it violates
Python's priciple of beeing explicit. It also harms duck typing.

I think this may be good food for Python 3.0, the are removing
undefined comparisons too (>), etc.

bye,
bearophile
Back to top
Bruno Desthuilliers
*nix forums Guru


Joined: 03 Mar 2005
Posts: 360

PostPosted: Tue Jul 18, 2006 10:52 pm    Post subject: Re: Coding style Reply with quote

Volker Grabsch a écrit :
Quote:
Bruno Desthuilliers <onurb@xiludom.gro> schrieb:

Carl Banks wrote:

Bruno Desthuilliers wrote:

I'm well aware of Python's semantics, and it's irrelvant to my
argument.

[...]

If the language
were designed differently, then the rules would be different.

Totally true - and totally irrelevant IMHO.


I strongly advise not to treat each others thoughts as irrelevant.
Assuming the opposite is a base of every public dicussion forum.

"Irrelevant" may not be the best expression of my thought here - it's
just that Carl's assertion is kind of a tautology and doesn't add
anything to the discussion. If Python had been designed as statically
typed (with declarative typing), the rules would be different. Yeah,
great. And now ?

Quote:
I assume here is a flaw in Python. To explain this, I'd like to
make Bruno's point

Actually Carl's point, not mine.

Quote:
clearer. As usually, code tells more then
thousand words (an vice versa Smile).

Suppose you have two functions which somehow depend on the emptyness
of a sequence. This is a stupid example, but it demonstrates at
least the two proposed programming styles:

------------------------------------------------------

def test1(x):

... if x:
... print "Non-Empty"
... else:
... print "Empty"
...

def test2(x):

... if len(x) > 0:
... print "Non-Empty"
... else:
... print "Empty"
------------------------------------------------------

Bruno

Carl

Quote:
pointed out a subtle difference in the behaviour of those
functions:

------------------------------------------------------

a = []
test1(a)

Empty

test1(iter(a))

Non-Empty

test2(a)

Empty

test2(iter(a))

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in test2
TypeError: len() of unsized object
------------------------------------------------------


While test1() returns a wrong/random result when called with an
iterator, the test2() function breaks when beeing called wrongly.

Have you tried these functions with a numpy array ?

Quote:
So if you accidently call test1() with an iterator, the program
will do something unintended, and the source of that bug will be
hard to find. So Bruno is IMHO right in calling that the source
of a suptle bug.

Actually it's Carl who makes that point - MHO being that it's a
programmer error to call a function with a param of the wrong type.

Quote:
However, if you call test2() with an iterator, the program will
cleanly break early enough with an exception. That is generally
wanted in Python. You can see this all over the language, e.g.
with dictionaries:

------------------------------------------------------

d = { 'one': 1 }
print d['one']

1

print d['two']

Traceback (most recent call last):
File "<stdin>", line 1, in ?
KeyError: 'two'
------------------------------------------------------

Python could have been designed to return None when d['two'] has been
called, as some other (bad) programming languages would. This would
mean that the problem will occur later in the program, making it easy
to produce a subtle bug. It would be some effort to figure out the
real cause, i.e. that d had no entry for 'two'.

I don't think the comparison is right. The equivalent situation would be
to have a function trying to access d['two'] on a dict-like type that
would return a default value instead of raising a KeyError.

Quote:
Luckily, Python throws an exception (KeyError) just at the original
place where the initial mistake occured. If you *want* to get None in
case of a missing key, you'll have to say this explicitly:

------------------------------------------------------

print d.get('two', None)

None
------------------------------------------------------

So maybe "bool()" should also break with an exception if an object
has neither a __nonzero__ nor a __len__ method, instead of defaulting
to True.

FWIW, Carl's main example is with numpy arrays, that have *both* methods
- __nonzero__ raising an expression.

Quote:
Or a more strict variant of bool() called nonempty() should
exist.

Iterators don't have a meaningful Boolean representation,
because
phrases like "is zero" or "is empty" don't make sense for them.

If so, almost no type actually has a "meaningfull" boolean value. I'd
rather say that iterators being unsized, the mere concept of an "empty"
iterator has no meaning.

Quote:
So
instead of answering "false", an iterator should throw an exception
when beeing asked whether he's empty.



Quote:
If a function expects an object to have a certain protocol (e.g.
sequence), and the given object doesn't support that protocol,
an exception should be raised.

So you advocate static typing ? Note that numpy arrays actually have
both __len__ and __nonzero__ defined, the second being defined to
forgive boolean coercion...

Quote:
This usually happens automatically
when the function calls a non-existing method, and it plays very
well with duck typing.

test2() behaves that way, but test1() doesn't. The reason is a
sluttery of Python. Python should handle that problem as strict
as it handles a missing key in a dictionary. Unfortunately, it
doesn't.

Then proceed to write a PEP proposing that evaluating the truth value of
an iterator would raise a TypeError. Just like numpy arrays do - as a
decision of it's authors.

Quote:
I don't agree with Bruno

s/bruno/Carl/

Quote:
that it's more natural to write
if len(a) > 0:
...
instead of
if a:
...

But I think that this is a necessary kludge you need to write
clean code. Otherwise you risk to create subtle bugs.

s/you risk to create/careless programmers will have to face/

And FWIW, this is clearly not the opinion of numpy authors, who state
that having len > 0 doesn't means the array is "not empty"...

Quote:
This advise,
however, only applies when your function wants a sequence, because
only in that can expect "len(a)" to work.

Since sequence types are defined as having a False value when empty,
this test is redondant *and* "will create subtle bugs" when applied to a
numpy array.

Quote:
I also agree with Carl that "if len(a) > 0" is less universal than
"if a", because the latter also works with container-like objects
that have a concept of emptiness,

s/emptiness/boolean value/

Quote:
but not of length.

However, this case is less likely to happen than shooting yourself
in the foot by passing accidently an iterator to the function
without getting an exception. I think, this flaw in Python is deep
enough to justify the "len() > 0" kludge.

It surely justify some thinking on the boolean value of iterators. Since
the common idiom for testing non-None objects is an explicit identity
test against None - which makes sens since empty sequences and zero
numerics eval to False in a boolean context - the less inappropriate
solution would be to have iterators implementing __nonzero__ like numpy
arrays do.

Quote:

IMHO, that flaw of Python should be documented in a PEP as it violates
Python's priciple of beeing explicit.

Here again, while I agree that there's room for improvement, I don't
agree on this behaviour being a "flaw" - "minor wart" would better
describe the situation IMHO.
Back to top
Bruno Desthuilliers
*nix forums Guru


Joined: 03 Mar 2005
Posts: 360

PostPosted: Tue Jul 18, 2006 10:52 pm    Post subject: Re: Coding style Reply with quote

Volker Grabsch a écrit :
Quote:
Bruno Desthuilliers <onurb@xiludom.gro> schrieb:

PTY wrote:

I was asking whether it was better style to
use len() or not.

FWIW, it's also more generic (you could have an object supporting
pop() but not __len__()), less error-prone,


While I agree with all other points, I don't think that it's less
error-prone.

There are less risk of a typo with "if a:" than with "if len(a) > 0".

Quote:
See my other posting where I worked out this a flaw
of Python.

See my answer where I don't agree on this being a "flaw" - a "minor
wart" at most !-)
Back to top
pavlovevidence@gmail.com
*nix forums beginner


Joined: 17 Jul 2006
Posts: 17

PostPosted: Tue Jul 18, 2006 11:25 pm    Post subject: Re: Coding style Reply with quote

Bruno Desthuilliers wrote:
Quote:
"Irrelevant" may not be the best expression of my thought here - it's
just that Carl's assertion is kind of a tautology and doesn't add
anything to the discussion. If Python had been designed as statically
typed (with declarative typing), the rules would be different. Yeah,
great. And now ?

I was answering someone who said you should use "if lst" because PEP 8
says to. I proposed that the PEP might be outdated here, and gave
reasons why I think it would be different if it were written today. (I
also, regrettably, implied the language might have been designed
differently.) This all might be irrelevant to you, but it's relevant
to the original question of whether that clause of PEP 8 is outdated.
I think it is.

BTW, I'm still waiting for anyone to come up with a real benefit of the
"if lst" test. I have yet to see a good reason than non-answer
cop-outs "it's Pythonic", "it's stood the test of time", and "it's in
PEP 8". "It's standard idiom" is about the best I've seen, and that's
pretty weak. "Saving a few keystrokes" is, as always, not a good
reason.


Carl Banks
Back to top
pavlovevidence@gmail.com
*nix forums beginner


Joined: 17 Jul 2006
Posts: 17

PostPosted: Tue Jul 18, 2006 11:27 pm    Post subject: Re: Coding style Reply with quote

Bruno Desthuilliers wrote:
Quote:
There are less risk of a typo with "if a:" than with "if len(a) > 0".

So, it's more important to protect against typos than subtle bugs?


Carl Banks
Back to top
Bruno Desthuilliers
*nix forums Guru


Joined: 03 Mar 2005
Posts: 360

PostPosted: Wed Jul 19, 2006 12:51 am    Post subject: Re: Coding style Reply with quote

Carl Banks a écrit :
Quote:
Bruno Desthuilliers wrote:

There are less risk of a typo with "if a:" than with "if len(a) > 0".


So, it's more important to protect against typos than subtle bugs?


People making smart points are really annoying... !-)

wrt/ to the "subtle bug" point, MHO is that a better solution could be
to have iterators/generators implement __nonzero__ the same way numpy
arrays do. It may not be a very strong argument, but I actually like the
fact that empty sequences eval to false just like numeric zeros and None...
Back to top
pavlovevidence@gmail.com
*nix forums beginner


Joined: 17 Jul 2006
Posts: 17

PostPosted: Wed Jul 19, 2006 1:40 am    Post subject: Re: Coding style Reply with quote

Bruno Desthuilliers wrote:
Quote:
Carl Banks a écrit :
Bruno Desthuilliers wrote:

There are less risk of a typo with "if a:" than with "if len(a) > 0".


So, it's more important to protect against typos than subtle bugs?


People making smart points are really annoying... !-)

wrt/ to the "subtle bug" point, MHO is that a better solution could be
to have iterators/generators implement __nonzero__ the same way numpy
arrays do. It may not be a very strong argument, but I actually like the
fact that empty sequences eval to false just like numeric zeros and None....

Well, I certainly can agree with that, except for the last point. Smile I
certainly wouldn't want to keep that unfortunate behavior around just I
have something to use as an argument using len to test emptiness.


Carl Banks
Back to top
Jorge Godoy
*nix forums Guru Wannabe


Joined: 28 Feb 2005
Posts: 144

PostPosted: Wed Jul 19, 2006 1:54 am    Post subject: Re: Coding style Reply with quote

"Carl Banks" <pavlovevidence@gmail.com> writes:

Quote:
Well, I certainly can agree with that, except for the last point. Smile I
certainly wouldn't want to keep that unfortunate behavior around just I
have something to use as an argument using len to test emptiness.

On the other hand, having this behavior makes it so simple to deal with some
algorithms because on doesn't need to know if the given object does or does
not support len()...

Having to test if something is of certain type then choosing what kind of test
to apply is not something I'd like to have to do all the time.

--
Jorge Godoy <jgodoy@gmail.com>
Back to top
Terry Reedy
*nix forums Guru


Joined: 21 Feb 2005
Posts: 544

PostPosted: Wed Jul 19, 2006 2:24 am    Post subject: Re: Coding style Reply with quote

"Patrick Maupin" <pmaupin@gmail.com> wrote in message
news:1153240327.611631.76600@h48g2000cwc.googlegroups.com...
Quote:

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)

The perverse wish, expressed in the specific example, that SOME piece
of code SOMEWHERE should PLEASE throw an exception because some idiot
passed a generator expression rather than a list into a function, is
not apt to be well received by an audience which strives for generality
when it makes sense; and I daresay most members of that audience, if
confronted with the wished-for exception, would fix the function so
that it quite happily accepted generator expressions, rather than
changing a conditional to use len() just so that an equivalent
exception could happen a bit earlier.

Given that the input is going to be scanned by an iterator, it really makes
sense to me to accept an iterator as input. (Unless the function is for
special-case usage in a predefined, never to be expanded, set of
circumstances in which such generality is not needed. In such a case, if
lst: is no problem.) I think the following, untested rewrite suffices.

def process_values(lst):
it = iter(lst)
try:
item = it.next()
do_expensive_initialization_step()
do_something_with(item) # see note
for item in it:
do_something_with(item)
do_expensive_finalization_step()
except StopIteration:
pass # or any special empty input code

# note: if writing do_something_with(item) is bothersome,
# replace 3 lines with
while True:
do_something_with(item)
try:
item = it.next
except StopIteration:
break

In general, to work with iterators instead of containers, change

if container:
do_stuff()
else:
do_empty()

to

try:
item = it.next()
do_modified_stuff() # taking into account that have item already
except StopIteration:
do_empty()

Guido has so far vetoed adding .__len__() to the iterator protocol because
a) it is not always possible and b) he want to keep the protocol as simple
as it is.

Terry Jan Reedy
Back to top
pavlovevidence@gmail.com
*nix forums beginner


Joined: 17 Jul 2006
Posts: 17

PostPosted: Wed Jul 19, 2006 2:35 am    Post subject: Re: Coding style Reply with quote

Jorge Godoy wrote:
Quote:
"Carl Banks" <pavlovevidence@gmail.com> writes:

Well, I certainly can agree with that, except for the last point. Smile I
certainly wouldn't want to keep that unfortunate behavior around just I
have something to use as an argument using len to test emptiness.

On the other hand, having this behavior makes it so simple to deal with some
algorithms because on doesn't need to know if the given object does or does
not support len()...

First of all, the unfortunate behavior I was referring to was the fact
that iterables that have unknown length are true in a boolean context,
even if they happen to be empty. Bruno and I had a disagreement over
whether this should also be a wart for lists and such, but I think we
agree that it would be better generators and other iterators raised an
exception in a boolean context.

Getting back to your reply--can you give an example of a useful
function that needs to do what you want? (Let's disregard iterators
and arrays for now, and focus on older Python types like lists, tuples,
strings, integers, floats, None, etc.) Can you give me an example of a
useful function that needs to test the truth value of an object, but
that can't rely on it having a length?

The only example I can think of here is a function that does nothing
with an object except pass it to other functions. Almost anything else
you do with an object pigeonholes it as a sequence or atomic type:
you've already assumed whether it has a length or not.


Carl Banks
Back to top
Google

Back to top
Display posts from previous:   
Post new topic   Reply to topic Page 4 of 6 [86 Posts] Goto page:  Previous  1, 2, 3, 4, 5, 6 Next
View previous topic :: View next topic
The time now is Fri Nov 21, 2008 1:02 pm | All times are GMT
navigation Forum index » Programming » python
Jump to:  

Similar Topics
Topic Author Forum Replies Last Post
No new posts Coding standard Carlos Martinez C++ 7 Wed Jul 19, 2006 11:48 am
No new posts registering class methods as C style callbacks noone@all.com C++ 11 Mon Jul 17, 2006 5:35 pm
No new posts Need Help with a PHP Coding Issue Brent PHP 4 Sun Jul 16, 2006 5:09 pm
No new posts Bug#378289: ITP: sigma-align -- Simple greedy multiple al... Charles Plessy devel 0 Sat Jul 15, 2006 3:00 am
No new posts Version control philosophy and style JDS PHP 4 Fri Jul 14, 2006 7:55 pm

MySpace Images | Xbox Mod Chip | Loans | ModernForums | Books
Copyright © 2004-2005 DeniX Solutions SRL
 
Other DeniX Solutions sites: Unix/Linux blog |  electronics forum |  medicine forum |  science forum | 
Privacy Policy


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.4423s ][ Queries: 16 (0.2681s) ][ GZIP on - Debug on ]