是否可以从函数内访问 exec 提供的全局字典?
Is it possible to access exec-provided globals dictionary from within a function?
如果函数是在 exec 代码之外定义的(因此已经绑定到不同的 __globals__
),是否可以从函数内部访问 exec 提供的全局字典?
换句话说,有没有办法让下面的例子起作用?
def f():
log("Hi")
exec('f()', {'f': f, 'log': print})
一般来说,是否可以替换函数的__globals__
?
不确定我的解释是否完全正确。 简而言之,这个例子不能在Python 3.
中运行
原因是两种情况的组合:[1] - exec
是 Python 中的一个函数 3、[2] - 您尝试执行的代码包含函数调用。
当您向函数 exec
提供 globals
可选参数时,它是该函数的局部范围。所以下面的例子有效:
exec('log("Hi")', {'log': print})
但是原来的没有。因为在原始示例中,您调用了函数 f
。它有自己的本地范围。 Python 做什么?它检查全局范围(程序的实际全局范围)和最内层范围(函数的局部范围 f
)。两个范围都缺少 log
,你得到 NameError
.
您可以使用两个常规函数获得完全相同的行为(相同的错误):
def f():
log("Hi")
def f_():
log = print
f()
f_()
这是一件很奇怪的事情,但它是可行的。
您的 exec 调用在提供的全局变量中执行语句 f()
。它不会在提供的全局变量中执行 f
的 body。在错误的堆栈框架中使用了提供的全局变量。要从 f
访问这些全局变量,您可以使用 stack inspection:
import inspect
def f():
log = inspect.currentframe().f_back.f_globals['log']
log('Hi')
exec('f()', {'f': f, 'log': print})
如果您想使用提供的全局变量执行 f
的主体而不是仅仅获得对全局变量的访问权限,您需要使用您自己的自定义全局变量制作 f
的副本:
import types
my_f = types.FunctionType(f.__code__,
{'log': print},
f.__name__,
f.__defaults__,
f.__closure__)
my_f()
函数类型构造函数有一定的记录;它不在在线文档中,但 记录在函数类型的文档字符串中:
function(code, globals[, name[, argdefs[, closure]]])
Create a function object from a code object and a dictionary.
The optional name string overrides the name from the code object.
The optional argdefs tuple specifies the default argument values.
The optional closure tuple supplies the bindings for free variables.
如果函数是在 exec 代码之外定义的(因此已经绑定到不同的 __globals__
),是否可以从函数内部访问 exec 提供的全局字典?
换句话说,有没有办法让下面的例子起作用?
def f():
log("Hi")
exec('f()', {'f': f, 'log': print})
一般来说,是否可以替换函数的__globals__
?
不确定我的解释是否完全正确。 简而言之,这个例子不能在Python 3.
中运行原因是两种情况的组合:[1] - exec
是 Python 中的一个函数 3、[2] - 您尝试执行的代码包含函数调用。
当您向函数 exec
提供 globals
可选参数时,它是该函数的局部范围。所以下面的例子有效:
exec('log("Hi")', {'log': print})
但是原来的没有。因为在原始示例中,您调用了函数 f
。它有自己的本地范围。 Python 做什么?它检查全局范围(程序的实际全局范围)和最内层范围(函数的局部范围 f
)。两个范围都缺少 log
,你得到 NameError
.
您可以使用两个常规函数获得完全相同的行为(相同的错误):
def f():
log("Hi")
def f_():
log = print
f()
f_()
这是一件很奇怪的事情,但它是可行的。
您的 exec 调用在提供的全局变量中执行语句 f()
。它不会在提供的全局变量中执行 f
的 body。在错误的堆栈框架中使用了提供的全局变量。要从 f
访问这些全局变量,您可以使用 stack inspection:
import inspect
def f():
log = inspect.currentframe().f_back.f_globals['log']
log('Hi')
exec('f()', {'f': f, 'log': print})
如果您想使用提供的全局变量执行 f
的主体而不是仅仅获得对全局变量的访问权限,您需要使用您自己的自定义全局变量制作 f
的副本:
import types
my_f = types.FunctionType(f.__code__,
{'log': print},
f.__name__,
f.__defaults__,
f.__closure__)
my_f()
函数类型构造函数有一定的记录;它不在在线文档中,但 记录在函数类型的文档字符串中:
function(code, globals[, name[, argdefs[, closure]]])
Create a function object from a code object and a dictionary.
The optional name string overrides the name from the code object.
The optional argdefs tuple specifies the default argument values.
The optional closure tuple supplies the bindings for free variables.