Python:在重新分配外部函数后,闭包如何继续存在?

2024-04-06

我学习了 Python 中的闭包,并且对这个概念有了足够的了解。在 IDLE 中闲逛时,我想到了如果我重新分配封闭函数然后尝试调用封闭函数会发生什么:

>>> def outer_function(hello):
        message = hello
        def inner_function():
            print(message)
        return inner_function

>>> function = outer_function("hello")

>>> function()
hello

>>> def outer_function():
    print("hi")

>>> function()
hello

我认为这非常有趣,但我意识到我对内存中的闭包发生的情况没有足够的理解等。有人可以解释我如何调用inner_function重新分配后outer_function?


在 CPython(即用 C 编写的参考实现,大多数人认为只是“Python”)中,词法闭包被实现为“平面闭包”(请参阅PEP 227 https://www.python.org/dev/peps/pep-0227/)使用单元对象引用,而不是在运行时搜索框架对象(嵌套范围)的链接列表。这允许在返回闭包函数时快速查找并改进垃圾收集。

字节码在outer_function专门用于访问堆栈帧中的单元对象,而不是直接引用message目的。解释器在设置调用的堆栈帧时知道这一点,因为代码对象将此变量定义为单元变量:

>>> outer_function.__code__.co_cellvars
('message',)

字节码在inner_function还取消引用单元格对象的值message,但由于它不是对象的源,因此它被分类为自由变量:

>>> type(outer_function.__code__.co_consts[1])
<class 'code'>
>>> outer_function.__code__.co_consts[1].co_name
'inner_function'
>>> outer_function.__code__.co_consts[1].co_freevars
('message',)

Each inner_function实例化的函数对象有一个__closure__引用包含的自由变量的单元格的元组。例如:

>>> function = outer_function('hello')
>>> type(function.__closure__[0])
<class 'cell'>
>>> function.__closure__[0].cell_contents
'hello'

这里面的细胞__closure__元组被加载到堆栈帧中时function叫做。

这个单元格元组使它变得扁平化。无论您将作用域嵌套多深,__closure__将始终繁殖所有所需的细胞。例如:

def a():
    x = 1
    def b():
        def c():
            def d():
                x
            print('d.__closure__[0].cell_contents:',
                  d.__closure__[0].cell_contents)
        print('c.__closure__[0].cell_contents:',
              c.__closure__[0].cell_contents)
        c()
    print('b.__closure__[0].cell_contents:',
          b.__closure__[0].cell_contents)
    b()

>>> a()
b.__closure__[0].cell_contents: 1
c.__closure__[0].cell_contents: 1
d.__closure__[0].cell_contents: 1

功能b and c不要直接引用x,但他们必须为内部功能传播细胞d来参考它。


上述检查依赖于 CPython 实现细节。在 Python 3.3+ 中你可以调用inspect.getclosurevars https://docs.python.org/3/library/inspect.html#inspect.getclosurevars检查闭包变量。例如:

import inspect

def outer_function(hello):
    message = hello
    def inner_function():
        print(message)
    return inner_function

>>> function = outer_function('hello')
>>> inspect.getclosurevars(function)
ClosureVars(nonlocals={'message': 'hello'},
            globals={},
            builtins={'print': <built-in function print>},
            unbound=set())
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python:在重新分配外部函数后,闭包如何继续存在? 的相关文章

  • 将 yerr/xerr 绘制为阴影区域而不是误差线

    在 matplotlib 中 如何将误差绘制为阴影区域而不是误差条 例如 而不是 忽略示例图中各点之间的平滑插值 这需要进行一些手动插值 或者只是获得更高分辨率的数据 您可以使用pyplot fill between https matpl
  • 如何删除 PyCharm 中的项目?

    如果我关闭一个项目 然后删除该项目文件夹 则在 PyCharm 重新启动后 会再次创建一个空的项目文件夹 只需按顺序执行以下步骤即可 他们假设您当前在 PyCharm 窗口中打开了该项目 单击 文件 gt 关闭项目 关闭项目 在 PyCha
  • 定义Python源代码编码的正确方法

    PEP 263 http www python org dev peps pep 0263 定义如何声明Python源代码编码 通常 Python 文件的前两行应以以下内容开头 usr bin python coding
  • 将 C++ 指针作为参数传递给 Cython 函数

    cdef extern from Foo h cdef cppclass Bar pass cdef class PyClass cdef Bar bar def cinit self Bar b bar b 这总是会给我类似的东西 Can
  • 使用 Python 3 动态插入到 sqlite

    我想使用 sqlite 写入多个表 但我不想提前手动指定查询 有数十种可能的排列 例如 def insert sqlite tablename data list global dbc dbc execute insert into tab
  • 检查 python 中命令行参数的数量

    我是蟒蛇新手 还是把脚弄湿了 我正在尝试做这样的事情 import sys if len sys argv lt 3 or lt len sys argv gt 3 print This script will compare two fi
  • 从 pyspark.sql 中的列表创建数据框

    我完全陷入了有线的境地 现在我有一个清单li li example data map lambda x get labeled prediction w x collect print li type li 输出就像 0 0 59 0 0
  • 使用 Pytest 的参数化添加测试功能的描述

    当其中一个测试失败时 可以在测试正在测试的内容的参数化中添加描述 快速了解测试失败的原因 有时您不知道测试失败的原因 您必须查看代码 通过每个测试的描述 您就可以知道 例如 pytest mark parametrize num1 num2
  • 以类型化内存视图作为成员的结构定义

    目前我正在尝试让一个具有类型化内存视图的结构能够工作 例如 ctypedef struct node unsigned int inds 如果 inds 不是内存视图 据我所知 它可以完美地工作 然而 通过内存视图并使用类似的东西 def
  • python 中的 h2o 框架子集

    如何在 python 中对 h2o 框架进行子集化 如果 x 是一个 df 并且 Origin 是一个变量 那么在 pandas 中我们通常可以通过以下方式进行子集化 x x Origin AAF 但使用 h2o 框架会出现以下错误 H2O
  • 自调用函数未定义

    如果我声明一个函数文字 var x function alert hi console log x returns the function code However var x function alert hi console log
  • 检索 geodjango 多边形对象的边界框

    如何在 geodjango 中获取 MultiPolygon 对象的边界框 在 API 中找不到任何内容http geodjango org docs geos html http geodjango org docs geos html
  • 将字符串中的随机字符转换为大写

    我尝试随机附加文本字符串 这样就不只是有像这样的输出 gt gt gt david 我最终会得到类似的东西 gt gt gt DaViD gt gt gt dAviD 我现在的代码是这样的 import random import stri
  • 如何从列表类别中对 pandas 数据框进行排序?

    所以我在下面有这个数据集 我想根据我的列表从 名称 列进行排序 以及按 A 升序和按 B 降序排序 import pandas as pd import numpy as np df1 pd DataFrame from items A 1
  • 使用 selenium 和 python 来提取 javascript 生成的 HTML?萤火虫?

    这里是Python新手 我遇到的是数据收集问题 我在这个网站上 当我用 Firebug 检查我想要的元素时 它显示了包含我需要的信息的源 然而常规源代码 没有 Firebug 不会给我这个信息 这意味着我也无法通过正常的 selenium
  • numpy polyfit 中使用的权重值是多少以及拟合误差是多少

    我正在尝试对 numpy 中的某些数据进行线性拟合 Ex 其中 w 是该值的样本数 即对于点 x 0 y 0 我只有 1 个测量值 该测量值是2 2 但对于这一点 1 1 我有 2 个测量值 值为3 5 x np array 0 1 2 3
  • 非法指令:MacOS High Sierra 上有 4 条指令

    我正在尝试在 pygame 3 6 中制作一个看起来像聊天的窗口 我刚刚将我的 MacBook 更新到版本 10 13 6 在我这样做之前它工作得很好 但在我收到消息之后 非法指令 4 Code import pygame from pyg
  • 如何在 scikit 中加载 CSV 数据并将其用于朴素贝叶斯分类

    尝试加载自定义数据以在 Scikit 中执行 NB 分类 需要帮助将示例数据加载到 Scikit 中 然后执行 NB 如何加载目标的分类值 使用相同的数据进行训练和测试 或使用完整的数据集进行测试 Sl No Member ID Membe
  • 描述符“join”需要“unicode”对象,但收到“str”

    代码改编自here http wiki geany org howtos convert camelcase from foo bar to Foo Bar def lower case underscore to camel case s
  • 使用 paramiko 运行 Sudo 命令

    我正在尝试执行sudo使用 python paramiko 在远程计算机上运行命令 我尝试了这段代码 import paramiko ssh paramiko SSHClient ssh set missing host key polic

随机推荐

  • PHP/Symfony2 表单复选框字段

    Orm My SampleBundle Entity Subject type entity id id type integer generator strategy AUTO fields motion type smallint un
  • 理解含义的算法[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想知道是否有任何特定的算法可以遵循
  • Vue:选择下拉菜单在更改值时清除其他输入

    我有一个带有输入值的表单 当我选择带有 v model 的选项并更改下拉值时 之前字段的输入将被清除 我制作了一个简单的代码笔来演示这一点 一段时间以来 这一直是我的痛点 但现在它开始干扰客户体验 所以我想看看为什么会发生这种情况 http
  • 带通配符的 FTP 目录部分列表

    首先我问 ftp 目录列表超时 大量子目录 https stackoverflow com questions 9230485 ftp directory listing timeout huge number of subdirs 我得到
  • 在 JFrame 中组织多个 JPanel 的好方法是什么?

    我想做的是在框架内组织五个独立的 JPanel 输出应如下所示 顶部将有一个面板 顶部面板正下方的两个面板垂直分割空间 然后另外两个面板水平分割剩余空间 我无法弄清楚如何组织如上所述的面板 我认为这是因为我不知道正确的语法 因此 非常感谢任
  • 引用在嵌套结构中的生存时间不够长

    我正在创建一系列数据结构 其中包含对较低级别结构的可变引用 我一直很愉快地与A B and C下面但我尝试添加一个新层D A B C D实际上是用于协议解码的状态机的状态 但我在这里删除了所有这些 struct A fn init A gt
  • Go 模块在 VSCode 中导入问题(“无法在任何 [...] 中找到包 [...]”)

    我遇到了可能是 Gopls 语言服务器问题 在 VSCode 中使用带有 Go 扩展的 Go 模块时 我的所有外部包导入语句都被标记为不正确 这正是我到目前为止所做的 在我的 GOPATH src github com Kozie1337
  • sbt:选择运行的主类

    我的应用程序中有大约 6 个主要类 但我通常只使用其中一个 所以我想通过 sbt 自动运行它 sbt 使得可以在 build sbt 中定义两个键 Run Key val selectMainClass TaskKey Option Str
  • 无法检索访问令牌 linkedin api

    我正在申请connect with linkedin 我正在关注分步指南 https code google com p simple linkedinphp wiki QuickStart 为了验证用户身份 我寻求了帮助this http
  • 如何绘制具有不同 colspan 的四个子图?

    我尝试使用四张图像来拟合matplotlib pyplot像下面这样 plot1 plot2 plot3 plot4 我发现的大多数例子都涵盖了如下三个图 ax1 plt subplot 221 ax2 plt subplot 222 ax
  • 当我将 targetSDK 设置为 API 30 后,我的 Android 应用程序无法正常工作;我如何找出原因?

    根据Google https developer android com distribute best practices develop target sdk 从 2021 年 8 月开始 所有新的 Google Play 应用程序除了
  • Gatsby 未生成正确的静态 HTML 文件

    我正在开发一个基于盖茨比的网站 到目前为止该网站的开发进展顺利 但在构建生产时遇到了一个问题 即我们在各个页面索引文件中没有获得任何静态 html 相反 Gatsby 似乎将尝试从 javascript 注入页面 这与我们的预期相反 我看到
  • Pandas.read_excel 读取 xlsx 文件集时出现 KeyError

    我使用 Anaconda shell 进行数据分析 上传到pandas一堆excel文件 25个文件 在此文件上https www dropbox com s 16ea1cw6k63i16p Newdata zip dl 0 https w
  • 添加两个具有不同回调的谷歌地图[重复]

    这个问题在这里已经有答案了 我的页面上有两个谷歌地图容器 第一个 id map 只是一个普通的 显示地图 第二个 id map2 是一个搜索地图 用户在其中键入输入 地图将刷新到用户键入的位置 这些地图使用相同的 api 密钥 但它们的回调
  • Request.pipe() JPEG 流

    我正在开发一个作为 ZoneMinder 中间件的 Nodejs 应用程序 简而言之 我的目标是屏蔽所有 ZoneMinder api 以便客户端不知道我是否使用 ZM 一切都很好 但有一件事让我烦恼 ZM 中有一个流 api 它提供流 J
  • PyGame:文本未出现

    我正在遵循教程 我试图让我的文本出现在屏幕上 这是我的代码 但文本不会出现 from future import division import math import sys import pygame class MyGame obje
  • 如何使用 PHP 安全地将 JSON 数据写入文件

    我有用于编辑图像的 HTML 表单 所有数据都存储在 JSON 中 当我更改当前图像时 我想通过 PHP 脚本将更改保存到文本文件中 如果我返回到上一个图像 该配置将再次从该文件发送到表单 我的问题是 如何安全地写入 读取此类数据 在哪里以
  • 在 WooCommerce 主页上隐藏“缺货”产品

    我不想在主页上显示 缺货 产品 我尝试了一些 WooCommerce 挂钩和过滤器来更改产品查询 但它不起作用 我还在 woocommerce 设置区域中检查了 隐藏缺货 但产品仍然出现 我能得到线索吗 发生了什么 我尝试使用此过滤器挂钩来
  • C#:正确使用 Wea​​kReference IsAlive 属性

    正如所解释的here https msdn microsoft com en us library system weakreference isalive v vs 110 aspx if WeakReference s IsAlive返
  • Python:在重新分配外部函数后,闭包如何继续存在?

    我学习了 Python 中的闭包 并且对这个概念有了足够的了解 在 IDLE 中闲逛时 我想到了如果我重新分配封闭函数然后尝试调用封闭函数会发生什么 gt gt gt def outer function hello message hel