I am trying to figure out why there is an optional else block in for loops. I’ve never seen this in another language. What’s the use case that put this in the language!?
'Finally' equivalent for If/Elif statements in Python - Stack Overflow
When would I use 'else' and 'finally' in a try-except statement in python? - Stack Overflow
For/else, while/else, try/else.
How does the else clause work in a try/except/else/finally block?
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 == theflag:
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.
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 {}'.format(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
It can be done totally non-hackily like this:
def function(x,y,z):
if condition1:
blah
elif condition2:
blah2
else:
return False
#finally!
clean up stuff.
In some ways, not as convenient, as you have to use a separate function. However, good practice to not make too long functions anyway. Separating your logic into small easily readable (usually maximum 1 page long) functions makes testing, documenting, and understanding the flow of execution a lot easier.
One thing to be aware of is that the finally clause will not get run in event of an exception. To do that as well, you need to add try: stuff in there as well.
you can use try
try:
if-elif-else stuff
finally:
cleanup stuff
the exception is raised but the cleanup is done
Someone has ever seen or use this statements -else- in real situations. I'm trying to find examples, but allways seems to be a easier and cleaner way.
I just re-learned some Python fundamentals and found that I almost forgot that it's possible to add an else clause after try/except (and before finally).
I thought this else is no more than a catch-all version of the usual except clause, which catches those exceptions not specified in the preceding except statements.
So this is what I think it works like:
try:
x = items[1]
except IndexError:
... # maybe there are fewer than two elements
except TypeError:
... # maybe it's a generator or whatever does not support indexing
else:
... # any exceptions other than IndexError and TypeError. Like NameError, if items is not even definedwhich I think is the same as
try:
x = items[1]
except IndexError:
...
except TypeError:
...
except Exception:
... # this catches all other exceptions
But some answers on SO explain that else is used when the exception is raised in the previous except clauses. Is that one of the differences between the two snippets above? So it's like wrapping the try/except block in another try/except block?
I also wonder whether the else actually does what I think (as in the first snippet). Maybe not? It's not a catch-all except?