Python overwriting variables in nested functions
假设我有以下python代码:
1 2 3 4 5 6 | def outer(): string ="" def inner(): string ="String was changed by a nested function!" inner() return string |
我希望调用outer()返回"字符串已被嵌套函数更改!"但我得到了。我的结论是,python认为行
在python 3.x中,可以使用
1 2 3 4 5 6 7 | def outer(): string ="" def inner(): nonlocal string string ="String was changed by a nested function!" inner() return string |
在python 2.x中,可以将列表与单个元素一起使用,并覆盖该单个元素:
1 2 3 4 5 6 | def outer(): string = [""] def inner(): string[0] ="String was changed by a nested function!" inner() return string[0] |
您还可以通过使用函数属性来绕过这个问题:
1 2 3 4 5 6 | def outer(): def inner(): inner.string ="String was changed by a nested function!" inner.string ="" inner() return inner.string |
说明:这在python 2.x和3.x中都有效。
这种情况经常发生在我身上,当我编写一个函数时,我突然意识到有一个较小的助手函数可能是一个好主意,但在其他任何地方都没有真正的用处。这很自然地让我想在内部将它定义为一个嵌套函数。
但我有Java匿名对象的经验(即:定义一个Runnabl),并且规则是匿名对象对其外部环境进行硬拷贝,在这种情况下,外部范围的变量。因此,如果外部变量是不可变的(
如果您了解编程,请将其视为传递值和传递引用。
在Python中,它是非常相同的。
总而言之,您需要一个可变对象……以便进行修改(即使您可以使用[]访问一个元组,但您不能在此处使用它,因为它不可变)
要添加到Sven的答案中:
在python 2.x中,只能从内部范围读取外部范围变量。赋值只会创建一个隐藏外部作用域1的新本地(即内部作用域)变量。
如果要读取和修改,可以使用
1 2 3 4 5 6 7 8 9 10 11 | def outer(): # hold some text, plus the number of spaces in the text vars = {'text': 'Some text.', 'num_spaces': 1} def inner(): # add some more text more_text = ' Then some more text.' vars['text'] += more_text # keep track of the number of spaces vars['num_spaces'] += more_text.count(' ') inner() return vars['text'], vars['num_spaces'] |
输出:
1 2 | >>> outer() ('Some text. Then some more text.', 5) |