This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Problem with if clause in generator expression on class level
Type: behavior Stage:
Components: Interpreter Core, Library (Lib), macOS, Regular Expressions, Tests, Tkinter, Unicode, Windows, XML Versions: Python 2.5
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: cito, georg.brandl
Priority: normal Keywords:

Created on 2008-03-02 17:43 by cito, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (6)
msg63182 - (view) Author: Christoph Zwerschke (cito) * Date: 2008-03-02 17:43
The following code throws a NameError which seems to be a bug existing
since Python 2.4 up to the current 2.5.2.

class A:
    a = 'test'
    [c for c in a]
    (c for c in a)
    tuple(c for c in a)
    [c for c in a if c in a]
    (c for c in a if c in a)
    tuple(c for c in a if c in a) # --> NameError
msg63183 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2008-03-02 17:56
This may seem odd, but is correct as per spec.

The "if c in a" part is executed in a scope of its own, and class scopes
don't contribute to nested scoping.
msg63184 - (view) Author: Christoph Zwerschke (cito) * Date: 2008-03-02 19:46
Thanks for the quick explanation. I understand that class scopes don't
extend and this is documented behavior.

However, the question is why the if clause is executed in a scope of its
own and where this is documented.

You would expect that the problematic generator expression is equivalent
to the following code which works fine:

class A:
    a = 'test'
    def __g(a):
        for c in a:
            if c in a:
                yield c
    tuple(__g(a))
msg63187 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2008-03-02 21:07
The actual equivalent would be

class A:
    a = 'test'
    def __g(_x):
        for c in _x:
            if c in a:
                yield c
    tuple(__g(a))

i.e. the outmost iterator is evaluated in the enclosing scope; not the
if clause is in its own scope, but the whole genexp.
msg63189 - (view) Author: Christoph Zwerschke (cito) * Date: 2008-03-02 22:27
Thanks, this now makes sense to me. You're right, it's rather an ugly
wart than a bug.

But I think the Python reference needs to be improved to make this clear
enough.

How about the following proposed addtions (in square brackets) to
section 5.2.5 (http://docs.python.org/ref/genexpr.html):

"Variables used in the generator expression are evaluated lazily [in the
scope of the generator function] when the next() method is called for
[the] generator object (in the same fashion as normal generators).
However, the leftmost for clause is immediately evaluated [in the
current scope] so that [an] error produced by it can be seen before any
other possible error in the code that handles the generator expression.
Subsequent for [and if] clauses cannot be evaluated immediately since
they may depend on the previous for loop."
msg63234 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2008-03-03 21:32
Good idea! I've committed these changes in r61212.
History
Date User Action Args
2022-04-11 14:56:31adminsetgithub: 46470
2008-03-03 21:32:40georg.brandlsetmessages: + msg63234
2008-03-02 22:27:56citosetmessages: + msg63189
2008-03-02 21:07:46georg.brandlsetmessages: + msg63187
2008-03-02 19:46:59citosetmessages: + msg63184
2008-03-02 17:56:45georg.brandlsetstatus: open -> closed
resolution: wont fix
messages: + msg63183
nosy: + georg.brandl
2008-03-02 17:43:31citocreate