Re: If/then style question

2010-12-21 Thread Francesco

I'd bet you would stress your point Steven! But you don't need to persuade me, 
I do already agree.
I just meant to say that, when the advantage is little, there's no need to 
rewrite a working function.
And that with modern CPUs, if tests take so little time, that even some 
redundant one is not so much of a nuisance.
in your working example, the payload is just a couple of integer calculations, that take very little time too. So the overhead due 
to redundant if tests does show clearly. And also in that not-really-real situation, 60% overhead just meant less than 3 seconds. 
Just for the sake of discussion, I tried to give both functions some plough to pull, and a worst-case situation too:


 t1 = Timer('for x in range(100): print func1(0),',
...  'from __main__ import func1')

 t2 = Timer('for x in range(100): print func2(0),',
...  'from __main__ import func2')

 min(t1.repeat(number=1, repeat=1))
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
53.011015366479114
 min(t2.repeat(number=1, repeat=1))
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
47.55442856564332

that accounts for a scant 11% overhead, on more than one million tests per 
cycle.

That said,  let's make really clear that I would heartily prefer func2 to func1, based both on readability and speed. Thank you for 
having spent some time playing with me!

Francesco

On 19/12/2010 1.05, Steven D'Aprano wrote:

Well, let's try it with a working (albeit contrived) example. This is
just an example -- obviously I wouldn't write the function like this in
real life, I'd use a while loop, but to illustrate the issue it will do.

def func1(n):
 result = -1
 done = False
 n = (n+1)//2
 if n%2 == 1:
 result = n
 done = True
 if not done:
 n = (n+1)//2
 if n%2 == 1:
 result = n
 done = True
 if not done:
 n = (n+1)//2
 if n%2 == 1:
 result = n
 done = True
 if not done:
 for i in range(100):
 if not done:
 n = (n+1)//2
 if n%2 == 1:
 result = n
 done = True
 return result


def func2(n):
 n = (n+1)//2
 if n%2 == 1:
 return n
 n = (n+1)//2
 if n%2 == 1:
 return n
 n = (n+1)//2
 if n%2 == 1:
 return n
 for i in range(100):
 n = (n+1)//2
 if n%2 == 1:
 return n
 return -1


Not only is the second far more readable that the first, but it's also
significantly faster:


from timeit import Timer
t1 = Timer('for i in range(20): x = func1(i)',

... 'from __main__ import func1')

t2 = Timer('for i in range(20): x = func2(i)',

... 'from __main__ import func2')

min(t1.repeat(number=10, repeat=5))

7.3219029903411865

min(t2.repeat(number=10, repeat=5))

4.530779838562012

The first function does approximately 60% more work than the first, all
of it unnecessary overhead.





--
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-19 Thread Steven D'Aprano
On Sat, 18 Dec 2010 19:59:45 -0800, Carl Banks wrote:

 On Dec 17, 12:23 am, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:
 On Thu, 16 Dec 2010 20:32:29 -0800, Carl Banks wrote:
  Even without the cleanup issue, sometimes you want to edit a function
  to affect all return values somehow.  If you have a single exit point
  you just make the change there; if you have mulitple you have to hunt
  them down and change all of them--if you remember to.  I just got bit
  by that one.

 If your function has so many exit points that you can miss some of them
 while editing, your function is too big, does too much, or both.
 
 Sanctimonious much?  In the real world, people miss things and make
 mistakes and not necessarily because they are working on something too
 complex to handle.  It happens.


Really? I had no idea. I've never made a misteak, I asumed evrybody else 
was equally brilliant. No, wait, there was that one time...

*wink*

Of course people make mistakes. So what's your point?

The point I was trying to make is that rather than encouraging an idiom 
(only one return statement, even if the algorithm is more clearly written 
with multiple exists) that leads to more complex, less efficient code 
just in case you might someday need to modify the return result, there 
are simple alternatives that avoid the need for anti-patterns like copy-
and-paste coding or enforced single exit point. I gave two: 

- refactor the complex code so that it's less complex (e.g. instead of 20 
exit points, which makes it easy to miss one or two, refactor it so there 
are two or three exit points); or if that's not practical:

- wrap it in a decorator that performs the post-processing you need.

Both can be simple, effective and Pythonic. Neither require the coder to 
use an artificial idiom just in case of some future need. The decorator 
solution works even if you don't have access to the source code, or if 
the function is a complex black box that nobody understands well enough 
to touch.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-18 Thread Francesco

On 17/12/2010 0.51, Steven D'Aprano wrote:

Don't get me wrong... spaghetti code is*bad*. But there are other ways
of writing bad code too, and hanging around inside a function long after
you've finished is also bad:

def function(arg):
 done = False
 do_something()
 if some_condition:
 result = finished
 done = True
 if not done:
 do_something_else()
 if another_condition:
 result = now we're finished
 done = True
 if not done:
 do_yet_more_work()
 if third_condition:
 result = finished this time for sure
 done = True
 if not done:
 for i in range(100):
 if not done:
 do_something_small()
 if yet_another_condition:
 result = finally done!
 done = True
 return result

It's far more complicated than it need be, and does*lots*  of unnecessary
work. This can be written more simply and efficiently as:

def function(arg):
 do_something()
 if some_condition:
 return finished
 do_something_else()
 if another_condition:
 return now we're finished
 do_yet_more_work()
 if third_condition:
 return finished this time for sure
 for i in range(100):
 do_something_small()
 if yet_another_condition:
 return finally done!


I agree to your point, but I'm afraid you chose a wrong example (AFAIK, and 
that's not much).
Sure, the second version of function(arg) is much more readable, but why do you think the first one would do *lots*  of unnecessary 
work?

All the overhead in that function would be:
  if some_condition, three IF tests, and you know that's NOT a lot!
  if no conditions were met, (worst case) the first version would return an exception (unless result was globally defined) while 
the second would happily return None. Apart from this, the overhead in the first one would amount to one million IF tests, again not 
a lot these days. I don't think I would rewrite that function, if I found it written in the first way...

I don't mean that the fist example is better, just I'm sure you could imagine a 
more compelling proof of your concept.
Maybe there's something I don't know... in that case, please enlighten me!

Francesco
--
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-18 Thread Steven D'Aprano
On Sat, 18 Dec 2010 12:29:31 +0100, Francesco wrote:

[...]
 I agree to your point, but I'm afraid you chose a wrong example (AFAIK,
 and that's not much). Sure, the second version of function(arg) is much
 more readable, but why do you think the first one would do *lots*  of
 unnecessary work?
 All the overhead in that function would be:
