Ah well, time for the answer I guess... Assuming anybody cares. (^_^)
The first one is pretty straightforward - the function prints one
and four
and returns 4
. It's logical if you think about it - finally
blocks are guaranteed to execute last, and this includes after a return
statement, but it might seem a little odd to some people that putting a return
in a finally
block can "override" the return value of a function.
As an aside, the else
clause would have normally executed (unless an exception was thrown), but the return
statement in the body of the try
block prevented that - the finally
block is the only one guaranteed to run. This behaviour is mentioned in the penultimate paragraph of the Python reference docs for the try
statement. For bonus fun, guess what this function returns:
def func():
for i in xrange(5):
try:
return i
finally:
break
The second example is a little quirkier. Those moderately familiar with Python will know that the is
operator differs from ==
in that it checks for referential equality as opposed to value equality (i.e. whether the two arguments refer to the same object as opposed to whether the objects hold equivalent values). So it seems a little odd that any two integers would ever return True
for an is
check.
As it turns out, however, Python has a quirky little optimisation where "small" integers are in fact singletons, much as None
is (all references to None
refer to the same global singleton object, which is why you can use the is
operator to compare it - indeed, that's considered best practice). I assume this is done to speed up common cases such as loops, which would tend to use small values, but I'm not sure. Of course, this is a CPython implementation issue and should never be relied upon. Indeed, the threshold of what counts as "small" has changed in different Python versions.
Hope that was at least slightly interesting!