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

为何fun.__code__.co_names未包含全部全局变量?fun1案例分析

为什么fun1的__code__.co_names不包含dict_de_en?

先看第一段测试代码:

dict_de_en = {'we':'wir', 'love':'lieben', 'cake':'kuchen'}
def fun1(sentence): 
    return " ".join([dict_de_en[w] for w in sentence.split()])
def fun2(sentence): 
    dd = dict_de_en
    return " ".join([dd[w] for w in sentence.split()])
print("f1:", fun1("we love cake")) # "wir lieben kuchen"
print("f2:", fun2("we love cake")) # ditto
print("n1", fun1.__code__.co_names) # ('join', 'split')
print("n2", fun2.__code__.co_names) # ('dict_de_en', 'join', 'split')

运行后发现fun1.__code__.co_names里没有dict_de_en,但下面这段代码的结果却符合预期:

dict_de_en = {'we':'wir', 'love':'lieben', 'cake':'kuchen'}
def fun3(word): 
    return dict_de_en[word]
def fun4(word): 
    dd = dict_de_en
    return dd[word]
print("f3:", fun3("we")) # "wir"
print("f4:", fun4("we")) # ditto
print("n3", fun3.__code__.co_names) # ('dict_de_en',)
print("n4", fun4.__code__.co_names) # ('dict_de_en',)

背景:运营Python MOOC时,自动评分系统需要检测函数中全局变量的使用,其他情况正常,但fun1的情况出现异常。


核心原因:列表推导式是独立的嵌套代码对象

Python中,列表推导式会被编译成一个独立的嵌套代码对象,不属于函数主代码的一部分:

  • fun1里的dict_de_en是在列表推导式内部被引用的,这个推导式有自己的__code__对象,dict_de_en会被记录在这个嵌套对象的co_names中,而非fun1自身的co_names。
  • 你可以通过以下代码验证这一点:
# 遍历fun1的常量,找到嵌套的列表推导式代码对象
for const in fun1.__code__.co_consts:
    if isinstance(const, type(fun1.__code__)):
        print(const.co_names)  # 输出 ('dict_de_en',)
  • fun2里的dict_de_en是在函数主代码中被引用(赋值给dd),所以会被记录在fun2自身的co_names里。
  • fun3直接在函数主代码中引用dict_de_en,自然出现在它的co_names中;fun4同样是在主代码里引用全局变量赋值,因此也会被记录。

对自动评分系统的改进建议

要准确检测全局变量的使用,不能只检查函数自身的__code__.co_names,还需要遍历函数__code__.co_consts中的所有嵌套代码对象(包括列表推导式、生成器表达式、嵌套函数等),检查这些子代码对象的co_names,这样才能覆盖所有全局变量引用的场景。


内容的提问来源于stack exchange,提问作者Berry Boessenkool

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 01:52:37