为什么在列表理解中没有定义一个类变量,而在列表理解中又定义了一个类变量呢? [英] Why is one class variable not defined in list comprehension but another is?

查看:55
本文介绍了为什么在列表理解中没有定义一个类变量,而在列表理解中又定义了一个类变量呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚阅读了以下问题的答案:从类定义中的列表理解中访问类变量

I just read the answer to this question: Accessing class variables from a list comprehension in the class definition

这有助于我理解为什么以下代码导致NameError: name 'x' is not defined:

It helps me to understand why the following code results in 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)

之所以出现NameError,是因为在列表理解的特殊范围内未定义x.但是我不明白为什么下面的代码能正常工作.

The NameError occurs because x is not defined in the special scope for list comprehension. But I am unable to understand why the following code works without any error.

class A:
    x = 1
    data = [0, 1, 2, 3]
    new_data = [i for i in data]
    print(new_data)

我得到输出[0, 1, 2, 3].但是我一直期待这个错误:NameError: name 'data' is not defined,因为我希望像在上一个示例中一样,名称x没有在列表理解的范围内定义,类似地,名称data也不会在列表理解的范围内定义.范围.

I get the output [0, 1, 2, 3]. But I was expecting this error: NameError: name 'data' is not defined because I was expecting just like in the previous example the name x is not defined in the list comprehension's scope, similarly, the name data would not be defined too in the list comprehension's scope.

您能不能帮助我理解为什么x不是在列表理解的范围内定义的,而data是在列表理解的范围内定义的?

Could you please help me to understand why x is not defined in the list comprehension's scope but data is?

推荐答案

data是列表理解的;它是传递给创建的嵌套作用域的一个参数.

data is the source of the list comprehension; it is the one parameter that is passed to the nested scope created.

列表理解中的所有内容都在单独的范围(基本上是作为一个函数)中运行,除了最左边的for循环中使用的可迭代项.您可以在字节码中看到这一点:

Everything in the list comprehension is run in a separate scope (as a function, basically), except for the iterable used for the left-most for loop. You can see this in the byte code:

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

像函数一样调用<listcomp>代码对象,并以iter(data)作为参数传递(CALL_FUNCTION用1个位置参数,即GET_ITER结果执行).

The <listcomp> code object is called like a function, and iter(data) is passed in as the argument (CALL_FUNCTION is executed with 1 positional argument, the GET_ITER result).

<listcomp>代码对象将查找该参数:

The <listcomp> code object looks for that one argument:

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

LOAD_FAST调用引用传入的第一个也是唯一的位置参数;之所以在这里未命名,是因为从来没有一个函数定义来为其命名.

The LOAD_FAST call refers to the first and only positional argument passed in; it is unnamed here because there never was a function definition to give it a name.

在列表理解(或集合或字典理解,或生成器表达式)中使用的其他任何名称都是局部变量,闭包或全局变量,而不是参数.

Any additional names used in the list comprehension (or set or dict comprehension, or generator expression, for that matter) are either locals, closures or globals, not parameters.

这篇关于为什么在列表理解中没有定义一个类变量,而在列表理解中又定义了一个类变量呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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