Lon*_*ner 18 python scope list-comprehension python-internals python-3.4
我刚刚阅读了这个问题的答案:从类定义中的列表解析中访问类变量
它帮助我理解为什么以下代码导致NameError: name 'x' is not defined
:
class A:
x = 1
data = [0, 1, 2, 3]
new_data = [i + x for i in data]
print(new_data)
Run Code Online (Sandbox Code Playgroud)
在NameError
因为出现x
在列表理解的特殊范围没有定义.但我无法理解为什么下面的代码没有任何错误.
class A:
x = 1
data = [0, 1, 2, 3]
new_data = [i for i in data]
print(new_data)
Run Code Online (Sandbox Code Playgroud)
我得到了输出[0, 1, 2, 3]
.但是我期待这个错误:NameError: name 'data' is not defined
因为我期望就像在前面的例子中一样,名称x
没有在列表推导的范围中定义,类似地,名称data
也不会在列表推导的范围中定义.
能否帮助我理解为什么x
列表理解范围没有定义但是data
?
Mar*_*ers 17
data
是列表理解的来源 ; 它是传递给创建的嵌套作用域的一个参数.
除了用于最左边for
循环的迭代之外,列表推导中的所有内容都在一个单独的作用域中运行(基本上作为一个函数).你可以在字节码中看到这个:
>>> def foo():
... return [i for i in data]
...
>>> dis.dis(foo)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x105390390, file "<stdin>", line 2>)
3 LOAD_CONST 2 ('foo.<locals>.<listcomp>')
6 MAKE_FUNCTION 0
9 LOAD_GLOBAL 0 (data)
12 GET_ITER
13 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
16 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
的<listcomp>
代码对象被称为像的功能,并且iter(data)
被传递在作为参数(CALL_FUNCTION
与1个位置参数,执行的GET_ITER
结果).
该<listcomp>
代码对象将查找一个参数:
>>> dis.dis(foo.__code__.co_consts[1])
2 0 BUILD_LIST 0
3 LOAD_FAST 0 (.0)
>> 6 FOR_ITER 12 (to 21)
9 STORE_FAST 1 (i)
12 LOAD_FAST 1 (i)
15 LIST_APPEND 2
18 JUMP_ABSOLUTE 6
>> 21 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
所述LOAD_FAST
呼叫是指在通过了第一和唯一的位置参数; 它在这里未命名,因为从来没有一个函数定义给它起一个名字.
列表推导中使用的任何其他名称(或者set或dict comprehension,或者生成器表达式)都是locals,closures或globals,而不是参数.
归档时间: |
|
查看次数: |
1974 次 |
最近记录: |