Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Monday, January 18, 2016

Why does python use 'else' after for and while loops?

Why does python use 'else' after for and while loops?


I understand how this construct works:

for i in range(10):      print(i)        if i == 9:          print("Too big - I'm giving up!")          break;  else:      print("Completed successfully")  

But I don't understand why else is used as the keyword here, since it suggests the code in question only runs if the for block does not complete, which is the opposite of what it does! No matter how I think about it, my brain can't progress seamlessly from the for statement to the else block. To me, continue or continuewith would make more sense (and I'm trying to train myself to read it as such).

I'm wondering how Python coders read this construct in their head (or aloud, if you like). Perhaps I'm missing something that would make such code blocks more easily decipherable?

Answer by Cat Plus Plus for Why does python use 'else' after for and while loops?


Because they didn't want to introduce a new keyword to the language. Each one steals an identifier and causes backwards compatibility problems, so it's usually a last resort.

Answer by pcalcao for Why does python use 'else' after for and while loops?


I read it something like:

If still on the conditions to run the loop, do stuff, else do something else.

Answer by jamylak for Why does python use 'else' after for and while loops?


You could think of it like, else as in the rest of the stuff, or the other stuff, that wasn't done in the loop.

Answer by Bjrn Lindqvist for Why does python use 'else' after for and while loops?


It's a strange construct even to seasoned Python coders. When used in conjunction with for-loops it basically means "find some item in the iterable, else if none was found do ...". As in:

found_obj = None  for obj in objects:      if obj.key == search_key:          found_obj = obj          break  else:      print 'No object found.'  

But anytime you see this construct, a better alternative is to either encapsulate the search in a function:

def find_obj(search_key):      for obj in objects:          if obj.key == search_key:              return obj  

Or use a list comprehension:

matching_objs = [o for o in objects if o.key == search_key]  if matching_objs:      print 'Found', matching_objs[0]  else:      print 'No object found.'  

It is not semantically equivalent to the other two versions, but works good enough in non-performance critical code where it doesn't matter whether you iterate the whole list or not. Others may disagree, but I personally would avoid ever using the for-else or while-else blocks in production code.

See also [Python-ideas] Summary of for...else threads

Answer by Lance Helsten for Why does python use 'else' after for and while loops?


A common construct is to run a loop until something is found and then to break out of the loop. The problem is that if I break out of the loop or the loop ends I need to determine which case happened. One method is to create a flag or store variable that will let me do a second test to see how the loop was exited.

For example assume that I need to search through a list and process each item until a flag item is found and then stop processing. If the flag item is missing then an exception needs to be raised.

Using the Python for...else construct you have

...    for i in mylist:      if i == theflag:          break      process(i)  else:      raise ValueError("List argument missing terminal flag.)    ...  

Compare this to a method that does not use this syntactic sugar:

...    flagfound = False  for i in mylist:      if i == the flag:          flagfound = True          break      process(i)    if not flagfound:      raise ValueError("List argument missing terminal flag.)    ...  

In the first case the raise is bound tightly to the for loop it works with. In the second the binding is not as strong and errors may be introduced during maintenance.

Answer by Ayan for Why does python use 'else' after for and while loops?


I think documentation has a great explanation of else, continue

"it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement."

source: https://docs.python.org/2/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops

Answer by Air for Why does python use 'else' after for and while loops?


There's an excellent presentation by Raymond Hettinger, titled "Transforming Code into Beautiful, Idiomatic Python," in which he briefly addresses the history of the for ... else construct. The relevant section is "Distinguishing multiple exit points in loops" starting at 15:50 and continuing for about three minutes. Here are the high points:

  • The for ... else construct was devised by Donald Knuth as a replacement for certain GOTO use cases
  • Reusing the else keyword made sense because "it's what Knuth used, and people knew, at that time, all for's had embedded an if and GOTO underneath, and they expected the else"
  • In hindsight, it should have been called "no break" (or possibly "nobreak"), and then it wouldn't be confusing1

So, if the question is, "Why don't they change this keyword?" then Cat Plus Plus probably gave the most accurate answer ? at this point, it would be too destructive to existing code to be practical. But if the question you're really asking is why else was reused in the first place, well, apparently it seemed like a good idea at the time.

Personally, I like the compromise of commenting # no break in-line wherever the else could be mistaken, at a glance, as belonging inside the loop. It's reasonably clear and concise. This option gets a brief mention in the summary that Bjorn linked at the end of his answer:

For completeness, I should mention that with a slight change in syntax, programmers who want this syntax can have it right now:

for item in sequence:      process(item)  else:  # no break      suite  

1Bonus quote from that part of the video: "Just like if we called lambda makefunction, nobody would ask, 'What does lambda do?'"

Answer by 0xc0de for Why does python use 'else' after for and while loops?


I read it like "When the iterable is exhausted completely, and the execution is about to proceed to the next statement after finishing the for, the else clause will be executed." Thus, when the iteration is broken by break, this will not be executed.

Answer by user44635 for Why does python use 'else' after for and while loops?


The easiest way I found to 'get' what the for/else did, and more importantly, when to use it, was to concentrate on where the break statement jumps to. The For/else construct is a single block. The break jumps out of the block, and so jumps 'over' the else clause. If the contents of the else clause simply followed the for clause, it would never be jumped over, and so the equivalent logic would have to be provided by putting it in an if. This has been said before, but not quite in these words, so it may help somebody else. Try running the following code fragment. I'm wholeheartedly in favour of the 'no break' comment for clarity.

for a in range(3):      print(a)      if a==4: # change value to force break or not          break  else: #no break  +10 for whoever thought of this decoration      print('for completed OK')    print('statement after for loop')  

Answer by Harsha Biyani for Why does python use 'else' after for and while loops?


Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement. This is exemplified by the following loop, which searches for prime numbers:

>>> for n in range(2, 10):  ...     for x in range(2, n):  ...         if n % x == 0:  ...             print n, 'equals', x, '*', n/x  ...             break  ...     else:  ...         # loop fell through without finding a factor  ...         print n, 'is a prime number'  ...     2 is a prime number  3 is a prime number  4 equals 2 * 2  5 is a prime number  6 equals 2 * 3  7 is a prime number  8 equals 2 * 4  9 equals 3 * 3  

Answer by NotAnAmbiTurner for Why does python use 'else' after for and while loops?


I know this is an old thread, but I am looking into the same question right now, and I'm not sure anyone has captured the answer to this question in the way I understand it.

For me, there are three ways of "reading" the else in For... else or While... else statements, all of which are equivalent, are:

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break) (presumably there is such a condition, or you wouldn't have a loop)

I think the key is that the else is pointless without the 'break', so a for...else includes:

for:      do stuff      conditional break # implied by else  else not break:      do more stuff  

So, essential elements of a for...else loop are as follows, and you would read them in plainer English as:

for:      do stuff      condition:          break  else: # read as "else not break" or "else not condition"      do more stuff  

As the other posters have said, a break is generally raised when you are able to locate what your loop is looking for, so the else: becomes "what to do if target item not located".

Example

You can also use exception handling, breaks, and for loops all together.

for x in range(0,3):      print("x: {}".format(x))      if x == 2:          try:              raise AssertionError("ASSERTION ERROR: x is {}".format(x))          except:              print(AssertionError("ASSERTION ERROR: x is {}".format(x)))              break  else:      print("X loop complete without error")  

Result

x: 0  x: 1  x: 2  ASSERTION ERROR: x is 2  ----------  # loop not completed (hit break), so else didn't run  

Example

Simple example with a break being hit.

for y in range(0,3):      print("y: {}".format(y))      if y == 2: # will be executed          print("BREAK: y is {}\n----------".format(y))          break  else: # not executed because break is hit      print("y_loop completed without break----------\n")  

Result

y: 0  y: 1  y: 2  BREAK: y is 2  ----------  # loop not completed (hit break), so else didn't run  

Example

Simple example where there no break, no condition raising a break, and no error are encountered.

for z in range(0,3):       print("z: {}".format(z))       if z == 4: # will not be executed           print("BREAK: z is {}\n".format(y))           break       if z == 4: # will not be executed           raise AssertionError("ASSERTION ERROR: x is {}".format(x))  else:       print("z_loop complete without break or error\n----------\n")  

Result

z: 0  z: 1  z: 2  z_loop complete without break or error  ----------  

Answer by 3rdWorldCitizen for Why does python use 'else' after for and while loops?


Since the technical part has been pretty much answered, my comment is just in relation with the confusion that produce this recycled keyword.

Being Python a very eloquent programming language, the misuse of a keyword is more notorious. The else keyword perfectly describes part of the flow of a decision tree, "if you can't do this, (else) do that". It's implied in our own language.

Instead, using this keyword with while and for statements creates confusion. The reason, our career as programmers has taught us that the else statement resides within a decision tree; its logical scope, a wrapper that conditionally return a path to follow. Meanwhile, loop statements have a figurative explicit goal to reach something. The goal is met after continuous iterations of a process.

if / else indicate a path to follow. Loops follow a path until the "goal" is completed.

The issue is that else is a word that clearly define the last option in a condition. The semantics of the word are both shared by Python and Human Language. But the else word in Human Language is never used to indicate the actions someone or something will take after something is completed. It will be used if, in the process of completing it, an issue rises (more like a break statement).

At the end, the keyword will remain in Python. It's clear it was mistake, clearer when every programmer tries to come up with a story to understand its usage like some mnemonic device. I'd have loved if they have chosen instead the keyword then. I believe that this keyword fits perfectly in that iterative flow, the payoff after the loop.

It resembles that situation that some child has after following every step in assembling a toy: And THEN what Dad?


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.