Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python lambda+exec scope error

In the following code, the first reference to iszero succeeds but the second (inside the lambda) gives a NameError: 'iszero' is not defined.

myblock = """
def iszero(x):
    return x == 0

print(iszero(0)) #works

args = [0, 1, 2]

flts = list(filter(lambda f:(not iszero(f)), args)) #NameError
"""

mylocals = {}
exec(myblock, globals(), mylocals)
like image 948
user5090812 Avatar asked Oct 22 '25 15:10

user5090812


1 Answers

I'd classify this as a Python bug (at very least a documentation bug).

You should open an issue in the Python bug tracker...

The problem is not related to lambda, looks like closures created by exec when a locals dictionary is provided don't have the correct scope resolution.

Curiously enough PyPy has the same behavior, so may be this is indeed the expected result (I can't understand where it's documented, however).

EDIT

It may seem strange but this is the expected behavior.

The reason is that when exec is provided both a global and local dictionary the code is executed like if it was in the body of a class definition.

That context is quite specific and closures created in it cannot access names defined in the scope of the class (that's why you need to use myclass.myattribute in methods to access class attributes - and that's a lookup that starts from global).

This strange behavior doesn't bite often because normally code at class definition scope just does simple assignments (for class-level attributes) and definitions (for methods) that doesn't try to capture those names.

like image 174
6502 Avatar answered Oct 25 '25 05:10

6502