Yield after the return in Python function.

Terry Reedy tjreedy at udel.edu
Mon Apr 5 15:00:53 EDT 2021


On 4/5/2021 1:53 PM, Chris Angelico wrote:
> On Tue, Apr 6, 2021 at 3:46 AM Terry Reedy <tjreedy at udel.edu> wrote:
>> *While 'a and not a' == False in logic, in Python it might raise
>> NameError.  But that would still mean that it is never True, making
>> 'yield 0' still unreachable.

When I wrote that, I knew I might be missing something else.

> And even just the lookup can have side effects, if your code is
> pathologically stupid.

Or pathologically clever.

>>>> class Wat(dict):
> ...     def __missing__(self, key):
> ...             global count
> ...             count -= 1
> ...             return count

'__missing__' is new since I learned Python.  I barely took note of its 
addition and have never used it.  Thanks for the example of what it can 
do.  One could also make it randomly return True or False.

>>>> count = 2
>>>> eval("print(a and not a)", Wat(print=print))
> True
> 
> So Python can't afford to treat this as dead code.

This gets to the point that logic and math are usually atemporal or at 
least static (as in a frozen snapshot), while computing is dynamic.  In 
algebra, the canon is that all instances of a variable are replaced by 
the same value.

Python *could* do the same for expresssions: load 'a' (in this case) 
once into a register or stack slot and use that value consistently 
throughout the expression.  Replacing the eval with the following exec 
has the same effect.

exec("tem=a; print(tem and not tem)", Wat(print=print))
# print False

In this example, one could disable the binding with __setitem__ 
(resulting in printing 0), but python code cannot disable internal 
register or stack assignments.

-- 
Terry Jan Reedy



More information about the Python-list mailing list