473,385 Members | 1,890 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

for: else: - any practical uses for the else clause?

A very old thread:
http://groups.google.com/group/comp....42d2041257c47e

discusses the optional "else:" clause of the for statement.

I'm wondering if anyone has ever found a practical use for the else
branch?

Sep 26 '06 #1
25 1829

metaperlI'm wondering if anyone has ever found a practical use for the
metaperlelse branch?

Yeah, I use it from time to time:

for foo in bar:
if foo matches some condition:
print "sail to tahiti!"
break
else:
print "abandon ship!"

Skip
Sep 26 '06 #2
me**********@gmail.com a écrit :
A very old thread:
http://groups.google.com/group/comp....42d2041257c47e

discusses the optional "else:" clause of the for statement.

I'm wondering if anyone has ever found a practical use for the else
branch?
I use it regularly in contructs like:

for value in someList:
if someCondition(value):
print "a matching item was found"
break
else:
print "no matching item"
return False

# ... continue with value

--
Amaury
Sep 26 '06 #3
me**********@gmail.com a écrit :
A very old thread:
http://groups.google.com/group/comp....42d2041257c47e

discusses the optional "else:" clause of the for statement.

I'm wondering if anyone has ever found a practical use for the else
branch?
<aol>
Just like Skip and Amaury...
</aol>
Sep 26 '06 #4

Amaury Forgeot d'Arc wrote:
me**********@gmail.com a écrit :
A very old thread:
http://groups.google.com/group/comp....42d2041257c47e

discusses the optional "else:" clause of the for statement.

I'm wondering if anyone has ever found a practical use for the else
branch?

I use it regularly in contructs like:

for value in someList:
if someCondition(value):
print "a matching item was found"
break
else:
print "no matching item"
return False

# ... continue with value
Me too...

Same with while loops.

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml

--
Amaury
Sep 26 '06 #5
sk**@pobox.com wrote:
metaperlI'm wondering if anyone has ever found a practical use for the
metaperlelse branch?

Yeah, I use it from time to time:

