سؤال

Here is some code that raise a NameError:

class Foo:
    a = [1,2,3,4,5]
    b = all(i for i in a) # works fine !
    c = [2,3,4]
    d = all(i in a for i in c) # raises NameError : name 'a' is not defined

I am quite confused by that --;

Thanks !

هل كانت مفيدة؟

المحلول

See this previous question, which is similar but not identical.

As stated in that answer:

classes don't have a lexical scope (actually, in either Python 2 or Python 3). Instead, they have a local namespace that does not constitute a scope. This means that expressions within the class definition have access to the content of the namespace [...] but scopes introduced within the body of the class do not have access to its namespace

In a generator expression, the for clause is in the enclosing scope/namespace, but the target expression is in a new scope created by the generator expression. This new scope doesn't have access to the enclosing class scope.

In short, your examples work and fail for the same reason that this works:

class Foo(object):
    a = 2
    def method(self, x=a):
        print x

but this fails:

class Foo(object):
    a = 2
    def method(self, x):
        print a

The for clause of the generator expression is similar scopewise to the argument specification of a method: it executes in the enclosing namespace. But the target expression of the genexp is similar to the method body: it executes in its own scope, which does not have access to the class namespace.

(In Python 2, using a list comprehension instead of a generator comprehension will work because list comprehensions do not createa new scope in Python 2. This was considered a wart and was changed in Python 3, so in Python 3 neither one will work.)

نصائح أخرى

The real answer to this question is what BrenBarn wrote.

In Python 2.7 what you wrote didn't work but if you change it to:

class Foo:
    a = [1,2,3,4,5]
    b = all(i for i in a) # works fine !
    c = [2,3,4]
    d = all([i in a for i in c]) #works fine too!

it will work as expected. The reason being as pointed out by BrenBarn that list comprehensions do not create a new scope in Python 2.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top