if some_condition, three IF tests, and you know that's NOT a lot! 

Well, let's try it with a working (albeit contrived) example. This is 
just an example -- obviously I wouldn't write the function like this in 
real life, I'd use a while loop, but to illustrate the issue it will do.

def func1(n):
result = -1
done = False
n = (n+1)//2
if n%2 == 1:
result = n
done = True
if not done:
n = (n+1)//2
if n%2 == 1:
result = n
done = True
if not done:
n = (n+1)//2
if n%2 == 1:
result = n
done = True
if not done:
for i in range(100):
if not done:
n = (n+1)//2
if n%2 == 1:
result = n
done = True
return result


def func2(n):
n = (n+1)//2
if n%2 == 1:
return n
n = (n+1)//2
if n%2 == 1:
return n
n = (n+1)//2
if n%2 == 1:
return n
for i in range(100):
n = (n+1)//2
if n%2 == 1:
return n
return -1


Not only is the second far more readable that the first, but it's also 
significantly faster:

 from timeit import Timer
 t1 = Timer('for i in range(20): x = func1(i)', 
... 'from __main__ import func1')
 t2 = Timer('for i in range(20): x = func2(i)', 
... 'from __main__ import func2')
 min(t1.repeat(number=10, repeat=5))
7.3219029903411865
 min(t2.repeat(number=10, repeat=5))
4.530779838562012

The first function does approximately 60% more work than the first, all 
of it unnecessary overhead.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-18 Thread Carl Banks
On Dec 17, 12:23 am, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 16 Dec 2010 20:32:29 -0800, Carl Banks wrote:
  Even without the cleanup issue, sometimes you want to edit a function to
  affect all return values somehow.  If you have a single exit point you
  just make the change there; if you have mulitple you have to hunt them
  down and change all of them--if you remember to.  I just got bit by that
  one.

 If your function has so many exit points that you can miss some of them
 while editing, your function is too big, does too much, or both.

Sanctimonious much?  In the real world, people miss things and make
mistakes and not necessarily because they are working on something
too complex to handle.  It happens.


Carl Banks
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Steven D'Aprano
On Thu, 16 Dec 2010 20:32:29 -0800, Carl Banks wrote:

 Even without the cleanup issue, sometimes you want to edit a function to
 affect all return values somehow.  If you have a single exit point you
 just make the change there; if you have mulitple you have to hunt them
 down and change all of them--if you remember to.  I just got bit by that
 one.


If your function has so many exit points that you can miss some of them 
while editing, your function is too big, does too much, or both. Refactor 
and simplify. 

Or wrap the function in a decorator:

def affect_all_return_values(func):
@functools.wraps(func)
def inner(*args, **kwargs):
result = func(*args, **kwargs)
do_something_to(result)
return result
return inner

@affect_all_return_values
def my_big_complicated_function(args):
do_something_with_many_exit_points()



-- 
Steven


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Jean-Michel Pichavant

John Gordon wrote:

(This is mostly a style question, and perhaps one that has already been
discussed elsewhere.  If so, a pointer to that discussion will be
appreciated!)

When I started learning Python, I wrote a lot of methods that looked like
this:


  def myMethod(self, arg1, arg2):

if some_good_condition:

  if some_other_good_condition:

if yet_another_good_condition:

  do_some_useful_stuff()
  exitCode = good1

else:
  exitCode = bad3

  else:
exitCode = bad2

else:
  exitCode = bad1

return exitCode


But lately I've been preferring this style:


  def myMethod(self, arg1, arg2):

if some_bad_condition:
  return bad1

elif some_other_bad_condition:
  return bad2

elif yet_another_bad_condition:
  return bad3

do_some_useful_stuff()
return good1

I like this style more, mostly because it eliminates a lot of indentation.

However I recall one of my college CS courses stating that one entry,
one exit was a good way to write code, and this style has lots of exits.

Are there any concrete advantages of one style over the other?

Thanks.

  


What about,


def myMethod():
   for condition, exitCode in [
   (cond1, 'error1'),
   (cond2, 'very bad error'),
   ]:
   if not condition:
   break
   else:
  do_some_usefull_stuff() # executed only if the we never hit the 
break statement.

  exitCode = good1

   return exitCode

This version uses the 'for ... else' statement. You can easily add 
conditions by simply adding a line in the list, that's it.
Note that this code uses a shadow declaration of exitCode in the for 
loop. If you're not comfortable with that, you'll have to use a properly 
'declared' variable retCode and write retCode = exitCode before 
breaking. Actually I would advise to do so.


JM
--
http://mail.python.org/mailman/listinfo/python-list


RE: If/then style question

2010-12-17 Thread Rob Richardson
-Original Message-
What about,


def myMethod():
for condition, exitCode in [
(cond1, 'error1'),
(cond2, 'very bad error'),
]:
if not condition:
break
else:
   do_some_usefull_stuff() # executed only if the we never hit the 
break statement.
   exitCode = good1

return exitCode

 I reply -

This is interesting, but I don't understand it (which speaks volumes
about the level of my understanding of Python).

First, just to clarify, I don't think the indentation I saw was what was
originally posted.  The else must be indented to match the if, and
the two statements under else are in the else block.  The return
statement is indented at the same level as the for statement, so that it
will be executed after the for loop exits.  Correct?

Now, the for loop will set condition to cond1 and exitCode to 'error1'.
Then it checks the contents of the condition variable.  But what does
not variable_name by itself mean?  I'm guessing that it checks that
the variable refers to an object.  So, the first time through, condition
refers to cond1, the if condition is false, and the else block gets
executed, and exitCode is changed to refer to good1.  The next time
through the loop, condition is set to refer to cond2 and exitCode is set
to refer to 'very bad error'.  Again, condition is refering to
something, so the else block is executed and we do useful stuff again,
which is probably not helpful and could well be harmful.  exitCode is
set to good1, we're finished with the loop, and we return exitCode.  

What happens if we try to do useful stuff, and we can't?  Where does the
error indication get set?  And once it does get set, the only way we can
exit the for loop is for condition to not refer to anything.  How can
that happen?

Thank you very much for your explanation and your patience with one who
only uses Python in very simplistic ways.

RobR

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Steven D'Aprano
On Fri, 17 Dec 2010 09:09:49 -0500, Rob Richardson wrote:


 First, just to clarify, I don't think the indentation I saw was what was
 originally posted.  The else must be indented to match the if, and
 the two statements under else are in the else block.  The return
 statement is indented at the same level as the for statement, so that it
 will be executed after the for loop exits.  Correct?

I think that what you are missing is that for-loops can include an else 
clause too, like this:


 for x in (1,2,3):
... print(x)
... else:
... print(finished)
...
1
2
3
finished



The else block runs after the for block, unless you exit the entire block 
by returning, raising an exception, or using break:


 for x in (1,2,3):
... print(x)
... if x == 3: break
... else:
... print(finished)
...
1
2
3
 


Does that clear up what is going on?


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Jean-Michel Pichavant

Rob Richardson wrote:

-Original Message-
What about,


def myMethod():
for condition, exitCode in [
(cond1, 'error1'),
(cond2, 'very bad error'),
]:
if not condition:
break
else:
   do_some_usefull_stuff() # executed only if the we never hit the 
break statement.

   exitCode = good1

return exitCode

 I reply -

This is interesting, but I don't understand it (which speaks volumes
about the level of my understanding of Python).

First, just to clarify, I don't think the indentation I saw was what was
originally posted.  The else must be indented to match the if, and
the two statements under else are in the else block.  

No, the else is indented to the for loop.
for ... else is a python statement, the else block is executed only if 
the loop did never break.

http://docs.python.org/reference/compound_stmts.html#for

The return
statement is indented at the same level as the for statement, so that it
will be executed after the for loop exits.  Correct?

Now, the for loop will set condition to cond1 and exitCode to 'error1'.
Then it checks the contents of the condition variable.  But what does
not variable_name by itself mean?  


condition is a bool value.

if not condition is evaluated to True, if the condition is False.
condition = False
not condition = True
condition = ('Foo' == 'Foo')
not condition = False

[snip]

RobR

  


My mail client could have messed up with the indentation.

Here is the code:
http://paste-it.net/public/t8a4acd/python/



JM


--
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread David Robinow
On Thu, Dec 16, 2010 at 6:51 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
...
 Functions always have one entry. The only way to have multiple entry
 points is if the language allows you to GOTO into the middle of a
 function, and Python sensibly does not allow this. The one entry, one
 exit rule comes from the days when people would routinely write
 spaghetti code, jumping into and out of blocks of code without using
 functions at all.
Only 99.7% true. Fortran still allows the appalling ENTRY statement.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Steve Holden
On 12/17/2010 9:38 AM, Steven D'Aprano wrote:
 On Fri, 17 Dec 2010 09:09:49 -0500, Rob Richardson wrote:
 
 
 First, just to clarify, I don't think the indentation I saw was what was
 originally posted.  The else must be indented to match the if, and
 the two statements under else are in the else block.  The return
 statement is indented at the same level as the for statement, so that it
 will be executed after the for loop exits.  Correct?
 
 I think that what you are missing is that for-loops can include an else 
 clause too, like this:
 
 
 for x in (1,2,3):
 ... print(x)
 ... else:
 ... print(finished)
 ...
 1
 2
 3
 finished

 
 
 The else block runs after the for block, unless you exit the entire block 
 by returning, raising an exception, or using break:
 
 
 for x in (1,2,3):
 ... print(x)
 ... if x == 3: break
 ... else:
 ... print(finished)
 ...
 1
 2
 3

 
 
 Does that clear up what is going on?
 
 
This construct appears to be unpopular in actual use, and when it comes
up in classes and seminars there is always interesting debate as people
discuss potential uses and realise there are useful applications.

I think the choice of keyword is probably not Guido's crowning language
achievement, but then since the English keywords don't make natural
sense to those who speak other languages it's at least fair that there
should be one that isn't totally natural to English speakers. A small
price to pay for all the other keywords not being Dutch.

regards
 Steve
-- 
Steve Holden   +1 571 484 6266   +1 800 494 3119
PyCon 2011 Atlanta March 9-17   http://us.pycon.org/
See Python Video!   http://python.mirocommunity.org/
Holden Web LLC http://www.holdenweb.com/

-- 
http://mail.python.org/mailman/listinfo/python-list


RE: If/then style question

2010-12-17 Thread Rob Richardson
My thanks for pointing out the existence of the else: suite in the for
statement.  However, I remain confused.  For reference, here's the
original code:

 def myMethod():
 for condition, exitCode in [
 (cond1, 'error1'),
 (cond2, 'very bad error'),
 ]:
 if not condition:
 break
 else:
do_some_usefull_stuff() # executed only if the we never hit the

 break statement.
exitCode = good1

 return exitCode

What do we know about cond1 and cond2?  Do they have to be assigned
before this for statement is executed?  The sample code doesn't show it.


