Python中什么情况下函数的__code__.co_freevars属性值非空?
Python中
co_freevars的触发场景说明 你举的示例里y没有被计入co_freevars的原因很简单:y不属于自由变量的范畴,Python会将其识别为需要从全局作用域查找的变量,因此被放入了co_names中。
三个代码对象属性的核心区别
co_varnames:存储函数自身的局部变量,包括所有入参,你示例中的x是函数入参,自然出现在该属性中co_names:存储函数需要从全局/模块作用域查找的变量名、属性名,你示例中f定义在全局作用域,没有嵌套的外层函数提供y,Python默认会去全局作用域查找y,因此y被放入该属性co_freevars:仅存储闭包场景下的变量名,也就是内层函数引用的、来自外层嵌套函数作用域的非全局变量
变量被计入co_freevars的必要条件
只有同时满足以下条件时,变量才会被记录到co_freevars中:
- 存在至少两层嵌套的函数结构:即有外层函数,且内层函数定义在外层函数的内部
- 内层函数显式引用了外层函数作用域内的变量(包括外层函数的入参、外层函数内定义的局部变量,且该变量不是全局变量)
- 内层函数的生命周期长于外层函数的执行周期(最常见的场景是外层函数将内层函数作为返回值返回,形成闭包捕获外层变量)
反例说明
如果内层函数中对同名变量进行了赋值操作且没有加nonlocal声明,该变量会被识别为内层函数的局部变量,不会计入co_freevars:
def outer(): y = 10 def inner(x): y = 20 # 此处为内层的局部变量,未引用外层的y return x + y return inner f = outer() print(f.__code__.co_freevars) # 输出为()
正例说明
符合闭包规则的场景下,变量会被计入co_freevars:
def outer(): y = 10 def inner(x): return x + y # 引用外层函数的y return inner f = outer() print(f.__code__.co_freevars) # 输出为('y',)
内容的提问来源于stack exchange,提问作者Davis Yoshida
相关产品推荐
相关产品推荐

