You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何内部函数引用局部变量会改变Python locals()的返回顺序?

为什么Python 3.10及更早版本中,局部变量顺序会因内部引用改变?

先看正常场景的代码,执行后会按参数定义顺序输出局部变量:

def foo(a: str = "a", b: str = "b") -> None:
    print(locals())
foo()  # 输出 {'a': 'a', 'b': 'b'}

这符合Python 3.7+的预期——locals()会按变量创建的顺序返回结果。

但如果在函数内部添加对某个参数的闭包引用(比如lambda或内部函数引用参数a),输出顺序就会反转:

def foo(a: str = "a", b: str = "b") -> None:
    print(locals())
    lambda: a
    # 或者替换为内部函数:
    # def inner() -> None:
    #     a

foo()  # 输出 {'b': 'b', 'a': 'a'}

这个现象仅出现在Python 3.10及更低版本,3.11及以上版本已修复。

原因分析

这是Python解释器处理闭包时的一个实现细节问题:
当函数内部出现对局部变量的闭包引用时,解释器会为被引用的变量创建cell对象(用于在闭包间共享变量)。在这个过程中,解释器会调整局部变量的内部存储顺序:被闭包引用的变量会被移到局部变量列表的末尾,未被引用的变量则保留在原有位置。

在示例中,参数a被lambda/内部函数引用,因此被移到了局部变量列表的最后;b没有被引用,排在前面。而locals()返回的字典顺序会跟随这个内部存储顺序,最终就出现了b在前、a在后的输出结果。

Python 3.11对局部变量的存储逻辑和闭包处理机制做了优化,修复了这个顺序异常的问题,所以在新版本中无论是否存在闭包引用,locals()都会保持参数定义的原始顺序。

内容的提问来源于stack exchange,提问作者Nelson Yeung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:49:59