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
变成了一个语句,但元组形式是为了向后兼容而保留的。链接到原文: