嵌套列表理解范围

2023-11-26

解释我的问题的最好方法是举一个例子:

示例.py:

class A(object):
    integers = [1, 2, 3]
    singles = [i for i in integers]

class B(object):
    integers = [1, 2, 3]
    pairs = [(i, j) for i in integers for j in integers]

当我在 python 2 下运行它时,它工作正常,但在 python 3 下我得到一个NameError上课B(但不是类A):

$ python example.py
Traceback (most recent call last):
  File "example.py", line 6, in <module>
    class B(object):
  File "example.py", line 8, in B
    pairs = [(i, j) for i in integers for j in integers]
  File "example.py", line 8, in <listcomp>
    pairs = [(i, j) for i in integers for j in integers]
NameError: global name 'integers' is not defined

为什么只上课B提出一个NameError为什么只在 Python 3 下?


类作用域在 Python 3 中有点奇怪,但这是有充分理由的。

在 Python 2 中,迭代变量 (i and j在您的示例中)泄漏出列表理解,并将包含在外部范围中。这是因为它们是在 Python 2 设计的早期开发的,并且基于显式循环。作为一个示例来说明这是如何意外的,请检查以下值B.i and B.j在 Python 2 中你没有收到错误!

在 Python 3 中,更改了列表推导式以防止这种泄漏。它们现在使用一个函数(有其自己的作用域)来实现,该函数被调用以生成列表值。这使得它们的工作方式与生成器表达式相同,而生成器表达式一直是隐藏的函数。

这样做的结果是,在类中,列表理解通常看不到任何类变量。这与无法直接查看类变量的方法是平行的(尽管self或明确的类名)。例如,调用下面类中的方法将给出相同的结果NameError您在列表理解中看到的异常:

class Foo:
    classvar = "bar"
    def blah(self):
        print(classvar) # raises "NameError: global name 'classvar' is not defined"

然而,有一个例外:第一个序列正在迭代for列表推导式的子句是在内部函数之外求值的。这就是为什么你的A类在 Python 3 中工作。它这样做是为了让生成器可以立即捕获不可迭代的对象(而不是仅当next调用它们并且运行它们的代码)。

但对内在不起作用for课堂上二级理解中的子句B.

如果您反汇编一些使用创建列表推导式的函数,您可以看到差异dis module:

def f(lst):
    return [i for i in lst]

def g(lst):
    return [(i, j) for i in lst for j in lst]

这是拆解f:

>>> dis.dis(f)
  2           0 LOAD_CONST               1 (<code object <listcomp> at 0x0000000003CCA1E0, file "<pyshell#374>", line 2>) 
              3 LOAD_CONST               2 ('f.<locals>.<listcomp>') 
              6 MAKE_FUNCTION            0 
              9 LOAD_FAST                0 (lst) 
             12 GET_ITER             
             13 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             16 RETURN_VALUE       

前三行显示f加载预编译的代码块并从中创建一个函数(将其命名为f.<locals>.<listcomp>)。这是用于创建列表的函数。

接下来的两行显示lst正在加载变量并从中创建迭代器。这发生在f的范围,而不是内部函数的范围。然后<listcomp>使用该迭代器作为其参数来调用函数。

这相当于类A。它从类变量中获取迭代器integers,就像您可以在新成员的定义中使用对先前类成员的其他类型的引用一样。

现在,比较一下拆解g,它通过迭代同一个列表两次来配对:

>>> dis.dis(g)
  2           0 LOAD_CLOSURE             0 (lst) 
              3 BUILD_TUPLE              1 
              6 LOAD_CONST               1 (<code object <listcomp> at 0x0000000003CCA810, file "<pyshell#377>", line 2>) 
              9 LOAD_CONST               2 ('g.<locals>.<listcomp>') 
             12 MAKE_CLOSURE             0 
             15 LOAD_DEREF               0 (lst) 
             18 GET_ITER             
             19 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             22 RETURN_VALUE         

这次,它使用代码对象构建一个闭包,而不是一个基本函数。闭包是一个带有一些“自由”变量的函数,这些变量引用封闭范围内的事物。为了<listcomp>函数于g,这工作得很好,因为它的范围是正常的。但是,当您尝试在类 B 中使用相同类型的理解时,闭包会失败,因为类不允许它们包含的函数以这种方式查看其作用域(如Foo上面的类)。

值得注意的是,不仅内部序列值会导致此问题。正如在上一个问题BrenBarn 在评论中链接到,如果在列表理解的其他地方引用类变量,您将遇到相同的问题:

class C:
    num = 5
    products = [i * num for i in range(10)] # raises a NameError about num

但是,您不会从多级列表推导中得到错误,其中内部for (or if) 子句仅引用前面循环的结果。这是因为这些值不是闭包的一部分,只是闭包内的局部变量<listcomp>函数的范围。

class D:
    nested = [[1, 2, 3], [4, 5, 6]]
    flattened = [item for inner in nested for item in inner] # works!

就像我说的,类作用域有点奇怪。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌套列表理解范围 的相关文章

随机推荐

  • 本地存储库需要 Git LFS 吗?

    我创建了一个专门存储在本地的 Git 存储库 我问自己 我是否真的需要 Git LFS 来存储二进制文件 据我所知 gitattributes已正确配置 如下所示 psd binary 是的 文件落在 git objects 但它们被压缩并
  • 创建CSS全局变量:样式表主题管理[重复]

    这个问题在这里已经有答案了 有没有办法在 css 中设置全局变量 例如 Color1 fff Color2 b00 h1 color Color1 background Color2 最新更新 16 01 2020 CSS 自定义属性 变量
  • CSV 到关联数组

    我见过很多关于如何获取 CSV 文件 然后创建一个以标题为键的关联数组的示例 例如 Brand Model Part Test Honda Civic 123 244 Honda Civic 135 434 Toyota Supra 511
  • 将范围扩展为:“1-3,6,8-10”到 [1,2,3, 6, 8,9,10]

    我试图在我的程序中添加一个选项 允许用户选择他想要执行的程序步骤 我希望能够解析像这样的字符串 1 3 6 8 10 并得到 1 2 3 6 8 9 10 你知道 Python 中是否已经存在正在执行此操作的东西吗 该函数执行您所要求的操作
  • Solr 可以加载原始 Lucene 索引吗?

    我的一些同事有一个大型 Java Web 应用程序 该应用程序使用使用 Lucene Java 构建的搜索系统 我想做的是拥有一个基于 HTTP 的 API 来访问那些现有的搜索索引 我以前使用过 Nutch 并且非常喜欢 OpenSear
  • WordPress 自定义注册表

    我有一位客户需要定制注册表 我需要在此页面上进行自定义设计 我需要添加自定义字段 例如名字 公司 电话等 有人可以帮我解决这个问题吗 询问 WordPress 问题的更好地方可能是WordPress 答案 无论如何 如果你想在没有插件的情况
  • 在角度引导程序中设置初始静态选项卡

    我似乎无法在角度引导选项卡集中设置初始选项卡 它始终将最左侧的选项卡设置为活动状态 给定 html
  • 忽略不允许的属性 IISMAJORVERSION 和“EnableUserControl”?

    我的安装程序包在我的计算机上运行 但在我同事的计算机上失败 查看日志 我可以看到一些属性值在 ExecuteAction 短语期间没有保留 有几个Ignoring disallowed property安装程序日志文件中的行以及这些属性在
  • Django 模板中的 IsInstance 吗?

    有没有办法在 Django 模板中执行 isinstance issubclass 操作 我意识到我可以编写自己的模板标签 但令我惊讶的是这不可能 这让我觉得我要么做错了什么 要么遗漏了一些明显的东西 我希望显示两个不同的标记部分 具体取决
  • 带窥视功能的 UIPageViewController

    我正在尝试使用创建页面浏览器UIPageViewController在 Interface Builder 中 允许显示部分相邻页面 也称为查看 我一直在关注教程http www appcoda com uipageviewcontroll
  • 从不同的类访问 HashMap

    我的班级中有一个名为 DataStorage 的哈希图 HashMap
  • Tensorflow 2.0 自定义训练循环的学习率

    当我使用tensorflow 2 0自定义训练循环时 是否有任何函数或方法可以显示学习率 这是张量流指南的示例 def train step images labels with tf GradientTape as tape predic
  • 在 py2exe 构建中包含 PYD/DLL

    我的应用程序的模块之一使用 pyd 文件中的函数 有一个选项可以排除 dll exclude dlls 但是有一个选项可以包含它们吗 尽管复制了其余文件 py 但构建过程似乎并未复制我的模块中的 pyd 我还需要包含一个 dll 如何让 p
  • Solr 使用太多内存

    我们有一个在带有 Oracle Java 6 Hotspot JDK 的 Windows 2008 R2 上运行的 Solr 3 4 实例 该实例变得无响应 当我们查看机器时 我们注意到可用物理内存变为零 Tomcat7 exe 进程使用了
  • php paypal 快速结帐问题

    我正在尝试在我的网站上集成贝宝快速结帐 我试图使用沙箱进行检查 当我从我的网站提交数据时 生成的令牌没有错误 但当重定向到 PayPal 时 它不显示付款金额 顺便说一句 我正在使用贝宝快速结帐向导中的代码 如果有人指出我正确的方向 那将会
  • 选择日期后添加天数(周末和节假日除外)

    我有两个文本字段 在第一个文本字段中 我使用 jQueryUI Datepicker 添加了一个日历 当用户从日期选择器中选择日期时 它应该自动向该日期添加 30 天 并在第二个文本字段中设置该值 我已经完成了将日期添加 30 天的工作 但
  • JPA EntityManager:为什么使用 persist() 而不是 merge()?

    EntityManager merge 可以插入新对象并更新现有对象 为什么要使用persist 只能创建新对象 无论哪种方式都会将实体添加到 PersistenceContext 中 不同之处在于您随后对该实体执行的操作 Persist
  • Spring中如何获取Session对象?

    我相对较新Spring和春季安全 我试图编写一个程序 需要使用 Spring security 在服务器端对用户进行身份验证 我想出了以下几点 public class CustomAuthenticationProvider extend
  • 从另一个模块访问对象

    我是一个非常缺乏经验的程序员 正在创建一个游戏 使用 Python 3 3 作为学习练习 我目前有一个主模块和一个战斗模块 游戏中的人物由 Person 类的实例表示 并在主模块中创建 然而 战斗模块显然需要访问这些对象 此外 我可能稍后会
  • 嵌套列表理解范围

    解释我的问题的最好方法是举一个例子 示例 py class A object integers 1 2 3 singles i for i in integers class B object integers 1 2 3 pairs i