类中生成器的可变范围 [英] Variable Scope In Generators In Classes

查看:55
本文介绍了类中生成器的可变范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我知道变量和生成器如何在Python中很好地工作.
但是,以下代码使我感到困惑.

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

from __future__ import print_function

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

a = A()
print(list(a.gen))

运行代码(Python 2)时,它说:

When run the code (Python 2), it says:

Traceback (most recent call last):
  File "Untitled 8.py", line 10, in <module>
    print(list(a.gen))
  File "Untitled 8.py", line 6, in <genexpr>
    gen = (x for _ in range(3))
NameError: global name 'x' is not defined

在Python 3中,它表示NameError: name 'x' is not defined
但是,当我运行时:

In Python 3, it says NameError: name 'x' is not defined
but, when I run:

from __future__ import print_function

class A(object):
    x = 4
    lst = [x for _ in range(3)]

a = A()
print(a.lst)

该代码在Python 3中不起作用,但是在Python 2或类似的函数中起作用

The code doesn't work in Python 3, but it does in Python 2, or in a function like this

from __future__ import print_function

def func():
    x = 4
    gen = (x for _ in range(3))
    return gen

print(list(func()))

此代码在Python 2和Python 3或模块级别上均能很好地工作

This code works well in Python 2 and Python 3 or on the module level

from __future__ import print_function

x = 4
gen = (x for _ in range(3))

print(list(gen))

该代码在Python 2和Python 3中也能很好地工作.

The code works well in Python 2 and Python 3 too.

为什么在class中出错?

推荐答案

如其他答案所述,由于它是静态变量,因此发生在True上.但是,不仅仅是该属性限制了您的代码正常工作.实际原因是变量的范围及其执行范围.例如,创建一个类为:

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

如果访问它的类属性A.xA.y,它将起作用.因为在初始化y时,x被替换了表达式x+1中的值.因为x的范围在该类之内.

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))

当您执行list(a.gen)时,它会在类外部执行(因为生成器会在运行时进行评估),并在当前作用域中检查x的引用.由于x尚未在该范围内初始化,因此会引发错误.

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.

显式初始化x=4时,它可以工作,因为现在生成器表达式的值可以使用x.

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

这篇关于类中生成器的可变范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