Re: for: else: - any practical uses for the else clause?
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/ -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Sybren Stuvel [EMAIL PROTECTED] writes: 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Paul Rubin wrote: Sybren Stuvel [EMAIL PROTECTED] writes: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Peter Otten [EMAIL PROTECTED] writes: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Peter Otten [EMAIL PROTECTED] writes: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Paul Rubin wrote: Peter Otten [EMAIL PROTECTED] writes: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Peter Otten [EMAIL PROTECTED] writes: 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
[EMAIL PROTECTED] 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
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. -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
On 29 Sep 2006 11:26:10 -0700, Klaas [EMAIL PROTECTED] wrote: else: does not trigger when there is no data on which to iterate, butwhen 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: for x in []:... print 'nothing'... else:... print 'done' ...done The else clause is executed because the loop still terminates normally with an empty list - albeit without having looped at all. 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: found = False for i in list: if i % 2 == 1: print Found an odd number. found = True break if not found: print No odd number found. OK, so using else only saves me 2 lines and a variable - not much to write home about, but I still like it. Johan. -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
On 9/29/06, Johan Steyn [EMAIL PROTECTED] wrote: On 29 Sep 2006 11:26:10 -0700, Klaas [EMAIL PROTECTED] 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. 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
On 9/29/06, Johan Steyn [EMAIL PROTECTED] wrote: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
[EMAIL PROTECTED] 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- -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Matthew Woodcraft [EMAIL PROTECTED] writes: 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) -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Ben Sizer [EMAIL PROTECTED] wrote: [EMAIL PROTECTED] 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 -- [EMAIL PROTECTED] -- 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
[EMAIL PROTECTED] wrote: metaperl I'm wondering if anyone has ever found a practical use for the metaperl else 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 -- http://mail.python.org/mailman/listinfo/python-list
for: else: - any practical uses for the else clause?
A very old thread: http://groups.google.com/group/comp.lang.python/browse_frm/thread/2c5022e2b7f05525/1542d2041257c47e?lnk=gstq=for+elsernum=9#1542d2041257c47e discusses the optional else: clause of the for statement. I'm wondering if anyone has ever found a practical use for the else branch? -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
metaperl I'm wondering if anyone has ever found a practical use for the metaperl else 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
[EMAIL PROTECTED] a écrit : A very old thread: http://groups.google.com/group/comp.lang.python/browse_frm/thread/2c5022e2b7f05525/1542d2041257c47e?lnk=gstq=for+elsernum=9#1542d2041257c47e 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
[EMAIL PROTECTED] a écrit : A very old thread: http://groups.google.com/group/comp.lang.python/browse_frm/thread/2c5022e2b7f05525/1542d2041257c47e?lnk=gstq=for+elsernum=9#1542d2041257c47e 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: for: else: - any practical uses for the else clause?
Amaury Forgeot d'Arc wrote: [EMAIL PROTECTED] a écrit : A very old thread: http://groups.google.com/group/comp.lang.python/browse_frm/thread/2c5022e2b7f05525/1542d2041257c47e?lnk=gstq=for+elsernum=9#1542d2041257c47e 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 -- http://mail.python.org/mailman/listinfo/python-list