Variable Scope In Generators In Classes

后端 未结 3 873
野性不改
野性不改 2020-12-17 19:17

I think that I know how variables and generators work in Python well.
However, the following code makes me confused.

from __future__ import print_functio         


        
相关标签:
3条回答
  • 2020-12-17 20:15

    As stated in other answer, it is True that it happens because it is static variable. But it is not just that property that restricts your code to work. Actual reason is the scope of the variable and the scope in which it executes. For example, create a class as:

    class A(object):
        x = 999999
        y = x +1
    

    If you access it's class properties A.x and A.y, it will work. Because, at the time of initializing y, x is replaced the value in expression x+1. As the scope of x was within the class.

    However this doesn't happens in the case of generators. i.e. in your example:

    class A(object):
        x = 4
        gen = (x for _ in range(3))
    

    When you do list(a.gen), it is executed outside the class (as generators are evaluated during run-time) and checks for the reference of x in the current scope. Since, x it is not initialized in that scope, it throws error.

    When you explicitly initialize x=4, it works because now the generator expression has value of x to which it could use.

    In order to make your generator expression work, as stated by others you have to define it like:

    class A(object):
        x = 4
        gen = (A.x for _ in range(3))
        #      ^ mentioning `A.x` is the value to access
    
    0 讨论(0)
  • 2020-12-17 20:21

    Because x is a class attribute (static variable), which you access like,

    Example

    >>> class A(object):
    ...     x = 4
    ...     gen = (A.x for _ in range(3))
    ...
    >>> a = A()
    >>> list(a.gen)
    [4, 4, 4]
    

    Here even gen is another class attribute, which means that,

    >>> b = A()
    >>> list(b.gen)
    []
    

    This gives empty because the generator has already exhausted.


    This happens because the generator is evaluated only when you issue a.gen, when it won't be able to resolve the name x.

    0 讨论(0)
  • 2020-12-17 20:22

    That is because x is a class variable. In python, class variables has to be accessed with self (ex. access from a instance method) or the class name.

    class A(object):
        x = 4
        gen = (A.x for _ in range(3))
    
        def call_me(self):
            print self.x
    
    a = A()
    a.call_me()
    print list(a.gen)
    

    For more detailed discussion see Static class variables in Python and Why is Python class not recognizing static variable

    0 讨论(0)
提交回复
热议问题