By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,627 Members | 1,211 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,627 IT Pros & Developers. It's quick & easy.

which is more 'pythonic' / 'better' ?

P: n/a
hi,

there are 2 versions of a simple code.
which is preferred?
===
if len(line) >= (n+1):
text = line[n]
else:
text = 'nothing'
===
===
try:
text = line[n]
except IndexError:
text = 'nothing'
===
which is the one you would use?

thanks,
gabor
Sep 12 '05 #1
Share this Question
Share on Google+
15 Replies


P: n/a
On Mon, 12 Sep 2005 12:52:52 +0200, gabor wrote:
hi,

there are 2 versions of a simple code.
which is preferred?
===
if len(line) >= (n+1):
text = line[n]
else:
text = 'nothing'
===
===
try:
text = line[n]
except IndexError:
text = 'nothing'
===
which is the one you would use?


Personally, I would use either. You say po-ta-to, I say pot-at-o.

try...except... blocks are quick to set up, but slow to catch the
exception. If you expect that most of your attempts will succeed, then the
try block will usually be faster than testing the length of the list
each time.

But if you expect that the attempts to write the line will fail more
frequently, then testing will be quicker.

You will need to do your own testing before hand to find the exact
cut-off, and expect that cut-off to vary according to the Python
implementation and version. But a rough rule of thumb is, if you expect
your code to fail more often than succeed, then test first, otherwise
catch an exception.

--
Steven.

Sep 12 '05 #2

P: n/a
gabor wrote:
hi,

there are 2 versions of a simple code.
which is preferred?
===
if len(line) >= (n+1):
text = line[n]
else:
text = 'nothing'
===
===
try:
text = line[n]
except IndexError:
text = 'nothing'
===
which is the one you would use?


I would actualy use the following for this particular case..

text = line[n:n+1] or 'nothing'

But in general I think it is best to use exceptions like that only where
you expect the code to _not_ throw the exception the majority of
times. Otherwise the simple condition is better. Although I expect there
is not much difference either way..
Will McGugan
--
http://www.kelpiesoft.com
Sep 12 '05 #3

P: n/a
Will McGugan a écrit :
gabor wrote:
hi,

there are 2 versions of a simple code.
which is preferred?
===
if len(line) >= (n+1):
text = line[n]
else:
text = 'nothing'
===
===
try:
text = line[n]
except IndexError:
text = 'nothing'
===
which is the one you would use?

I would actualy use the following for this particular case..

text = line[n:n+1] or 'nothing'


.... and you would get either a list of one element or a string ...
I think you wanted to write :

text = (line[n:n+1] or ['nothing'])[0]

However, I wouldn't use that because it is hard to read ... you have to
know Python in great detail to know that:

1 - is the expressions "line[i:j]", i and j are replaced with
"len(line)" if they are greater than "len(line)"
2 - so if n > len(line), then line[n:n+1]" == len[len(line):len(line)]
== []
(it is not evident that line[n:n+1] can give an empty list ...)
3 - empty list evaluate to "False"
4 - the "or" operator returns the first argument evaluating to "true"

So, in the end, you use 3 side-effects of Python in the same small
expression ... (1, 2 and 4)

But in general I think it is best to use exceptions like that only where
you expect the code to _not_ throw the exception the majority of times.
Otherwise the simple condition is better. Although I expect there is not
much difference either way..
Will McGugan
--
http://www.kelpiesoft.com


What I would do is the following:
- if this happen in a loop, I would, if possible, remove any test and
catch the exception outside the loop !
- otherwise, I would go for the test, as it is more straitforward to read.

Pierre
Sep 12 '05 #4

P: n/a
Pierre Barbier de Reuille wrote:

I would actualy use the following for this particular case..

text = line[n:n+1] or 'nothing'

... and you would get either a list of one element or a string ...
I think you wanted to write :

text = (line[n:n+1] or ['nothing'])[0]


I was assuming that 'line' would be a string, not a list. Seems more
likely give the name and context.

