在Python 2.6中访问外部作用域
假设我有一些变量在某个范围内,而这个范围里的一个函数想要改变一些不可变的变量:
def outer(): s = 'qwerty' n = 123 modify() def modify(): s = 'abcd' n = 456
有没有办法访问外部范围的变量呢?就像Python 3中的nonlocal
变量那样。
当然,我可以这样做:s,n = modify(s,n)
,但是如果我需要一些通用的“注入”操作,让它在那儿执行,并且能够重新赋值给任意变量呢?
我考虑到性能,所以如果可能的话,不想使用eval
和堆栈帧检查这些方法 :)
更新:这是不可能的。就这样。不过,有一些方法可以访问外部范围的变量:
- 使用全局变量。顺便提一下,
func.__globals__
是一个可变的字典;) - 把变量存储在字典、类实例或其他可变容器中。
- 把变量作为参数传入,然后以元组的形式返回它们:
a,b,c = innerfunc(a,b,c)
- 注入其他函数的字节码。这可以通过
byteplay
这个Python模块实现。
6 个回答
7
在函数外面定义变量,并使用 global
关键字。
s, n = "", 0
def outer():
global n, s
n = 123
s = 'qwerty'
modify()
def modify():
global n, s
s = 'abcd'
n = 456
7
有时候我会看到这样的代码。里面有一个嵌套的函数,它修改了一个可变对象,而不是给一个nonlocal
变量赋值:
def outer():
s = [4]
def inner():
s[0] = 5
inner()
3
这并不是说nonlocal
的工作方式。它并不提供动态作用域(这其实是个大麻烦,几乎没有什么用处,甚至比一般的“坏”特性还要少)。它只是修正了词法作用域。
总之,你想的那种做法是行不通的(我觉得这其实是件好事)。连个简单的黑科技都没有(顺便说一下:这种黑科技并不被反对,因为它们通常性能稍差!)。所以就别想这个了,去好好解决真正的问题吧(你没有提到具体问题,所以我们也没法说什么)。
你能做到的最接近的方式是定义一个对象,把你想共享的所有东西都放在里面,然后明确地传递这个对象(比如,创建一个类并使用self
,就像另一个回答中提到的那样)。不过这样做在很多地方都比较麻烦,而且还是有点黑科技(虽然比动态作用域要好,因为“显式比隐式好”)。