The loop is going to to execute once for condition = cond1 and exitCode
= 'error1'.  The only thing it's going to do is check to see what
condition is.  Since we can assume (I hope) that cond1 is not false,
then the for loop continues.  Now condition = cond2 and exitCode = 'very
bad error'.  The if condition is still false, so the loop continues.
We've come to the end now, and the else: suite is executed.  We finally
do some useful stuff and exitCode = good1.  (Should that have been in
quotes, or doesn't it matter?)  But now the for loop's job is done and
we return the exitCode, which at this point is good1.  

But I still don't understand what happens if we can't do useful stuff.
Where does an error code get set, and where is that error code checked?
We don't have a chance to check it in the for loop, because once we're
in the else: suite the loop condition is never rechecked.  Or is it?

Thanks again!

RobR
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Tim Golden

On 17/12/2010 15:53, Steve Holden wrote:

[... snip example of for-else ...]


This construct appears to be unpopular in actual use, and when it comes
up in classes and seminars there is always interesting debate as people
discuss potential uses and realise there are useful applications.


I use this not infrequently, and I like it when it seems to be an
elegant way to express the code path. But I still misremember from
time to time and assume that the else clause fires when the for
loop is empty.

TJG
--
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Paul Rubin
Jean-Michel Pichavant jeanmic...@sequans.com writes:
 What about,

 def myMethod():
for condition, exitCode in [
(cond1, 'error1'),
(cond2, 'very bad error'),
]:
if not condition:
break
else:
   do_some_usefull_stuff() # executed only if the we never hit the
 break statement.
   exitCode = good1

return exitCode

 This version uses the 'for ... else' statement. 

For..else always has seemed ugly and confusing to me, as does that thing
of using the captured loop indexes after the loop finishes.  I'd prefer
a more functional style (untested):

   def myMethod():
  def success():
 do_some_usefull_stuff()
 return good1
  cond_table = [
   (cond1, lambda: 'error1'),
   (cond2, lambda: 'very bad error'),
   (True, success)
  ]
  func = next(f for c,f in cond_table if c)
  return func()

This uses the next() builtin from Python 2.6.  You could make it more
concise:

   def myMethod():
  cond_table = [
   (cond1, lambda: 'error1'),
   (cond2, lambda: 'very bad error'),
   (True, lambda: (do_some_usefull_stuff(), good1)[1])
  ]
  return next(f for c,f in cond_table if c)()
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Ethan Furman

Rob Richardson wrote:

My thanks for pointing out the existence of the else: suite in the for
statement.  However, I remain confused.  For reference, here's the
original code:


def myMethod():
for condition, exitCode in [
(cond1, 'error1'),
(cond2, 'very bad error'),
]:
if not condition:
break
else:
   do_some_usefull_stuff() # executed only if the we never hit the



break statement.
   exitCode = good1

return exitCode


What do we know about cond1 and cond2?  Do they have to be assigned
before this for statement is executed?  The sample code doesn't show it.


cond1 and cond2 should be expressions of some sort, e.g.  check_files() 
or feedback (feedback being a variable of some sort).




The loop is going to to execute once for condition = cond1 and exitCode
= 'error1'.  The only thing it's going to do is check to see what
condition is.  Since we can assume (I hope) that cond1 is not false,
then the for loop continues.  Now condition = cond2 and exitCode = 'very
bad error'.  The if condition is still false, so the loop continues.
We've come to the end now, and the else: suite is executed.  We finally
do some useful stuff and exitCode = good1.  (Should that have been in
quotes, or doesn't it matter?)  But now the for loop's job is done and
we return the exitCode, which at this point is good1.  


But I still don't understand what happens if we can't do useful stuff.
Where does an error code get set, and where is that error code checked?
We don't have a chance to check it in the for loop, because once we're
in the else: suite the loop condition is never rechecked.  Or is it?


You have outlined what happens when cond1 and cond2 both evaluate to 
True -- what happens if, say, cond2 evaluates to False?


.

.

.

.

.

if not cond2 becomes True, we hit the break, do not do 
do_some_usefull_stuff(), but proceed to return exitCode -- and exitCode 
was set in the for loop to 'very bad error' when condition was set to cond2.


The exitCode no longer needs to be checked inside the function, because 
there is no chance of do_some_useful_stuff running if any of the 
conditions are False.


Hope this helps.

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Steve Holden
On 12/17/2010 11:13 AM, Tim Golden wrote:
 On 17/12/2010 15:53, Steve Holden wrote:
 
 [... snip example of for-else ...]
 
 This construct appears to be unpopular in actual use, and when it comes
 up in classes and seminars there is always interesting debate as people
 discuss potential uses and realise there are useful applications.
 
 I use this not infrequently, and I like it when it seems to be an
 elegant way to express the code path. But I still misremember from
 time to time and assume that the else clause fires when the for
 loop is empty.
 
Yes, that's a common misconception. The classical use is something like

for item in possibilities:
if item == target:
break
else:
raise NotFound(Didn't find it)

Though of course arguably that logic might be expressed in other ways,
such as

if target not in possibilities:
raise NotFound(Didn't find it)

regards
 Steve
-- 
Steve Holden   +1 571 484 6266   +1 800 494 3119
PyCon 2011 Atlanta March 9-17   http://us.pycon.org/
See Python Video!   http://python.mirocommunity.org/
Holden Web LLC http://www.holdenweb.com/

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Mark Wooding
Steve Holden st...@holdenweb.com writes:

 I think the choice of keyword is probably not Guido's crowning
 language achievement,

I remember the behaviour by considering a typical application:

for thing in things:
  if shinyp(thing):
break
else:
  raise DullError, 'nothing shiny found'

In this kind of search loop, `break' signifies a kind of successful
completion: the `for' loop can be considered to be a test acting over an
iterable, and `else' therefore denotes the action if the test fails.

I don't know whether that's the official intuition, or even if there is
an official intuition, but it works well enough for me.  I'm quite fond
of Python's extra `else' clauses in `for' and (particularly) `try'.

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Arnaud Delobelle
Tim Golden m...@timgolden.me.uk writes:

 On 17/12/2010 15:53, Steve Holden wrote:

 [... snip example of for-else ...]

 This construct appears to be unpopular in actual use, and when it comes
 up in classes and seminars there is always interesting debate as people
 discuss potential uses and realise there are useful applications.

 I use this not infrequently, and I like it when it seems to be an
 elegant way to express the code path. But I still misremember from
 time to time and assume that the else clause fires when the for
 loop is empty.

I use it from time to time, even though, like you, I used to always be
unsure when the else: suite would be executed.  I now remember this
idiom as the break else construct: either the loop breaks, or the
else: suite is executed.

-- 
Arnaud
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread python
 I now remember this idiom as the break else construct: either the loop 
 breaks, or the else: suite is executed.

A perfect description.

Malcolm
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Grant Edwards
On 2010-12-16, Stefan Sonnenberg-Carstens stefan.sonnenb...@pythonmeister.com 
wrote:

 The advantage in latter case is fewer operations, because you can
 skip the assignments, and it is more readable.

 The one entry, one exit is an advice. Not a law.
 Your code is OK.

 As long as it works ;-)

Even that last bit isn't that important.

Give me code that's easy-to-read and doesn't work rather code that
works and can't be read any day.


-- 
Grant Edwards   grant.b.edwardsYow! What's the MATTER
  at   Sid? ... Is your BEVERAGE
  gmail.comunsatisfactory?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Grant Edwards
On 2010-12-16, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 16 Dec 2010 21:49:07 +, John Gordon wrote:

 (This is mostly a style question, and perhaps one that has already been
 discussed elsewhere.  If so, a pointer to that discussion will be
 appreciated!)
 
 When I started learning Python, I wrote a lot of methods that looked
 like this:
 
   def myMethod(self, arg1, arg2):
 if some_good_condition:
   if some_other_good_condition:
 if yet_another_good_condition:
   do_some_useful_stuff()
   exitCode = good1
 else:
   exitCode = bad3
   else:
 exitCode = bad2
 else:
   exitCode = bad1
 return exitCode


 It doesn't look like you were learning Python. It looks like you were 
 learning C with Python syntax :(

Let's not blame C for bad program structure.  No good C programmer
would use that construct either.

One choice in C would look like this:

  if (some_condition)
return code1;

  if (other_condition)
return code2;

  if (condition3)
return code3;

  //do whatever work really needs to be done here.

  return successCode;

Or, if there's cleanup that needs to be done, then you raise a an
exception:


  if (condition1)
{
  ret  = code1;
  goto errexit;  
}

  if (condition2)
{
  ret  = code2;
  goto errexit;  
}

  if (condition3)
{
  ret  = code3;
  goto errexit;  
}


  // do the normal bit of work


  errexit:

  //cleanup  

  return ret;

  
-- 
Grant Edwards   grant.b.edwardsYow! Awright, which one of
  at   you hid my PENIS ENVY?
  gmail.com
-- 
http://mail.python.org/mailman/listinfo/python-list


RE: If/then style question

2010-12-17 Thread Rob Richardson

-Original Message-
You have outlined what happens when cond1 and cond2 both evaluate to 
True -- what happens if, say, cond2 evaluates to False?

- I reply 

And the light goes on!  (And palm strikes forehead.)  I was thinking
that the error we were processing was raised by the
do_some_useful_stuff() function.  But the whole purpose of this thread
was to evaluate error conditions that might have been set before we do
useful stuff!  Which, of course, was what the original poster was
asking.  

My thanks again for your patience.

RobR
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Kev Dwyer
On Thu, 16 Dec 2010 21:49:07 +, John Gordon wrote:

 (This is mostly a style question, and perhaps one that has already been
 discussed elsewhere.  If so, a pointer to that discussion will be
 appreciated!)
 
 When I started learning Python, I wrote a lot of methods that looked
 like this:
 
 
   def myMethod(self, arg1, arg2):
 
 if some_good_condition:
 
   if some_other_good_condition:
 
 if yet_another_good_condition:
 
   do_some_useful_stuff()
   exitCode = good1
 
 else:
   exitCode = bad3
 
   else:
 exitCode = bad2
 
 else:
   exitCode = bad1
 
 return exitCode
 
 

Another way to look at this is as question of object-oriented style, as you
 are using a method in your example...

Arguably, rather than branching your code based on the arguments being 
passed to your method, you can embody the required behaviour in subclasses
of your class, and at runtime just use an object that does the right 
thing.  Of course, you end up writing the same branching in some factory 
object instead, but at least it isn't cluttering up your business logic 
any longer.  Trying to write an OO-style program without using any if 
statements in the business logic can be an interesting exercise, albeit 
not a terribly realistic one.

Apologies if your choice of a method for your example was entirely
incidental to your question :)

Kev

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Steven D'Aprano
On Fri, 17 Dec 2010 10:53:45 -0500, Steve Holden wrote about for...else:

 This construct appears to be unpopular in actual use, and when it comes
 up in classes and seminars there is always interesting debate as people
 discuss potential uses and realise there are useful applications.

Yes, I find I don't need it often, but it is useful from time to time.

I wonder whether it would have been more useful to reverse the sense of 
the else, and have it run only if the for loop *didn't* run to 
completion. That seemed more intuitive to me, and I've wanted to do this 
more than once. Here's a toy example:

for x in sequence:
if x == spam:
print(exiting early)
break
elif x == ham:
print(exiting early)
break
do_something(x)


would become:

for x in sequence:
if x == spam:
break
elif x == ham:
break
do_something(x)
else:
print(exiting early)



 I think the choice of keyword is probably not Guido's crowning language
 achievement, but then since the English keywords don't make natural
 sense to those who speak other languages it's at least fair that there
 should be one that isn't totally natural to English speakers. A small
 price to pay for all the other keywords not being Dutch.

Indeed :)




-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-17 Thread Steven D'Aprano
On Fri, 17 Dec 2010 17:26:08 +, Grant Edwards wrote:

 Give me code that's easy-to-read and doesn't work rather code that works
 and can't be read any day.

Well, in that case, you'll love my new operating system, written in 100% 
pure Python:

[start code]
print(this is an operating system)
[end code]

I expect it to rapidly make Windows, Linux and OS-X all obsolete. Bill 
Gates and Steve Jobs, look out!

*grin*


Surely your attitude towards usefulness vs. readability will depend 
strongly on whether you are intending to *use* the code, or *maintain* 
the code?



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Ethan Furman

John Gordon wrote:

(This is mostly a style question, and perhaps one that has already been
discussed elsewhere.  If so, a pointer to that discussion will be
appreciated!)

When I started learning Python, I wrote a lot of methods that looked like
this:


  def myMethod(self, arg1, arg2):
if some_good_condition:
  if some_other_good_condition:
if yet_another_good_condition:
  do_some_useful_stuff()
  exitCode = good1
else:
  exitCode = bad3
  else:
exitCode = bad2
else:
  exitCode = bad1
return exitCode


But lately I've been preferring this style:

  def myMethod(self, arg1, arg2):
if some_bad_condition:
  return bad1
elif some_other_bad_condition:
  return bad2
elif yet_another_bad_condition:
  return bad3
do_some_useful_stuff()
return good1

I like this style more, mostly because it eliminates a lot of indentation.


As far as if/else goes, I prefer the second style also.

As far as returning bad codes, you are better off raising exceptions:

def myMethod(self, arg1, arg2):
if some_bad_condition:
raise Bad1()
elif some_other_bad_condition:
raise Bad2()
elif yet_another_bad_condition:
raise Bad3()
do_some_useful_stuff
# no need to return 'good' code -- success means no problems

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Tim Harig
On 2010-12-16, John Gordon gor...@panix.com wrote:
 I like this style more, mostly because it eliminates a lot of indentation.

 However I recall one of my college CS courses stating that one entry,
 one exit was a good way to write code, and this style has lots of exits.

So, take the good intentation from one and the single exit from the other:

   def myMethod(self, arg1, arg2):

 if some_bad_condition:
   exitCode = bad1

 elif some_other_bad_condition:
   exitCode = bad2

 elif yet_another_bad_condition:
   exitCode = bad3

 else:
   exitCode = do_some_useful_stuff()

 # possible common cleanup code here

 return exitCode

Or, raise an exception on bad condtions rather then passing an error code.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Grant Edwards
On 2010-12-16, John Gordon gor...@panix.com wrote:
 (This is mostly a style question, and perhaps one that has already been
 discussed elsewhere.  If so, a pointer to that discussion will be
 appreciated!)

 When I started learning Python, I wrote a lot of methods that looked like
 this:


   def myMethod(self, arg1, arg2):
 if some_good_condition:
   if some_other_good_condition:
 if yet_another_good_condition:
   do_some_useful_stuff()
   exitCode = good1
 else:
   exitCode = bad3
   else:
 exitCode = bad2
 else:
   exitCode = bad1
 return exitCode


 But lately I've been preferring this style:


   def myMethod(self, arg1, arg2):

 if some_bad_condition:
   return bad1

 elif some_other_bad_condition:
   return bad2

 elif yet_another_bad_condition:
   return bad3

 do_some_useful_stuff()
 return good1

 I like this style more, mostly because it eliminates a lot of
 indentation.

There's nothing inherently wrong with indentation, but in this case
the latter style is a _lot_ easier to read (and modify without
breaking).

 However I recall one of my college CS courses stating that one
 entry, one exit was a good way to write code, and this style has
 lots of exits.

 Are there any concrete advantages of one style over the other?

I think the check/exit style is far more readable.

It can trip you up if there is cleanup stuff that needs to happen
before you return from the function.  In that case putting the whole
function in a try statement and raising exceptions for the bad
conditions works nicely.  Then you get the more readable style of the
check/exit style, plus the advantage of a single exit (it's easy to
verify visually that all the required cleanup is happening).

-- 
Grant Edwards   grant.b.edwardsYow! I want a WESSON OIL
  at   lease!!
  gmail.com
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Stefan Sonnenberg-Carstens

Am 16.12.2010 22:49, schrieb John Gordon:

(This is mostly a style question, and perhaps one that has already been
discussed elsewhere.  If so, a pointer to that discussion will be
appreciated!)

When I started learning Python, I wrote a lot of methods that looked like
this:


   def myMethod(self, arg1, arg2):

 if some_good_condition:

   if some_other_good_condition:

 if yet_another_good_condition:

   do_some_useful_stuff()
   exitCode = good1

 else:
   exitCode = bad3

   else:
 exitCode = bad2

 else:
   exitCode = bad1

 return exitCode


But lately I've been preferring this style:


   def myMethod(self, arg1, arg2):

 if some_bad_condition:
   return bad1

 elif some_other_bad_condition:
   return bad2

 elif yet_another_bad_condition:
   return bad3


else:

do_some_useful_stuff()
return good1

I like this style more, mostly because it eliminates a lot of indentation.

However I recall one of my college CS courses stating that one entry,
one exit was a good way to write code, and this style has lots of exits.

Are there any concrete advantages of one style over the other?

Thanks.






The advantage in latter case is fewer operations, because you can skip 
the assignments,

and it is more readable.

The one entry, one exit is an advice. Not a law.
Your code is OK.

As long as it works ;-)


P.S.:
Sorry, I could not resist:
return bad1 if some_bad_condition else bad2 if some_other_bad_condition 
else bad3 if yet_another_bad_condition else good1 if 
do_some_useful_stuff() else good1

Or consider this:
return [x for x,y in 
((bad1,some_bad_condition),(bad2,some_other_bad_condition),(bad3,yet_another_bad_condition),(good1,do_some_useful_stuff() 
or True)) if x][0]


Neither self explanatory nor readable :-(
--
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Ryan Kelly
On Thu, 2010-12-16 at 21:49 +, John Gordon wrote:
 (This is mostly a style question, and perhaps one that has already been
 discussed elsewhere.  If so, a pointer to that discussion will be
 appreciated!)
 
 When I started learning Python, I wrote a lot of methods that looked like
 this:
 
 
   def myMethod(self, arg1, arg2):
 if some_good_condition:
   if some_other_good_condition:
 if yet_another_good_condition:
   do_some_useful_stuff()
   exitCode = good1
 else:
   exitCode = bad3
   else:
 exitCode = bad2
 else:
   exitCode = bad1
 return exitCode
 
 
 But lately I've been preferring this style:
 
 
   def myMethod(self, arg1, arg2):
 if some_bad_condition:
   return bad1
 elif some_other_bad_condition:
   return bad2
 elif yet_another_bad_condition:
   return bad3
 do_some_useful_stuff()
 return good1
 
 I like this style more, mostly because it eliminates a lot of indentation.
 
 However I recall one of my college CS courses stating that one entry,
 one exit was a good way to write code, and this style has lots of exits.
 
 Are there any concrete advantages of one style over the other?


one entry, one exit has its good points, but it's *way* overquoted and
overused.

Do you raise any exceptions? Do you call any functions that might raise
exceptions?  If so, you've got multiple exit points already.

I think this style a lot more important in a language like C where you
have to be super-careful about cleaning up after yourself.  The single
exit point makes it easier to verify that all cleanup tasks have been
performed.  Assuming you're using with or try-finally then you just
don't need such guarantees in python.

I'm not a PEP-8 pedant by any means, but I think that the first section
of PEP-8 contains the best advice I've ever read about programming
language style.  In fact, I'm going to quote it right here:



  A Foolish Consistency is the Hobgoblin of Little Minds
  ==
One of Guido's key insights is that code is read much more often than it
is written.  The guidelines provided here are intended to improve the
readability of code and make it consistent across the wide spectrum of
Python code.  As PEP 20 says, Readability counts.

...snip...

But most importantly: know when to be inconsistent -- sometimes the style
guide just doesn't apply.  When in doubt, use your best judgment.  Look
at other examples and decide what looks best.  And don't hesitate to ask!



In your example, the first style is difficult to read wile the second
style is easy to read.  You don't need any further justification for
preferring the latter.


  Cheers,


 Ryan


-- 
Ryan Kelly
http://www.rfk.id.au  |  This message is digitally signed. Please visit
r...@rfk.id.au|  http://www.rfk.id.au/ramblings/gpg/ for details



signature.asc
Description: This is a digitally signed message part
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Ian Kelly
On Thu, Dec 16, 2010 at 3:41 PM, Stefan Sonnenberg-Carstens
stefan.sonnenb...@pythonmeister.com wrote:
 return [x for x,y in
 ((bad1,some_bad_condition),(bad2,some_other_bad_condition),(bad3,yet_another_bad_condition),(good1,do_some_useful_stuff()
 or True)) if x][0]

This doesn't work.  do_some_usefull_stuff() gets called during the
tuple construction regardless of the conditions, not during the list
comprehension execution as you would want.

Here's my take on an unreadable one-liner:

return reduce(lambda x, y: (x or (y[0]() and y[1])),
[(some_bad_condition, bad1), (some_other_bad_condition, bad2),
(yet_another_bad_condition, bad3), (lambda: (do_some_useful_stuff() or
True), good1)], None)

This of course assumes that bad1, bad2, and bad3 all evaluate as true.

Cheers,
Ian
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Steven D'Aprano
On Thu, 16 Dec 2010 21:49:07 +, John Gordon wrote:

 (This is mostly a style question, and perhaps one that has already been
 discussed elsewhere.  If so, a pointer to that discussion will be
 appreciated!)
 
 When I started learning Python, I wrote a lot of methods that looked
 like this:
 
   def myMethod(self, arg1, arg2):
 if some_good_condition:
   if some_other_good_condition:
 if yet_another_good_condition:
   do_some_useful_stuff()
   exitCode = good1
 else:
   exitCode = bad3
   else:
 exitCode = bad2
 else:
   exitCode = bad1
 return exitCode


It doesn't look like you were learning Python. It looks like you were 
learning C with Python syntax :(

The above would be more Pythonically written as:


def myMethod(self, arg1, arg2):
if not some_good_condition:
raise SomeException(message)
if not some_other_good_condition:
raise SomeOtherException(another message)
if yet_another_good_condition:
do_some_useful_stuff()
else:
raise SomeThirdException(whatever)


using exceptions to communicate errors out-of-band. Since no return 
result is needed, no explicit return is used and the method is the 
closest thing to a procedure that Python can offer.

The problem with in-band transmission of errors is that they invite the 
anti-pattern of this:

result = obj.myMethod(arg1, arg2)
if result == good1:
do_something_good()
elif result == bad1:
handle_error1()
elif result == bad2:
handle_error2()
elif result == bad3():
handle_error3()
else:
print This can't ever happen, but if it does...


which all too often becomes:

result = obj.myMethod(arg1, arg2)
if result == good1:
do_something_good()
else:  # assume result is bad1
handle_error1()


or even:

who_cares = obj.myMethod(arg1, arg2)
do_something_good()



 But lately I've been preferring this style:
 
   def myMethod(self, arg1, arg2):
 if some_bad_condition:
   return bad1
 elif some_other_bad_condition:
   return bad2
 elif yet_another_bad_condition:
   return bad3
 do_some_useful_stuff()
 return good1
 
 I like this style more, mostly because it eliminates a lot of
 indentation.

Well, that's better, but still more like C rather than Python. Avoid the 
anti-pattern of returning in-band error codes. In some languages, either 
exceptions aren't available at all, or the overhead of them is so great 
that for performance you have to avoid them, but Python is not one of 
those languages.

In Python, exceptions are *the* primary way of communicating exceptional 
cases such as (but not limited to) errors. I can only think of two, er, 
exceptions to this rule: str.find() and some of the regular expression 
methods.


 However I recall one of my college CS courses stating that one entry,
 one exit was a good way to write code, and this style has lots of
 exits.

Functions always have one entry. The only way to have multiple entry 
points is if the language allows you to GOTO into the middle of a 
function, and Python sensibly does not allow this. The one entry, one 
exit rule comes from the days when people would routinely write 
spaghetti code, jumping into and out of blocks of code without using 
functions at all.

If one entry is pointless (all functions have one entry!) then one 
exit is actively harmful. It leads to adding unnecessary complexity to 
functions, purely to meet the requirements of a rule invented to 
discourage spaghetti code. This hides bugs and increases the maintenance 
burden.

Don't get me wrong... spaghetti code is *bad*. But there are other ways 
of writing bad code too, and hanging around inside a function long after 
you've finished is also bad:

def function(arg):
done = False
do_something()
if some_condition:
result = finished
done = True
if not done:
do_something_else()
if another_condition:
result = now we're finished
done = True
if not done:
do_yet_more_work()
if third_condition:
result = finished this time for sure
done = True
if not done:
for i in range(100):
if not done:
do_something_small()
if yet_another_condition:
result = finally done!
done = True
return result

It's far more complicated than it need be, and does *lots* of unnecessary 
work. This can be written more simply and efficiently as:

def function(arg):
do_something()
if some_condition:
return finished
do_something_else()
if another_condition:
return now we're finished
do_yet_more_work()
if third_condition:
return finished this time for sure
for i in range(100):
do_something_small()
if yet_another_condition:
return finally done!


Over 40% of the code in the first version is 

Re: If/then style question

2010-12-16 Thread alex23
John Gordon gor...@panix.com wrote:
 But lately I've been preferring this style:

   def myMethod(self, arg1, arg2):

     if some_bad_condition:
       return bad1

     elif some_other_bad_condition:
       return bad2

     elif yet_another_bad_condition:
       return bad3

     do_some_useful_stuff()
     return good1

For more than 2 tests in a function like this, I'd probably use
dictionary dispatch:

def myMethod(self, arg1, arg2):
branches = dict(
cond1:  bad1,
cond2:  bad2,
cond3:  bad3
)

cond = expression

if cond == cond_good:
do_some_useful_stuff()
exitCode = good1
else:
exitCode = branches[cond]

return exitCode
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Joel Koltner
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote in message 
news:4d0aa5e7$0$29997$c3e8da3$54964...@news.astraweb.com...

It doesn't look like you were learning Python. It looks like you were
learning C with Python syntax :(


True, although in many cases one has to interface to legacy C code where it'd 
be rather more code to start throwing exceptions left or right... since sooner 
or later those exceptions would still have to be turned into a single status 
(error) code!



which all too often becomes:

result = obj.myMethod(arg1, arg2)
if result == good1:
   do_something_good()
else:  # assume result is bad1
   handle_error1()


This really isn't a bad way to go *if you weren't planning on spending the 
time to really, fully flesh out the individual error cases anyway.*  I see 
this pretty often: Peple put in sophisticated exception handling 
infrastructure, but when an error actually occurs, all six dozen cases handled 
individually end up just printing some generic message and exiting the program 
anyway.


In an ideal world all the error cases would do something smart, but 
pragmatically one has to balance how likely an error is to occur and how much 
damage it does with how much time you want to spend making a really smart 
error handler.



or even:

who_cares = obj.myMethod(arg1, arg2)
do_something_good()


Even this can be OK if do_something_good() behaves in a relatively benign 
fashion when feed gibberish.  I mean, how many people actually check to see 
whether or not printf() succeeded, you know?


But I would agree that often you see...

who_care = obj.myMethod(arg1, arg2)
do_something_really_dangerous_that_depends_on_the_success_of_myMethod()

:-)


Well, that's better, but still more like C rather than Python. Avoid the
anti-pattern of returning in-band error codes.


The main sticky point here is that what's an error vs. a warning or note 
(but not success) is often rather a grey area.  E.g., Pyhton's open() raises 
an IOError is the file can't be opened, but in my mind that's still a common 
enough/expected occurrence that elevating its behavior to an exception is more 
a judgement call than something everyone would agree on.  (On the other hand, 
trying to read or write to an un-opened file is now clearly in the realm of an 
error and deserves an exception.)


---Joel

--
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Carl Banks
On Dec 16, 2:56 pm, Ryan Kelly r...@rfk.id.au wrote:
 On Thu, 2010-12-16 at 21:49 +, John Gordon wrote:
  (This is mostly a style question, and perhaps one that has already been
  discussed elsewhere.  If so, a pointer to that discussion will be
  appreciated!)

  When I started learning Python, I wrote a lot of methods that looked like
  this:

    def myMethod(self, arg1, arg2):
      if some_good_condition:
        if some_other_good_condition:
          if yet_another_good_condition:
            do_some_useful_stuff()
            exitCode = good1
          else:
            exitCode = bad3
        else:
          exitCode = bad2
      else:
        exitCode = bad1
      return exitCode

  But lately I've been preferring this style:

    def myMethod(self, arg1, arg2):
      if some_bad_condition:
        return bad1
      elif some_other_bad_condition:
        return bad2
      elif yet_another_bad_condition:
        return bad3
      do_some_useful_stuff()
      return good1

  I like this style more, mostly because it eliminates a lot of indentation.

  However I recall one of my college CS courses stating that one entry,
  one exit was a good way to write code, and this style has lots of exits.

  Are there any concrete advantages of one style over the other?

 one entry, one exit has its good points, but it's *way* overquoted and
 overused.

 Do you raise any exceptions? Do you call any functions that might raise
 exceptions?  If so, you've got multiple exit points already.

 I think this style a lot more important in a language like C where you
 have to be super-careful about cleaning up after yourself.  The single
 exit point makes it easier to verify that all cleanup tasks have been
 performed.  Assuming you're using with or try-finally then you just
 don't need such guarantees in python.

Even without the cleanup issue, sometimes you want to edit a function
to affect all return values somehow.  If you have a single exit point
you just make the change there; if you have mulitple you have to hunt
them down and change all of them--if you remember to.  I just got bit
by that one.

It's a trade-off.  Readability and/or conciseness versus error
robustness.  I tend to go for the former but mileage varies.


Carl Banks
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: If/then style question

2010-12-16 Thread Steve Holden
On 12/16/2010 11:32 PM, Carl Banks wrote:
 On Dec 16, 2:56 pm, Ryan Kelly r...@rfk.id.au wrote:
 On Thu, 2010-12-16 at 21:49 +, John Gordon wrote:
 (This is mostly a style question, and perhaps one that has already been
 discussed elsewhere.  If so, a pointer to that discussion will be
 appreciated!)

 When I started learning Python, I wrote a lot of methods that looked like
 this:

   def myMethod(self, arg1, arg2):
 if some_good_condition:
   if some_other_good_condition:
 if yet_another_good_condition:
   do_some_useful_stuff()
   exitCode = good1
 else:
   exitCode = bad3
   else:
 exitCode = bad2
 else:
   exitCode = bad1
 return exitCode

 But lately I've been preferring this style:

   def myMethod(self, arg1, arg2):
 if some_bad_condition:
   return bad1
 elif some_other_bad_condition:
   return bad2
 elif yet_another_bad_condition:
   return bad3
 do_some_useful_stuff()
 return good1

 I like this style more, mostly because it eliminates a lot of indentation.

 However I recall one of my college CS courses stating that one entry,
 one exit was a good way to write code, and this style has lots of exits.

 Are there any concrete advantages of one style over the other?

 one entry, one exit has its good points, but it's *way* overquoted and
 overused.

 Do you raise any exceptions? Do you call any functions that might raise
 exceptions?  If so, you've got multiple exit points already.

 I think this style a lot more important in a language like C where you
 have to be super-careful about cleaning up after yourself.  The single
 exit point makes it easier to verify that all cleanup tasks have been
 performed.  Assuming you're using with or try-finally then you just
 don't need such guarantees in python.
 
 Even without the cleanup issue, sometimes you want to edit a function
 to affect all return values somehow.  If you have a single exit point
 you just make the change there; if you have mulitple you have to hunt
 them down and change all of them--if you remember to.  I just got bit
 by that one.
 
 It's a trade-off.  Readability and/or conciseness versus error
 robustness.  I tend to go for the former but mileage varies.
 
Heaven forfend you should just wrap the existing function inside another
one which takes its name, if all its returns need to be altered.

regards
 Steve
-- 
Steve Holden   +1 571 484 6266   +1 800 494 3119
PyCon 2011 Atlanta March 9-17   http://us.pycon.org/
See Python Video!   http://python.mirocommunity.org/
Holden Web LLC http://www.holdenweb.com/

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: calling functions style question

2006-06-06 Thread Thomas Nelson
The difference becomes clear when you import your program into another
program (or the command line python editor).  __name__!='__main__' when
you import, so the functions will not be called if they're inside the
block.  This is why you see this block so often at the end of scripts;
so that the script runs its main functions when called as a standalone
program, but you can also import the code and do something with it
without setting off those functions.

THN

Brian wrote:
 I just have a basic style question here.  Suppose you have the program:

 def foo1():
 do something

 def foo2()
 do something else

 Assume that you want to call these functions at execution.  Is it more
 proper to call them directly like:

 foo1()
 foo2()

 or in an if __name__ == __main__: ?

 Both will execute when the script is called directly, I was just
 wondering if there is a preference, and what the pros and cons to each
 method were.
 
 Thanks,
 Brian

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: calling functions style question

2006-06-06 Thread Kay Schluehr

Brian wrote:
 I just have a basic style question here.  Suppose you have the program:

 def foo1():
 do something

 def foo2()
 do something else

 Assume that you want to call these functions at execution.  Is it more
 proper to call them directly like:

 foo1()
 foo2()

 or in an if __name__ == __main__: ?

 Both will execute when the script is called directly, I was just
 wondering if there is a preference, and what the pros and cons to each
 method were.

 Thanks,
 Brian

If you want those functions to be called each time your module gets
imported you have to apply calls out of the if __name__ ...
statement. If your module is, for certain reasons, always the __main__
module and never gets imported there is no obvious preference because
behaviour will be the same.

-- 
http://mail.python.org/mailman/listinfo/python-list