Skip to main content
 首页 » 编程设计

python之为什么必须创建一个新的全局变量来引用 "exec"中的当前类实例

2025年05月04日8pengyingh

我有一个包含 ~20 个方法的类,在 def __init__(self, ...): 中,我必须调用其中的许多方法 (~9) 但我不想必须一个接一个地调用每个单独的方法。

所以我采取了简单的方法并创建了两个列表推导式,它们使用 exec 来调用每个方法:

[exec("self.create%s()" % x) for x in "ArticleObjects SeriesObjects ArticleList SearchList".split(" ")] 
[exec("self.compile%sPage(self)" % x) for x in "About Screenshots Search Contact Articles".split(" ")] 

当我使用 python3 filename.py 运行此代码时,出现错误,内容为:

NameError: name 'self' is not defined 

通过反复试验,我发现;为了让这段代码工作,我必须创建一个名为 instance 的 self 副本,并将新的 instance 变量设为全局变量,然后使用 ClassName.methodName(instance) 而不是 self.methodName() 调用方法:

工作代码为:

global instance; instance = self 
[exec("ClassNamecreate%s(instance)" % x) for x in "ArticleObjects SeriesObjects ArticleList SearchList".split(" ")] 
[exec("ClassName.compile%sPage(instance)" % x) for x in "About Screenshots Search Contact Articles".split(" ")] 

这是为什么?为什么 self 变量在 exec 中未定义,尽管它可用于调用 exec 的范围?

更新:我使用的是 Python 3.6.7

请您参考如下方法:

这里有很多关于如何避免 exec 语句(这通常是不好的)的好建议,但是要回答您关于为什么会发生这种情况的问题,它更多地与列表理解有关。列表理解创建一个新的范围,当你调用 exec 时没有全局或本地参数,它使用 locals() 函数:

Note: The default locals act as described for function locals() below

Source

在这里,您可以从列表理解中看到 locals() 函数的结果:

class Sample: 
    def __init__(self): 
        k = 4 
        print(locals()) 
        exec("print(locals())") 
        [print(locals()) for x in range(1)] 
        [exec("print(locals())") for x in range(1)] 
Sample() 

输出:

{'k': 4, 'self': <__main__.Sample object at 0x00000000030295C0>} 
{'k': 4, 'self': <__main__.Sample object at 0x00000000030295C0>} 
{'x': 0, '.0': <range_iterator object at 0x00000000030019F0>} 
{'x': 0, '.0': <range_iterator object at 0x00000000030019F0>} 

因此,locals() 在 exec 内部或外部都是相同的。改变它的是列表理解。只是,当您在 exec 语句之外时,解释器可以超越列表理解的局部并在外部范围内找到 self 。一旦调用 exec,就没有这样的运气了。