for foo in bar:
if foo matches some condition:
print "sail to tahiti!"
break
else:
print "abandon ship!"
As a C++ programmer (which I'm sure undermines my argument before
you've even read it...), this feels 'backwards' to me. Although I am no
purist, the 'else' typically implies failure of a previous explicit
condition, yet in this case, it's executed by default, when the
previous clause was successfully executed. It would seem more natural
if the else clause was triggered by 'bar' being empty, or even if the
loop was explicitly broken out of, though I'm sure that would make the
construct much less useful.

--
Ben Sizer

Sep 27 '06 #6
Ben Sizer <ky*****@gmail.comwrote:
>sk**@pobox.com wrote:
>Yeah, I use it from time to time:

for foo in bar:
if foo matches some condition:
print "sail to tahiti!"
break
else:
print "abandon ship!"

As a C++ programmer (which I'm sure undermines my argument before
you've even read it...), this feels 'backwards' to me. Although I am no
purist, the 'else' typically implies failure of a previous explicit
condition, yet in this case, it's executed by default, when the
previous clause was successfully executed. It would seem more natural
if the else clause was triggered by 'bar' being empty, [ ... ]
It does:
>>for foo in []:
.... print foo
.... else:
.... print 'else'
....
else

I think it's clearer to see by comparing while with if:

if False:
do nothing
else:
do something

while False:
do nothing
else:
do something

and getting to the for behaviour from while is trivial.

That said, I've not had much call for it and was kind of surprised to
find myself writing a genuine for ... else the other week. But it was
the obvious way to do the task at hand, and I was happy it was there.

--
\S -- si***@chiark.greenend.org.uk -- http://www.chaos.org.uk/~sion/
___ | "Frankly I have no feelings towards penguins one way or the other"
\X/ | -- Arthur C. Clarke
her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump
Sep 28 '06 #7
Actually right after posting this I came up with a great usage. I use
meld3 for my Python based dynamic HTML generation. Whenever I plan to
loop over a tree section I use a for loop, but if there is no data to
iterate over, then I simply remove that section from the tree or
populate it with a "no data" message.

Sep 29 '06 #8
metaperl wrote:
Actually right after posting this I came up with a great usage. I use
meld3 for my Python based dynamic HTML generation. Whenever I plan to
loop over a tree section I use a for loop, but if there is no data to
iterate over, then I simply remove that section from the tree or
populate it with a "no data" message.
else: does not trigger when there is no data on which to iterate, but
when the loop terminated normally (ie., wasn't break-ed out). It is
meaningless without break.

Python 2.4.3 (#1, Mar 29 2006, 15:37:23)
[GCC 4.0.2 20051125 (Red Hat 4.0.2-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>for x in []:
.... print 'nothing'
.... else:
.... print 'done'
....
done

-Mike

Sep 29 '06 #9
Klaas wrote:
else: does not trigger when there is no data on which to iterate, but
when the loop terminated normally (ie., wasn't break-ed out). It is
meaningless without break.
Sorry, this was worded confusingly. "else: triggers when the loop
terminates normally, not simply in the case that there is no iterated
data".

-Mike

Sep 29 '06 #10
On 9/29/06, Johan Steyn <jo*********@gmail.comwrote:
On 29 Sep 2006 11:26:10 -0700, Klaas <mi********@gmail.comwrote:
else: does not trigger when there is no data on which to iterate, but
when the loop terminated normally (ie., wasn't break-ed out). It is
meaningless without break.

The else clause *is* executed when there is no data on which to iterate.
Your example even demonstrates that clearly:
Yes--there is a missing "just" in that sentence.

-Mike
Sep 29 '06 #11
On 9/29/06, Johan Steyn <jo*********@gmail.comwrote:
I agree that it is meaningless without a break statement, but I still find
it useful when I want to determine whether I looped over the whole list or
not. For example, if I want to see whether or not a list contains an odd
number:

for i in list:
if i % 2 == 1:
print "Found an odd number."
break
else:
print "No odd number found."

Without the else clause I would need to use an extra variable as a "flag"
and check its value outside the loop:
You can use generator comprehension:

if (i for i in list if i % 2 == 1):
print "Found an odd number."
else:
print "No odd number found."

I *think* any() should also work:

if any(i % 2 == 1 in list):
....

And so on. For every use of the for/else clause there exists a better
alternative. Which sums up my opinion about the construct -- if you
are using it, there's something wrong with your code.

--
mvh Björn
Sep 29 '06 #12
bj*****@gmail.com wrote:
And so on. For every use of the for/else clause there exists a better
alternative. Which sums up my opinion about the construct -- if you
are using it, there's something wrong with your code.
How do you transform this?

height = 0
for block in stack:
if block.is_marked():
print "Lowest marked block is at height", height
break
height += block.height
else:
raise SomeError("No marked block")

-M-

Sep 29 '06 #13
Matthew Woodcraft <ma******@chiark.greenend.org.ukwrites:
How do you transform this?

height = 0
for block in stack:
if block.is_marked():
print "Lowest marked block is at height", height
break
height += block.height
else:
raise SomeError("No marked block")
Untested:

all_heights = [block.height for block in stack if block.is_marked()]
if all_heights:
height = sum(all_heights)
else:
raise SomeError("No marked block")

Alternatively (lower memory usage for large list):

all_heights = (block.height for block in stack if block.is_marked())
try:
height = all_heights.next()
height += sum(all_heights)
except StopIteration:
raise SomeError("No marked block")
Sep 29 '06 #14
Paul Rubin enlightened us with:
>height = 0
for block in stack:
if block.is_marked():
print "Lowest marked block is at height", height
break
height += block.height
else:
raise SomeError("No marked block")

all_heights = [block.height for block in stack if block.is_marked()]
if all_heights:
height = sum(all_heights)
else:
raise SomeError("No marked block")

Alternatively (lower memory usage for large list):

all_heights = (block.height for block in stack if block.is_marked())
try:
height = all_heights.next()
height += sum(all_heights)
except StopIteration:
raise SomeError("No marked block")
I must say that the for/else construct is a LOT more readable than the
rewritten alternatives.

Sybren
--
Sybren Stüvel
Stüvel IT - http://www.stuvel.eu/
Sep 30 '06 #15
Sybren Stuvel wrote:
I must say that the for/else construct is a LOT more readable than the
rewritten alternatives.
+1

I just wish it had a more intuitive name like "after:" or "then:", as
"else:" seems like a choice between the loop and the other block (but
really the choice is between StopIteration and break).

Regards,
Jordan

Sep 30 '06 #16
Sybren Stuvel <sy*******@YOURthirdtower.com.imaginationwrites:
I must say that the for/else construct is a LOT more readable than the
rewritten alternatives.
They are all pretty ugly. I prefer the genexp version with a
hypothetical "is_empty" function:

all_heights = (block.height for block in stack if block.is_marked())
if is_empty(all_heights):
raise SomeError("No marked block")
heights = sum(all_heights)

Python generators don't really work the right way for this though.

I've been fooling around with Haskell, so these kinds of constructions
seems more natural to me than explicit for loops.
Sep 30 '06 #17
Sybren Stuvel wrote:
Paul Rubin enlightened us with:
>>height = 0
for block in stack:
if block.is_marked():
print "Lowest marked block is at height", height
break
height += block.height
else:
raise SomeError("No marked block")

all_heights = [block.height for block in stack if block.is_marked()]
if all_heights:
height = sum(all_heights)
else:
raise SomeError("No marked block")

Alternatively (lower memory usage for large list):

all_heights = (block.height for block in stack if block.is_marked())
try:
height = all_heights.next()
height += sum(all_heights)
except StopIteration:
raise SomeError("No marked block")

I must say that the for/else construct is a LOT more readable than the
rewritten alternatives.
I like

def blocks_til_mark(stack):
for block in stack:
if block.is_marked():
return
yield block
raise SomeError
height = sum(block.height for block in blocks_til_mark(stack))

Peter
Sep 30 '06 #18
Paul Rubin wrote:
Sybren Stuvel <sy*******@YOURthirdtower.com.imaginationwrites:
>I must say that the for/else construct is a LOT more readable than the
rewritten alternatives.

They are all pretty ugly. I prefer the genexp version with a
hypothetical "is_empty" function:

all_heights = (block.height for block in stack if block.is_marked())
if is_empty(all_heights):
raise SomeError("No marked block")
Such a function would have to rebind the generator:

def check_empty(items):
items = iter(items)
try:
first = items.next()
except StopIteration:
return False
return chain([first], items)

all_heights = check_empty(all_heights)
if not all_heights:
raise SomeError
heights = sum(all_heights)

Python generators don't really work the right way for this though.
You can make it work, but the result tends to be messy:

from itertools import chain

def raiseiter(exc, *args):
raise exc(*args)
yield None # unreachable
def stop():
raise StopIteration

height = sum(block.height for block in chain(stack, raiseiter(SomeError)) if
(not block.is_marked()) or stop())

Peter
Sep 30 '06 #19
Peter Otten <__*******@web.dewrites:
I like

def blocks_til_mark(stack):
for block in stack:
if block.is_marked():
return
yield block
raise SomeError
height = sum(block.height for block in blocks_til_mark(stack))
Oh my, I realize now that I mis-read the original, and my examples
were all wrong. Shows how the explicit loop isn't necessarily so
clear ;-). Note that unlike the original, the loop above fails to set
height = 0 in the case where the exception gets raise.

I'd maybe just scan the stack twice. The rescan is needed only if
there can be blocks with height <= 0. Otherwise, you can just raise
SomeError if height == 0:

height = sum(b.height for b in
itertools.takewhile(lambda: not block.is_marked(), stack))

if height == 0 and True not in (b.is_marked() for b in stack):
raise SomeError
Sep 30 '06 #20
Peter Otten <__*******@web.dewrites:
all_heights = (block.height for block in stack if block.is_marked())
if is_empty(all_heights):
raise SomeError("No marked block")

Such a function would have to rebind the generator:
Yeah, that's what I mean about generators not working the right way.
You can make it work, but the result tends to be messy:
I think it's better underneath, but still syntactically ugly, to just
defer the generator creation:

all_heights = lambda:
(block.height for block in stack if block.is_marked())
if is_empty(all_heights ()):
raise SomeError("No marked block")
height = sum(all_heights ())

Now sum and is_empty see two separate generators, so is_empty is
straightforward:

def is_empty(gen):
try:
gen.next()
return True
except StopIteration:
return False
Sep 30 '06 #21
Paul Rubin wrote:
Peter Otten <__*******@web.dewrites:
all_heights = (block.height for block in stack if
block.is_marked()) if is_empty(all_heights):
raise SomeError("No marked block")

Such a function would have to rebind the generator:

Yeah, that's what I mean about generators not working the right way.
>You can make it work, but the result tends to be messy:

I think it's better underneath, but still syntactically ugly, to just
defer the generator creation:

all_heights = lambda:
(block.height for block in stack if
block.is_marked())
You still need the stop() trick to omit the heights after the marked block.
if is_empty(all_heights ()):
raise SomeError("No marked block")
height = sum(all_heights ())

Now sum and is_empty see two separate generators, so is_empty is
straightforward:

def is_empty(gen):
try:
gen.next()
return True
except StopIteration:
return False
Alternatively you can turn all_heights into a list (comprehension) which
makes the test trivial.

I think it will be interesting to see how Python 3000's emphasis on
iterators will affect overall code complexity.

Peter
Sep 30 '06 #22
Peter Otten <__*******@web.dewrites:
all_heights = lambda:
(block.height for block in stack if
block.is_marked())

You still need the stop() trick to omit the heights after the marked block.
Yeah, that code was based on my earlier mis-read of the original post.
How's this:

def blocks_until_mark():
return itertools.takewhile(lambda block:\
not block.is_marked(), \
stack)

height = sum(b.height for b in blocks_until_mark())
if is_empty(blocks_until_mark()):
raise SomeError("No marked block")
Alternatively you can turn all_heights into a list (comprehension) which
makes the test trivial.
Yes, I felt it wasn't in the spirit of the thing to use that memory.
I think it will be interesting to see how Python 3000's emphasis on
iterators will affect overall code complexity.
We will need more iterator primitives, which are still evolving.
Sep 30 '06 #23
me**********@gmail.com wrote:
I'm wondering if anyone has ever found a practical use for the else
branch?
Say you have code that looks like this:

if command.startswith("set"):
do_set_action(command)
elif command.startswith("input"):
do_input_action(command)
elif command.startswith("print"):
do_print_action()
else:
do_general_action()

Now, during refactoring, we note that there's a lot of similarity in
all those if clauses that we can exploit to simplify the code. Let's
ignore the final else clause for now, since it's not similar to the if
and elif clauses (it has no test). We define a mapping of prefixes to
actions, and rewrite the if...elif as a for loop:

command_map = (
("set",do_set_action),
("input",do_input_action),
("print",do_print_action)
)

for keyword,action in command_map:
if command.startswith(keyword):
action(command)
break

Ok, this works great. Now let's come back to that else clause: how do
we translate default case to the for loop? Well, I guess we could set
some sort of flag indicating we got a match.... But wait! We don''t
have to! We can just leave the else clause there as-is, and it'll
work. The for loop here is quite literally a drop-in replacement for
the if...elif...elif, even going so far as to allow the same else
clause.

for keyword,action in command_list:
if command.startswith(keyword):
action(command)
break
else:
do_general_action()
Moral of the story: there are two ways to do a linear search (or linear
sequence of tests): either an unrolled sequence of if...elif...elif
clauses, or a rolled up for loop with a break. Either way you do it,
you can tack on an else clause for when you don't find anything.
Carl Banks

Sep 30 '06 #24
How do you transform this?
>
height = 0
for block in stack:
if block.is_marked():
print "Lowest marked block is at height", height
break
height += block.height
else:
raise SomeError("No marked block")
def get_height_of_first_marked_bock(stack):
height = 0
for block in stack:
if block.is_marked():
return height
height += block.height
raise SomeError("No marked block")

height = get_height_of_first_marked_block(stack)
print "Lowest marked block is at height", height

Yes, this transformation is one line longer, but the control flow is
much easier to understand. In general, using the for/else clause mixes
the retrieval and the usage of the element. Consider this:

for item in list:
if somecond(item):
A) do something with item
break
else:
B) exceptional code when somecond() doesnt match anything in list

The code that you write in the positions A and B really are misplaced.
They arent part of the iteration of list. The two tasks, find item and
do something with item should be separated.

def find_item(list):
for item in list:
if somecond(item):
return item
return None # OR raise an exception

item = find_item(list)
if item:
A) do something with item
else:
B) exceptional code

This is, IMHO, much better style.

--
mvh Björn
Sep 30 '06 #25
BJörn Lindqvist wrote:
The code that you write in the positions A and B really are misplaced.
They arent part of the iteration of list. The two tasks, find item and
do something with item should be separated.
I think it is useful to have them joined. Consider a contrived example:

for i in (1,2,3,0,5,6):
try:
print 10 / i
except:
print 'Error in data'
break
else:
print 'Data processed cleanly'

Yes, you could use a flag variable instead:

done = 1
for i in (1,2,3,0,5,6):
try:
print 10 / i
except:
print 'Error in data'
done = 0
break
if done:
print 'Data processed cleanly'

....but that is not as clean imo.

Regards,
Jordan

Sep 30 '06 #26

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

33
by: Diez B. Roggisch | last post by:
Hi, today I rummaged through the language spec to see whats in the for ... else: for me. I was sort of disappointed to learn that the else clauses simply gets executed after the loop-body -...
18
by: Guinness Mann | last post by:
Greetings, I think I saw an article yesterday in which you told someone not to make an Identity column a primary key. I seem to remember you saying something like "It undermines the entire...
3
by: David L | last post by:
Hi, I am wondering that whether the fact that as more tools/environments/products support XML, then the need for knowing XML itself gets less important. I am comparing xml to assembler. IT...
19
by: William Wisnieski | last post by:
Hello Everyone, I have a main form with a datasheet subform that I use to query by form. After the user selects two criteria on the main form and clicks the cmdShowResults button on the main...
9
by: DFS | last post by:
You might also find other uses ========================================================= Public Function getSelections(selType As String, selSeparator As Boolean, selList As ListBox, selCol As...
9
by: dave_140390 | last post by:
Hi, Is there a clean way to determine at compile-time whether your compiler supports the __func__ feature? I mean, something similar to the following (which tests for the existence of macro...
30
by: MikeC | last post by:
Good People, I'm writing a backup utility that uses a chdir() to go into the source directory (in which the files reside that I want to back up), so I don't want to use chdir() to get into the...
5
by: nospam_news | last post by:
When language changes make old code uncompilable, that's not what is called protection of investment. New compilers (g++ 3.2.3) reject classes where methods throw the class they belong to. gcc...
1
by: almurph | last post by:
Hi everyone, Concerning the Needleman-Wunsch algorithm (cf. http://en.wikipedia.org/wiki/Needleman-Wunsch_algorithm) I have noticed a possible loop. Inside the algorithm there is an...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.