在Python中共享调用函数与被调用函数的作用域
有没有办法在Python中管理作用域,让调用函数中的变量在被调用的函数中也能被看到?我想要的效果像下面这样:
z = 1
def a():
z = z * 2
print z
def b():
z = z + 1
print z
a()
print z
b()
我希望能得到以下输出:
2
4
2
解决这个问题的真正方法就是把z作为一个变量传递过去。但我不想这么做。
我的代码库很大而且复杂,里面有不同水平的用户。他们现在已经习惯只传递一个变量,而我现在需要添加另一个变量。我不太相信他们能在所有函数调用中都正确地传递第二个变量,所以我在寻找一种保持接口不变的替代方案。很有可能这根本就做不到。
5 个回答
3
这个方法看起来有点复杂,但它避免了使用全局变量,我测试过了,确实有效。使用选定答案中的代码,函数 getSetZ()
有一个“静态”变量,可以用来存储传入的值,然后在函数被调用时,如果传入 None
,就可以取出这个值。有一些限制,比如它假设 None
不是 z 的可能值,而且不适合在多线程环境中使用。你只需要记得在每次调用你想要使用调用函数的 z
的函数之前,先调用一次 getSetZ()
,然后把从 getSetZ()
中取出的值放到那个函数的局部变量里。
def getSetZ(newZ):
if newZ is not None:
getSetZ.z = newZ
else:
return getSetZ.z
def a():
z = getSetZ(None)
z = z * 2
print z
def b():
z = getSetZ(None)
z = z + 1
print z
getSetZ(z)
a()
print z
getSetZ.z = 0
getSetZ(1)
b()
希望这对你有帮助。
7
这里可能适合用一个类来解决问题:
class MyClass(object):
def __init__(self, z):
self.z = 1
def a(self):
self.z = self.z * 2
print self.z
def b():
self.z = self.z + 1
print self.z
self.a()
print self.z
你也可以用全局变量来达到相同的效果,但我建议你创建一个自己的独立命名空间(比如用一个类),这样可以更好地管理你的代码范围。
14
我觉得这就是你想要的。如果你能控制内部的函数,并且你想要的变量已经在调用链的某个地方可用了,但你又不希望用户在调用时必须包含这个变量。很明显,你不想用global
关键字,因为你不希望内部的赋值影响到外部的范围。
使用inspect
模块可以让你访问到调用的上下文。(不过,要注意这有点脆弱。你最好只在没有线程的CPython中使用。)
import inspect
def calling_scope_variable(name):
frame = inspect.stack()[1][0]
while name not in frame.f_locals:
frame = frame.f_back
if frame is None:
return None
return frame.f_locals[name]
z = 1
def a():
z = calling_scope_variable('z')
z = z * 2
print z
def b():
z = calling_scope_variable('z')
z = z + 1
print z
a()
print z
b()
这样确实能得到正确的答案:
2
4
2