Will McGugan
--
http://www.kelpiesoft.com
Sep 12 '05 #5

P: n/a
Steven D'Aprano wrote:
try...except... blocks are quick to set up, but slow to catch the
exception. If you expect that most of your attempts will succeed, then the
try block will usually be faster than testing the length of the list
each time.

But if you expect that the attempts to write the line will fail more
frequently, then testing will be quicker.

You will need to do your own testing before hand to find the exact
cut-off, and expect that cut-off to vary according to the Python
implementation and version. But a rough rule of thumb is, if you expect
your code to fail more often than succeed, then test first, otherwise
catch an exception.


FWIW, these are almost exactly my criteria too. Exceptions are for
"exceptional" conditions, that is, things that you expect to happen
infrequently[1]. So if I think the code is going to fail frequently, I
test the condition, but if I think it won't, I use exceptions.

STeVe

[1] Note though that what is "infrequent" in Python might be still
considered "frequent" in other languages. For example, Java's iterators
check the result of a .hasNext() method before each .next() call, while
Python's iterators assume the .next() call will succeed, and simply test
for the "exceptional" condition of a StopIteration exception.
Sep 12 '05 #6

P: n/a
Will McGugan wrote:
Pierre Barbier de Reuille wrote:

I would actualy use the following for this particular case..

text = line[n:n+1] or 'nothing'

... and you would get either a list of one element or a string ...
I think you wanted to write :

text = (line[n:n+1] or ['nothing'])[0]

I was assuming that 'line' would be a string, not a list. Seems more
likely give the name and context.

I'd say it's much more likely that line is a list of lines, since it
seems improbable that absence of a character should cause a value of
"nothing" to be required.

so-i-say-po-tay-to-ly y'rs - steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Sep 12 '05 #7

P: n/a
Steven Bethard wrote:
Exceptions are for
"exceptional" conditions, that is, things that you expect to happen
infrequently[1]. So if I think the code is going to fail frequently, I
test the condition, but if I think it won't, I use exceptions.


I think there exceptions (no pun intended) to that rule as well. A
classic example is writing to a file. Even if you expect this to be
impossible, it's best to just create it and trap the exception, thereby
avoiding a race condition.
--
Michael Hoffman
Sep 12 '05 #8

P: n/a
Steve Holden wrote:
I'd say it's much more likely that line is a list of lines, since it
seems improbable that absence of a character should cause a value of
"nothing" to be required.


You may be right. I always use plural nouns for collections. To me
'line' would suggest there was just one of them, so I assumed it was string.
Will McGugan
--
http://www.willmcgugan.com
"".join({'*':'@','^':'.'}.get(c,0) or chr(97+(ord(c)-84)%26) for c in
"jvyy*jvyyzpthtna^pbz")
Sep 12 '05 #9

P: n/a

"Will McGugan" <ne**@NOwillmcguganSPAM.com> wrote in message
news:43*********************@news.zen.co.uk...
You may be right. I always use plural nouns for collections.
ditto To me 'line' would suggest there was just one of them,
so I assumed it was string.


I did too.

for line in file('skljflask.txt',r): # or similar

is a common idiom posted here many times.

Terry J. Reedy

Sep 13 '05 #10

P: n/a
Terry Reedy wrote:
"Will McGugan" <ne**@NOwillmcguganSPAM.com> wrote in message
news:43*********************@news.zen.co.uk...
You may be right. I always use plural nouns for collections.

ditto
To me 'line' would suggest there was just one of them,
so I assumed it was string.

I did too.


i'm sorry ;) it was a list of strings...

the code was something like:

for line in open('x.y'):
line = line.split('\t')
a better naming would be better it seems :)

gabor
Sep 13 '05 #11

P: n/a

"gabor" <ga***@nekomancer.net> wrote in message
news:43***************************@news.flashnewsg roups.com...
i'm sorry ;) it was a list of strings...

the code was something like:

for line in open('x.y'):
line = line.split('\t')

a better naming would be better it seems :)


Like 'fields', for a list of fields ;-?

