访问Python 2.6中的外部作用域

时间:2011-01-21 21:27:40

标签: python scope

说,我有一些变量范围,并且在这个范围内调用的函数想要更改一些不可变变量:

def outer():
    s = 'qwerty'
    n = 123
    modify()

def modify():
    s = 'abcd'
    n = 456

是否有可能以某种方式访问​​外部范围?类似Py3k的nonlocal变量。

当然,在这种情况下我可以做s,n = modify(s,n),但如果我需要一些在那里执行的通用“注入”并且必须能够重新分配给任意变量呢?

我考虑到了绩效,如果可能的话,eval&不欢迎堆栈框架检查:)


UPD :这是不可能的。期。但是,如何访问外部作用域中的变量有一些选项:

  1. 使用全局变量。顺便说一句,func.__globals__是一个可变的字典;)
  2. 将变量存储在dict / class-instance /任何其他可变容器中
  3. 将变量作为参数&将它们作为元组取回:a,b,c = innerfunc(a,b,c)
  4. 注入其他函数的字节码。这可以通过byteplay python模块实现。

6 个答案:

答案 0 :(得分:7)

定义函数之外的变量并使用global关键字。

s, n = "", 0

def outer():
    global n, s
    n = 123
    s = 'qwerty'
    modify()

def modify():
    global n, s
    s = 'abcd'
    n = 456

答案 1 :(得分:7)

有时候我会遇到像这样的代码。嵌套函数修改可变对象,而不是分配给nonlocal

def outer():
    s = [4]
    def inner():
        s[0] = 5
    inner()

答案 2 :(得分:3)

nonlocal如何运作。它不提供动态范围(这只是一个巨大的PITA等待发生,甚至比普通的“邪恶”特征更有用)。它只是修复了词法范围。

无论如何,你不能做你想到的事情(我会说这是一件好事)。甚至没有一个肮脏但容易破解的黑客(当我们处于它的时候:这样的黑客不会气馁,因为它们通常表现得更差!)。忘记它并正确解决真正的问题(你没有说出来,所以我们不能就此发表任何意见)。

你可以得到的最接近的是定义一个对象,它包含你想要分享的所有内容并明确地传递它(例如,如另一个答案所示,创建一个类并使用self)。但到处都是相对麻烦,而且仍然是hackery(虽然比动态范围更好,因为“显式优于隐式”)。

答案 3 :(得分:3)

您的选择是使用global变量,

s = None
n = None

def outer(self):
    global s
    global n
    s = 'qwerty'
    n = 123
    modify()

def modify(self):
    global s
    global n
    s = 'abcd'
    n = 456

或将它们定义为方法并使用类或实例变量。

class Foo(object):
    def __init__(self):
        self.s = None
        self.n = None

    def outer(self):
        self.s = 'qwerty'
        self.n = 123
        self.modify()

    def modify(self):
        self.s = 'abcd'
        self.n = 456

答案 4 :(得分:1)

你也可以这样做(不是说它是对的);

定义一个返回数组的函数,其中包含类似

的行
["a = qwerty","n = 123"]

然后在你需要vars的范围内做

for row in array:
  eval(row)
但是,这非常讨厌。

答案 5 :(得分:0)

def a():
    i = 1

    def b():
        # i = 2

        def c():
            nonlocal i
            i = 3

        c()
        print('b:', i)

    b()
    print('a:', i)


a()

nonlocal将在较高级别的范围内进行搜索,如果未找到则向上移

> python3 t.py
b: 3
a: 1

评论i = 2

> python3 t.py
b: 3
a: 3