gpt4 book ai didi

python - Future 的 exec_ 是如何工作的?

转载 作者:行者123 更新时间:2023-11-28 21:53:32 29 4
gpt4 key购买 nike

这段向前移植 exec 的代码是如何工作的?

# Implementation of exec_ is from ``six``:
if PY3:
import builtins
exec_ = getattr(builtins, "exec")
else:
def exec_(code, globs=None, locs=None):
"""Execute code in a namespace."""
if globs is None:
frame = sys._getframe(1)
globs = frame.f_globals
if locs is None:
locs = frame.f_locals
del frame
elif locs is None:
locs = globs
exec("""exec code in globs, locs""")

该片段复制自Python Future因为懒得找the original from Six Martijn Pieters 链接到的。

也欢迎针对 Six(相同栏 reraise)版本的特定答案。

最佳答案

对于 Python 3:

if PY3:

这是相对简单的:

    import builtins
exec_ = getattr(builtins, "exec")

使用 getattr 的原因是在 Python 2 上 exec 是一个语句,你想避免:

>>> builtins.exec
File "<stdin>", line 1
builtins.exec
^
SyntaxError: invalid syntax

使用字符串进行查找可以解决 exec 不是有效标识符的问题。

如果是 Python 2:

else:

我们想将 exec_ 定义为类似于 Python 3 上的 exec,这意味着它看起来像这样:

    def exec_(code, globs=None, locs=None):
"""Execute code in a namespace."""

让我们快速查看文档:

help(exec)
#>>> Help on built-in function exec in module builtins:
#>>>
#>>> exec(...)
#>>> exec(object[, globals[, locals]])
#>>>
#>>> Read and execute code from an object, which can be a string or a code
#>>> object.
#>>> The globals and locals are dictionaries, defaulting to the current
#>>> globals and locals. If only globals is given, locals defaults to it.
#>>>

这应该有助于解释下一部分:

        if globs is None:
frame = sys._getframe(1)
globs = frame.f_globals

如果 globs 是 None,我们希望它默认为调用者作用域的全局变量 。这其实很复杂。

首先我们得到外框:

import sys
help(sys._getframe)
#>>> Help on built-in function _getframe in module sys:
#>>>
#>>> _getframe(...)
#>>> _getframe([depth]) -> frameobject
#>>>
#>>> Return a frame object from the call stack. If optional integer depth is
#>>> given, return the frame object that many calls below the top of the stack.
#>>> If that is deeper than the call stack, ValueError is raised. The default
#>>> for depth is zero, returning the frame at the top of the call stack.
#>>>
#>>> This function should be used for internal and specialized
#>>> purposes only.
#>>>

sys._getframe 只是调用者的作用域。框架是函数执行发生的环境,并存储几个有趣的属性,例如 f_globals - 从该函数的角度来看的全局变量。

那么如果是:

            if locs is None:
locs = frame.f_locals

locs 默认为本地。

删除框架是为了防止在 exec 调用期间不必要地保持事件状态。

            del frame

倒数第二,

        elif locs is None:
locs = globs

这是为了满足“如果只给出全局变量,则默认为局部变量”。部分。

然后是最有趣的部分:

        exec("""exec code in globs, locs""")

只运行 exec code in globs, locs 意味着在 Python 3 上编译时,这会出错,因为 exec 不再是语句。因此,将进行外部 exec("""exec code in globs, locs""") 调用。

在 Python 3 上,它永远不会运行,但会编译。在 Python 2 上,这将捕获局部变量 globslocs,允许它在 globs, locs 中运行 exec 代码。






Please do look at Antti Haapala's answer, though因为这些恶作剧实际上与他指出的内容有些无关,包括 Martijn Pieters 提出的一些信息。








关于python - Future 的 exec_ 是如何工作的?,我们在Stack Overflow上找到一个类似的问题:

https://stackoverflow.com/questions/26097789/




29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com