使用其中的另一个方法更改方法内的变量

时间:2015-12-23 08:11:06

标签: python

以下代码引发UnboundLocalError

def foo():
    i = 0
    def incr():
        i += 1
    incr()
    print(i)

foo()

有没有办法实现这个目标?

7 个答案:

答案 0 :(得分:30)

使用nonlocal声明

def foo():
    i = 0
    def incr():
        nonlocal i
        i += 1
    incr()
    print(i)

foo()

有关python 3.x中添加的新语句的更多信息,请转到https://docs.python.org/3/reference/simple_stmts.html#the-nonlocal-statement

答案 1 :(得分:20)

您可以使用i作为参数:

def foo():
    i = 0
    def incr(i):
        return i + 1
    i = incr(i)
    print(i)

foo()

答案 2 :(得分:9)

请参阅9.2. Python Scopes and Namespaces

  

如果没有global语句生效 - 名称的赋值总是进入最里面的范围。

此外:

  

global语句可用于表示特定变量存在于全局范围内,应该在那里反弹; nonlocal语句表明特定变量存在于封闭范围中,应该在那里反弹。

你有很多解决方案:

  • 通过i作为参数✓(我会选择这个)
  • 使用nonlocal关键字

请注意,在Python2.x中,您可以访问非本地变量,但无法更改它们。

答案 3 :(得分:4)

在Python中,int是不可变的。所以你可以将你的int放在一个可变对象中。

def foo():
    i = 0
    obj = [i]
    def incr(obj):
        obj[0]+=1
    incr(obj)
    print(obj[0])

foo()

答案 4 :(得分:2)

您可以将i设为全局并使用它。

i = 0
def foo():
    def incr():
        global i
        i += 1
    incr()
    print(i)

foo()

但最首选的方法是将i作为参数传递给incr

def foo():
    i = 0
    def incr(arg):
        arg += 1
        return arg
    i = incr(i)
    print(i)

foo()

答案 5 :(得分:0)

你也可以使用lambda函数:

def foo():
  i=0
  incr = lambda x: x+1
  print incr(i)

foo()

我认为代码更清洁

答案 6 :(得分:0)

在这种情况下,简单的函数属性不起作用。

>>> def foo():
...     foo.i = 0
...     def incr():
...         foo.i +=1
...     incr()
...     print(foo.i)
... 
>>> 
>>> 
>>> foo()
1
>>> foo()
1
>>> foo()
1

每次拨打0时,您都会将foo.i指定给foo。 最好使用hassattr。但是代码变得更加复杂。

>>> def foo():
...     if not hasattr(foo, 'i'):
...         foo.i = 0
...     def incr():
...         foo.i += 1
...         return foo.i
...     i = incr()
...     print(i)
... 
>>> 
>>> 
>>> foo()
1
>>> foo()
2
>>> foo()
3

你也可以尝试这个想法:

>>> def foo():
...     def incr():
...         incr.i += 1
...         return incr.i
...     incr.i = 0
...     return incr
... 
>>> a = foo()
>>> a()
1
>>> a()
2
>>> a()
3
>>> a()
4

将你装入装饰师可能会更方便。