我有信心至少对Python的范围系统有一些基本的了解.现在我收到一个错误,遗憾的是到目前为止我甚至无法为复制编写好的代码片段.我尝试在一个新的小项目中重现它,但一切都按照我的预期运行: - /
我只能描述我的所作所为,并希望有人能够检测出一种模式并告诉我这里可能出现的问题.
起初有一个python文件x.py实现了一个类X.
在其他一些python文件中,有以下字符串:
code="""
...
from x import X
...
class Y(X): # does not crash here, ...
def __init__(self):
X.__init__(self) # ... but here
...
foo=Y()
"""
Run Code Online (Sandbox Code Playgroud)
您可以假设python能够找到该x模块.在某个地方,我尝试执行:
exec(code, globals(), locals())
Run Code Online (Sandbox Code Playgroud)
现在我得到了NameError.它告诉我,X当它试图调用它的构造函数时没有定义.它显然定义在上面几行.
如果我通过Y.__init__添加from x import X为第一行进行修改,则可以正常工作.但为什么我要在那里再次导入呢?
如前所述,实际代码更复杂,并且做了更多事情.在一个不幸的情况下,我的帖子甚至没有显示实际导致问题的部分.但也许你有一些一般的想法,如何才能得到这样的行为.
这只是一个猜测,因为您没有给我们展示足够的代码,而您给我们展示的内容实际上并没有重现问题,但是……
如果您在exec函数内部执行此操作,则locals()和globals()将有所不同。在这种情况下,代码将像在类定义中一样被执行。因此,就像您这样做:
class _:
from x import X
class Y(X): # does not crash here, ...
def __init__(self):
X.__init__(self) # ... but here
foo=Y()
del _
Run Code Online (Sandbox Code Playgroud)
(我以前认为您还必须在Y()之外执行类似的操作exec,但user2357112的回答使我确信这不是必需的。)
如果这是您的问题,您可以通过致电exec(code, globals(), globals())或来解决exec(code, locals(), locals())。(当然,哪一个合适,取决于您实际上要尝试执行的操作,而您没有告诉我们。)
从exec文档:
如果exec获得两个单独的对象作为全局变量和局部变量,则代码将被执行,就像它嵌入在类定义中一样.
这有很好的理由,我不会在这里讨论.
类定义中定义的函数不会查看变量分辨率的类定义的范围.当你exec的时候code,它实际上是这样执行的:
class Dummy:
from x import X
...
class Y(X):
def __init__(self):
X.__init__(self)
...
foo=Y()
Run Code Online (Sandbox Code Playgroud)
这意味着这个功能:
def __init__(self):
X.__init__(self)
Run Code Online (Sandbox Code Playgroud)
没有看到这个变量:
from x import X
Run Code Online (Sandbox Code Playgroud)
即使这一点:
class Y(X):
Run Code Online (Sandbox Code Playgroud)
确实看到了.