我有一个函数P()
。致load_variables()
的调用应该为P
变量x
。
load_variables
应该能够接受默认值作为关键字参数。
如何做到这一点?
我尝试了以下内容:
import inspect
def P():
x = 1
load_variables(x = 2)
return x
def load_variables(**kargs):
stack = inspect.stack()
try:
locals_ = stack[1][0].f_locals
finally:
del stack
for __k, __v in kargs.iteritems():
locals_[__k] = __v
print P() # => should print 2
x = 1
行实际上并不存在,因为我希望load_variables()
将x
放到P
的范围内。
还有另一种,或许更好的方法吗?我想要的是:
x = 2
的调用load_variables()
。load_variables
覆盖这些内容,例如,load_varibales()
可以访问变量字典,如果x
已经在这里,我们会覆盖它,并将其溢出{{ 1}}而不是作为默认参数给出的那个。答案 0 :(得分:1)
更新:正如DSM指出的那样,不支持更新locals()
。所以,答案是不正确的,至少对于CPython来说。
你能让 load_variables()
返回一个字典并使用locals()
来更新局部变量:
def P():
x=1
locals().update(load_variables(x=2))
return x
def load_variables(**kargs):
res={}
for __k, __v in kargs.iteritems():
res[__k] = __v
return res
请注意,x=1
是必需的,否则x
将被字节码编译器假定为全局变量,NameError
将获得return x
异常击>
如果你真的想要摆脱 x=1
,你可以改为retrun locals()['x']
。
答案 1 :(得分:1)
Python编译器和字节码解释器在可能的情况下处理对作为定义大小数组的插槽的局部变量的引用。这意味着如果局部变量未在作用域中初始化(赋值),则语言将不知道作用域中存在该变量的槽,而是在封闭作用域或全局作用域中查找该变量。查看函数P
的反汇编:
def P():
load_variables(x=2)
return x
dis.dis(P)
2 0 LOAD_GLOBAL 0 (load_variables)
3 LOAD_CONST 1 ('x')
6 LOAD_CONST 2 (2)
9 CALL_FUNCTION 256
12 POP_TOP
3 13 LOAD_GLOBAL 1 (x)
16 RETURN_VALUE
您可以看到,如果未在本地范围内x
分配P
,则会在全局范围内查找。
执行此操作的正确方法是使用解包显式声明您希望load_variables
函数返回哪些变量:
x, y, z = load_variables(...)
答案 2 :(得分:1)
由于我们在这里谈论Python,可能有一种方法可以做到,但我想知道:你应该尝试吗?
通常,定义共享存储/值对象然后传递它更好:
data = {}
def P(data):
load_variables(data, x=2)
return data['x']
def load_variables(data, **kargs):
data.update(kargs)
这样,你就不会有不可预见的副作用。