Or your question could have either included the code above or simply
specified what 'line' was. Asking clear questions is a learning process.

Terry J. Reedy

Sep 13 '05 #12

P: n/a
Will McGugan wrote:
gabor wrote:
hi,

there are 2 versions of a simple code.
which is preferred?
===
if len(line) >= (n+1):
text = line[n]
else:
text = 'nothing'
===
===
try:
text = line[n]
except IndexError:
text = 'nothing'
===
which is the one you would use?

I would actualy use the following for this particular case..

text = line[n:n+1] or 'nothing'

But in general I think it is best to use exceptions like that only where
you expect the code to _not_ throw the exception the majority of times.
Otherwise the simple condition is better. Although I expect there is not
much difference either way..
Will McGugan
--
http://www.kelpiesoft.com


Hey are you a perl programmer? That looks perlish to me. A python
programmer would never use "or" that way (even though it works). :)

It's okay, I used to be a perl programmer too. It's nothing to be
ashamed of. :)

- Ken

Sep 13 '05 #13

P: n/a
Ken Seehart wrote:
Will McGugan wrote:
I would actualy use the following for this particular case..

text = line[n:n+1] or 'nothing'
Hey are you a perl programmer? That looks perlish to me. A python
programmer would never use "or" that way (even though it works). :)
I don't think that's at all true. The pattern "somevalue or default" is
an accepted idiom for returning a default value when "somevalue" is
False, often used inside __init__ methods to set up attributes. A most
common case is like this (inside a class obviously):

def meth(self, things=None):
self.things = things or []

(The reason you don't just use a keyword argument of "things=[]" should
be obvious to all but newbies, and they'll learn a lot by researching
why so I won't say here. ;-) )

The alternative is fine too, but insisting on it would be pedantic, and
if you have more than one of these it is definitely less readable (and,
therefore, not Pythonic):

def meth(self, things=None):
if things:
self.things = things
else:
self.things = []
It's okay, I used to be a perl programmer too. It's nothing to be
ashamed of. :)


Ah, now I would disagree with that as well! ;-)

-Peter
Sep 13 '05 #14

P: n/a
Peter Hansen wrote:
def meth(self, things=None):
self.things = things or []
[snip]
The alternative is fine too, but insisting on it would be pedantic, and
if you have more than one of these it is definitely less readable (and,
therefore, not Pythonic):

def meth(self, things=None):
if things:
self.things = things
else:
self.things = []


Probably worth pointing out that there is at least one more alternative:

def meth(self, things=None):
if things is None:
things = []
self.things = things

I usually opt for this one, mainly because "things or []" makes me
nervous -- it has different behavior if the user passes in an empty list:

py> class Things1(object):
.... def __init__(self, things=None):
.... if things is None:
.... things = []
.... self.things = things
....
py> class Things2(object):
.... def __init__(self, things=None):
.... self.things = things or []
....
py> lst = []
py> thing = Things1(lst)
py> thing.things.append(100)
py> thing.things, lst
([100], [100])
py> lst = []
py> thing = Things2(lst)
py> thing.things.append(100)
py> thing.things, lst
([100], [])

That said, I do use "and" and "or" occasionally when I'm sure I don't
have to worry about complications like the above. I've probably even
used them in an assignment statement. ;)

STeVe
Sep 13 '05 #15

P: n/a
On Mon, 12 Sep 2005 12:52:52 +0200, gabor <ga***@nekomancer.net> wrote:
hi,

there are 2 versions of a simple code.
which is preferred?
I don't know. Who cares?
===
try:
text = line[n]
except IndexError:
text = 'nothing'
===
which is the one you would use?


The 'try' version. But I'd also ask myself how I could end up in a state where
this part of the code is asked to find a string that doesn't exist, and if I
really want it to keep running, with a made-up value.

/Jorgen

--
// Jorgen Grahn <jgrahn@ Ph'nglui mglw'nafh Cthulhu
\X/ algonet.se> R'lyeh wgah'nagl fhtagn!
Sep 17 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.