为什么函数(Python)的 __code__ 是可变的

2024-04-24

在昨天的上一个问题中,在评论中,我开始知道在 python 中__code__函数的属性是可变的。因此我可以编写如下代码

def foo():
    print "Hello"

def foo2():
    print "Hello 2"

foo()
foo.__code__ = foo2.__code__
foo()

Output

Hello
Hello 2

我尝试谷歌搜索,但要么是因为没有信息(我非常怀疑这一点),要么是关键字(__code__)不容易搜索,我找不到这方面的用例。

“因为 Python 中的大多数东西都是可变的”似乎也不是一个合理的答案,因为函数的其他属性 -__closure__ and __globals__- 明确只读(来自对象/funcobject.c https://github.com/python/cpython/blob/master/Objects/funcobject.c#L236):

static PyMemberDef func_memberlist[] = {
    {"__closure__",   T_OBJECT,     OFF(func_closure),
     RESTRICTED|READONLY},
    {"__doc__",       T_OBJECT,     OFF(func_doc), PY_WRITE_RESTRICTED},
    {"__globals__",   T_OBJECT,     OFF(func_globals),
     RESTRICTED|READONLY},
    {"__module__",    T_OBJECT,     OFF(func_module), PY_WRITE_RESTRICTED},
    {NULL}  /* Sentinel */
};

为什么会__code__是可写的,而其他属性是只读的?


事实是,Python 中的大多数东西are可变的。所以真正的问题是,为什么__closure__ and __globals__ not?

答案乍一看似乎很简单。这两件事都是函数可能需要的变量的容器。代码对象本身并不携带其封闭变量和全局变量;它只知道如何从函数中获取它们。当函数被调用时,它从这两个属性中获取实际值。

但范围本身是可变的,所以这个答案并不令人满意。我们需要解释为什么修改这些东西特别会破坏东西。

For __closure__,我们可以看看它的结构。它不是映射,而是单元元组。它不知道封闭变量的名称。当代码对象查找封闭变量时,它需要知道它在元组中的位置;他们一对一地匹配co_freevars这也是只读的。如果元组的大小错误或根本不是元组,则如果底层 C 代码没有预料到这种情况,则该机制可能会严重崩溃(读取:段错误)。强制 C 代码检查元组的类型和大小是不必要的繁琐工作,可以通过将属性设置为只读来消除。如果您尝试更换__code__具有不同数量的自由变量的东西,你得到一个错误 https://github.com/python/cpython/blob/master/Objects/funcobject.c#L269,所以尺寸总是正确的。

For __globals__,解释不太明显,但我会推测。作用域查找机制期望始终能够访问全局命名空间。事实上,字节码可能是硬编码的 https://docs.python.org/2/library/dis.html#opcode-LOAD_GLOBAL直接进入全局命名空间,如果编译器可以证明没有其他命名空间会有具有特定名称的变量。如果全局命名空间突然None或者其他一些非映射对象,C 代码可能会再次出现严重的错误行为。同样,让代码执行不必要的类型检查会浪费 CPU 周期。

另一种可能性是(通常声明的)函数借个参考 https://docs.python.org/3/c-api/intro.html#reference-count-details到模块的全局命名空间,并使属性可写会导致引用计数混乱。我可以想象这种设计,但我不太确定这是一个好主意,因为可以使用生命周期可能比所属模块短的对象显式构造函数,并且这些对象需要特殊处理。

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

为什么函数(Python)的 __code__ 是可变的 的相关文章

随机推荐

  • 我可以在 reStructuredText 中使用内联原始 LaTeX

    我正在尝试将 LaTeX 变量嵌入到一些 reStructuredText 中 我知道 raw 指令 但我希望将其嵌入到文本段落中 具体来说 我希望从模板考试文档中复制 numquestions 和 numpoints 变量 我尝试过使用
  • yaml.parser.ParserError:解析块映射时

    ERROR yaml parser ParserError while parsing a block mapping in tmp statelesscs compose yml line 1 column 1 expected
  • github 存储库的本地缓存?

    我们使用 github 来管理我们的大量软件环境 我敢打赌 像许多其他组织一样 该存储库的绝大多数流量来自我们的办公室 考虑到这一点 有没有一种方法可以构建给定 github 存储库的本地缓存 但仍然具有云版本的保护 我在缓存代理服务器的模
  • 设置 stats_flutter 时间序列图表中时间标签的格式以包含 hh:mm:ss

    是否可以格式化charts flutter时间序列图表的x轴上的标签以进行显示hh mm ss 这个答案 https stackoverflow com a 51138909 1954993解释了如何格式化代码以显示月份和日期 但我需要显示
  • 快速加速平均值和标准差

    我正在研究 Accelerate 以计算 Swift 中数组的平均值和标准差 我可以做到这一点 如何计算标准差 let rr Double 18 0 21 0 41 0 42 0 48 0 50 0 55 0 90 0 var mn Dou
  • 除了不可变值对象之外,什么时候应该重写 equals() ?

    很明显equals 而且当然hashCode 在处理不可变值对象时很有价值 映射键 需要在包含它们的对象之间进行比较的强类型字段值等 但除了值对象之外 您有多少可能真正拥有两个独立构造的实例并希望它们成为equal 我很难想象一个现实的场景
  • 我可以使用在 DispatcherServlet Context 中声明的 Hibernate Session Factory 而不是 hibernate.cfg.xml 吗?

    在我之前的 Spring MVC 项目中 我使用 Hibernate 作为 JPA 的提供者 我不必创建hibernate cfg xml文件 因为我已经在 Spring DispatcherServlet 上下文文件中声明了 Hibern
  • 为什么 JSON 应该有一个 status 属性

    我偶然发现了一种相当普遍的做法 我什至找到了一个为其命名的网页 但我忘记了名称 并且无法再在谷歌上找到该页面 实践中 来自 REST 服务的每个 JSON 响应都应具有以下结构 status ok data 或者在错误情况下 status
  • DirectX 11 ClearRenderTargetView 恢复透明缓冲区?

    我正在尝试创建一个使用 directx 进行绘制的窗口opaque上面的内容透明的视图 即桌面显示出来 使用 DirectX11 我尝试执行以下操作 但它并没有使背景透明 事实上 我输入的任何不透明度值都会给出完全相同的结果 我在做什么 f
  • Java ConcurrentHashMap 集合的模式

    我在多线程应用程序中常用的数据结构是 ConcurrentHashMap 我想在其中保存一组共享相同键的项目 安装特定键值的第一个项目时会出现此问题 我一直使用的模式是 final ConcurrentMap
  • Flowtype - 字符串与字符串枚举不兼容

    我有一个来自选择输入且类型为字符串的值 但是我想将其传递到函数中 更新语言 接收带有类型别名 Language 我面临的问题是 Flow 只允许我打电话更新语言如果我明确地将我的字符串值与枚举字符串进行比较 并且我想使用像 array in
  • C#:使用指针类型作为字段?

    在 C 中 可以声明具有指针类型成员的结构 或类 如下所示 unsafe struct Node public Node NextNode 它是否安全 呃 暂时忽略那个具有讽刺意味的小unsafe标志 使用这个结构 我的意思是在堆上长期存储
  • 使用 VSCode 在 Python 中调试期间读取输入

    这是我在 vs code 中使用的 python 扩展 python 扩展 https marketplace visualstudio com items itemName donjayamanne python 当我使用扩展提供的调试功
  • python 中数据库连接池的最佳解决方案是什么?

    我开发了一些类似于 DAO 的自定义类来满足我的项目的一些非常特殊的要求 该项目是一个不在任何类型的框架内运行的服务器端进程 该解决方案效果很好 只是每次发出新请求时 我都会通过 MySQLdb connect 打开一个新连接 将其切换为使
  • 当我提出自己的异常作为响应时,如何更轻松地抑制以前的异常?

    Consider try import someProprietaryModule except ImportError raise ImportError It appears that
  • 西格网络速度

    这个库对于获取 cpu ram 和其他人员来说非常棒 但是 我不知道如何获得网络速度 这意味着 在一段时间内发送和接收了多少数据 有办法给我这些数据吗 这可能是我正在寻找的东西吗 Tcp stat sigar getTcp stat get
  • Windows 和 OS X 之间 build.gradle 中的相对路径不同

    我的项目有一个包含密钥库文件 file keystore 的文件夹 这是结构 gradle 2 2 taskArtifacts idea copyright libraries app build generated libs src an
  • 如何使视频资源兼容视网膜显示?

    我有一个应用程序 可以在播放 2 秒的电影时加载 目前 该应用程序已在商店上架 并且除此视频外 所有静态内容均符合视网膜显示标准 我有一个用于视网膜显示屏的 960x640 mp4 h 264 编码视频 它在 iPhone 是的 高分辨率
  • 深层链接不起作用 - 离子

    我正在使用 Deeplinks 和 ionic 3 但我创建的 url 不起作用 这是网址 https lucky com prd rm74fEgBB2frzhagYcov https lucky com prd rm74fEgBB2frz
  • 为什么函数(Python)的 __code__ 是可变的

    在昨天的上一个问题中 在评论中 我开始知道在 python 中 code 函数的属性是可变的 因此我可以编写如下代码 def foo print Hello def foo2 print Hello 2 foo foo code foo2