如何在命名空间字典中执行函数?

cap*_*tle 5 python python-3.x

假设我有以下命令:

In [6]: scope
Out[6]: {'bar': <function bar>, 'foo': <function foo>}
Run Code Online (Sandbox Code Playgroud)

并且foobar是:

def foo():
    return 5

def bar(x):
    return foo() + x
Run Code Online (Sandbox Code Playgroud)

我想跑bar(1),但还需要找到foo()bar()有没有办法在名称空间中运行scope以便找到foo()

我不确切知道需要哪个函数,所以我需要一个在命名空间中scope bar运行的通用方法。我没有源代码,也无法修改任何一个函数来接受字典。barscope

看起来函数有一个__closure__属性,但它是不可变的。还有一个__globals__属性,但它仅指向globals(). 我已经看到了有关该更新的一些答案,locals()但我想保持locals()不变。

我尝试了evalin scope,但得到了NameErrorfor foo

In [12]: eval(scope['bar'](1), scope)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-12-f6305634f1da> in <module>()
----> 1 eval(scope['bar'](1), scope)

<string> in bar(x)

NameError: global name 'foo' is not defined
Run Code Online (Sandbox Code Playgroud)

我缺少一些简单的方法吗?

mar*_*eau 2

使用eval()会起作用,但是您尝试使用它的方式存在两个问题。对于初学者来说,它的第一个参数expression应该是一个字符串。其次,由于您scope在该表达式中引用并将eval()作为全局命名空间参数传递,因此您需要将其添加到自身。

这说明了我的意思:

def foo():
    return 5

def bar(x):
    return foo() + x

scope = {'scope': {'bar': bar, 'foo':foo}}  # define self-referential scope
expression = "scope['bar'](42)"  # explicit reference to `scope`
print('eval({!r}, scope) returns {}'.format(expression, eval(expression, scope)))
Run Code Online (Sandbox Code Playgroud)

然而,在这种特定情况下,直接在字典命名空间本身中eval()查找 的值(而不是 via )会更简单:barscopescope['scope']['bar']

scope = {'bar': bar, 'foo':foo}
expression = 'bar(42)'
print('eval({!r}, scope) returns {}'.format(expression, eval(expression, scope)))
Run Code Online (Sandbox Code Playgroud)