将变量注入调用者的作用域中?
我可以定义一个函数,当这个函数被调用时,能够在调用它的地方插入新的局部变量吗?我觉得把调用者的 locals() 传给这个函数可能可以实现,但有没有办法做到我想要的 而不需要 这样做呢?
3 个回答
0
这件事不可能做到,因为CPython在函数调用期间会保留对参数列表的引用。
一种解决方法是传递一个对象,然后在使用完这个对象后清空它的内部状态。
class Obj(object):
def __init__(self, state):
self.state = state
def f(o):
# Do stuff with o.state
del o.state
9
根据Python的规则,你不能直接修改调用你函数的地方的本地变量。在目前的实现中,如果你尝试这样做(比如用Anurag提到的那些“黑魔法”),你不会收到错误提示(虽然我想在未来的版本中加入这个错误检查),但是如果调用者是一个函数的话,你的修改实际上不会生效(如果调用者是模块的顶层代码,那就另当别论了)——调用者的实际本地变量不会受到影响。无论调用者的本地变量是显式传入的,还是通过“黑魔法”获取的,如果你的代码想要保持合理性,它们都应该被视为只读的字典。
相反,你可以让调用者传入一个明确的、真实的、普通的字典(如果你想的话,可以从locals()
初始化这个字典),这样你在这个字典上所做的所有修改都会保留给调用者使用——当然,这些修改不会作为“新的变量名”出现在调用者的本地作用域中,但无论调用者是用x['foo']
、x.foo
,还是(如你所希望的)直接用变量名foo
,功能都是一样的。
顺便说一下,如果你想使用属性访问的语法,而不是字典索引的语法,你可以这样做:
class Bunch(object): pass
...
# caller code
b = Bunch()
thefun(b)
print b.foo
...
# called function
def thefun(b):
b.foo = 23
这也涵盖了一个小变体的情况,即thefun
想使用字典索引的语法(比如它的主体是b['foo'] = 23
而不是b.foo = 23
):在这种情况下,调用者只需要使用thefun(vars(b))
而不是简单的thefun(b)
,但之后它仍然可以继续使用b.foo
的访问语法。