Python 未来';什么是执行工作?

Python 未来';什么是执行工作?,python,python-3.x,python-2.x,Python,Python 3.x,Python 2.x,这段代码是如何工作的,这些转发端口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:

这段代码是如何工作的,这些转发端口
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""")
这段代码是从中复制的,因为我太懒了,找不到哪个Martijn Pieters链接到了

也欢迎针对Six(相同的条形码)版本的答案。

对于Python 3:

if PY3:
这是相对严格的:

    import builtins
    exec_ = getattr(builtins, "exec")
使用
getattr
的原因是,在Python2上
exec
是一种声明,您希望避免:

>>> builtins.exec
  File "<stdin>", line 1
    builtins.exec
                ^
SyntaxError: invalid syntax
我们希望将
exec\uuu
定义为类似于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
,我们希望它默认为调用者作用域的globals。这实际上相当复杂

首先我们得到外框:

sys.\u getframe
只是调用方的作用域。框架是函数执行的环境,它存储了一些有趣的属性,例如从函数的角度来看的全局属性

如果有:

            if locs is None:
                locs = frame.f_locals
locs
默认为本地值

删除该框架是为了防止在调用
exec
期间不必要地保持活动状态

            del frame
最终

        elif locs is None:
            locs = globs
这就是“如果只给出全局变量,则局部变量默认为全局变量”部分

然后是最有趣的部分:

        exec("""exec code in globs, locs""")
在globs、locs中运行
exec代码意味着在python3上编译时会出现错误,因为
exec
不再是语句。因此,进行外部
exec(““exec code in globs,locs”“”)
调用

在Python3上,这将永远不会运行,而是编译。在Python2上,这将捕获本地
globs
locs
,允许它在globs、locs
中运行
exec代码


正如他所指出的,包括Martijn Pieters所提出的一些信息,这些神奈根实际上有些无关紧要。

最后的
exec(“globs,locs中的exec code”)确实是多余的,通过将代码编写为

exec (code) in globs, locs
在python 2中,它将被解析为

exec code in globs, locs
tuple([print >> sys.stdout, argument, argument, argument])
在Python3中,它实际上与

tuple([exec(code) in globs, locs])

但是,Python中的
exec
语句始终能够接受元组参数,因此
exec
行可以写成

exec(code, globs, locs)
在Python2和Python3中运行相同,甚至

exec(tuple([code, globs, locs]))
(仅适用于Python 2);事实上,在Python3中唯一可以做的事情是Python2中不可能做的,并且为什么需要这个包装器是为了使它成为一个真正的函数/方法对象,可以指定给另一个名称或作为参数传递,就像当前一样

exec_ = exec
在Python 2中是
SyntaxError


类似地,在Python 3中

print argument, argument, argument,
是一个语法错误,但在多段代码中总是可以包含

if PY2:
    print >> sys.stdout, argument, argument, argument,
在Python 3中,它将被解析为

exec code in globs, locs
tuple([print >> sys.stdout, argument, argument, argument])

实际上,
def exec\uuuu
中的双执行是不必要的:
exec(code)在globs,locs
中,在
code
周围加上额外的括号,在python3中不会导致
SyntaxError
,在python2中,您可以使用
exec(code,globs,locs)
很好;它与Python 3开箱即用是向前兼容的。@MartijnPieters你知道是什么版本引入的吗?@Veedrac:它一直在工作,因为
exec
变成了一个语句,但元组形式是为了向后兼容而保留的。链接到原文: