关于生成器在类中作用域混乱的问题
0

第一种方式:

python 2:

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

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

result:

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

python3 result: NameError: name 'x' is not defined

第二种方式:

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

a = A()
print(a.list)

这种方式在Python2 中是可以的, 但是在Python3 里面是不行的。

第三种方式

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

上面代码在Python3 & Python2 的model级别都是通用的

第四种方式

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

print(list(gen))

这个也在两种方式里面通用

仅仅当生成器作为类变量时,他会在类外部执行(因为在运行时会评估生成器??), 并检查当前作用域中x的引用。 由于x在该范围内未初始化, 因此会引发错误

讨论数量: 5

作为类变量时生成器调用了 globals(),之后没有调用 locals(),不过在函数中,这两个都没调用。

如果真想在类变量中用生成器,可以结合lambda,

class A(object):
    list = lambda e=c: [e.x for _ in range(3)]
    x = 4
    c = x

指定任何一个类变量都可以,指定后会变成此类...也就是lambdae 参数不管指定 x 还是 c 返回的都是 <__main__.A object at 0x0000000000984BA8>...

还有个奇怪的地方是,如果

list = lambda e=c: [e.x for _ in range(3)]

放在

x = 4
c = x

前面的时候,可以指定 e = c但不能指定 e = x...
不知道为什么.... :joy:

2个月前
katsueiki

@Cyrbuzz 虽然lambda也可以, 但是直接用A.x 就可以搞了啊。。。。而且我试了一下,放在后面那个是不行的

file

2个月前

@katsueiki joy:

发现自己有点傻... lambda 也是函数定义,第一个参数当然是 self 实例对象啦= =。

直接在生成器里用 A.x 吗?貌似不行吧,A 都还没定义出来。

2个月前
katsueiki

@Cyrbuzz 可以的,你可以试试

2个月前

@katsueiki

作为类属性不行...

放在外面可以

2个月前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!