我正在尝试从已定义的变量中增加或减少,但是我不知道如何用新的变量覆盖旧的值。

a = 15

def test():
    a = a +10
    print ( a )

test()


错误消息:

 Traceback (most recent call last):
  File "test.py", line 7, in <module>
    test()
  File "test.py", line 4, in test
    a = a +10
UnboundLocalError: local variable 'a' referenced before assignment
 


评论

加号后可能需要一个空格。如果符号之间没有空格,Swift也会给出错误信息。

请将图像中的代码作为文本添加到问题本身。

Python中UnboundLocalError的可能重复项

这个问题包括所需的行为,特定的问题或错误,并且,除非我们真正地将头发分开成一行,否则是再现它所需的最短代码。毫无疑问,它是@approxiblue所引用问题的重复,但可能是一个更好的问题,因为该问题使用了增强分配(对于初学者来说,错误消息根本没有意义),并且可接受的答案不负责任地建议仅使用。全局或非本地而不是首先避免使用全局变量。

我已经投票决定要重新开放。虽然一个肯定是另一个的重复,但我认为应该将所提及的问题标记为该重复的重复,因为它的含义不太清楚,可接受的答案很糟糕,而当前被标记为重复的问题是甚至更糟。有关此原理的背景信息,请参见meta.stackoverflow.com/questions/251938/…。

#1 楼

尝试运行代码时遇到的错误是:

UnboundLocalError: local variable 'a' referenced before assignment


…从表面上看,这似乎很奇怪:毕竟,其中的第一个语句上面的代码(a = 15)是一个分配。因此,发生了什么事?

实际上,发生了两种截然不同的事情,除非您已经知道它们,否则它们都不是显而易见的。

首先,您实际上有两个不同的变量:


第一行中的a是全局变量(之所以这样称呼,是因为它存在于全局范围内,在任何函数定义之外)。其他行中的a是局部变量,意味着它仅存在于test()函数内部。

这两个变量即使名称相同,也完全不相关。

如果在函数中有一个分配给该函数的语句(例如您的a = a +10行),则该变量对于该函数是局部的。

即使如此,错误仍然看起来很奇怪-毕竟,您在test()内部所做的第一件事就是分配给a,那么如何事先对其进行引用?

答案是,在赋值语句中,Python eva在将=符号的右手边的所有内容分配给左手边的名称之前,先对其进行遍历-因此,即使该赋值是在您的代码中首先编写的,a仍会在该右手边首先被引用:a +10

有两种方法可以解决此问题。首先是要告诉Python,您真的希望a内部的test()与全局范围内的a相同:

def test():
    global a
    a = a + 10
    print(a)


这将起作用,但这是编写程序的一种非常糟糕的方法。更改函数内部的全局变量变得很难很快地进行管理,因为您通常有很多函数,而且它们中的任何一个都无法确保另一个函数不会以他们不期望的某种方式弄乱全局变量。 />
更好的方法是将变量作为参数传递给函数,如下所示:

a = 15

def test(x):
    x = x + 10
    print(x)

test(a)


请注意,名称不必相同-您对test()的新定义只是说它接受一个值,然后对该值进行处理。您可以输入任何喜欢的内容-可以是a或数字7或其他名称。实际上,如果您尝试避免在不同的作用域中使用名称相同的变量,那么您的代码将总是更容易理解。

如果您使用上面的代码,您会发现一些有趣的事情:

>>> a = 15
>>> test(a)
25
>>> a
15


a没变!这是因为,尽管您将其传递给test()并分配给了x,但后来更改了x,而原来的a却没有得到解决。从函数中修改了a,然后在外部将其重新分配回x

>>> a = 15
>>> 
>>> def test(x):
...     x = x + 10
...     print(x)
...     return x
... 
>>> a = test(a)
25
>>> a
25


评论


在有人指出x实际上已被替换而不是更改之前……我知道。但是,我已经必须要有一定的基础才能正确回答这个问题,并且决定不打开这种特殊的蠕虫罐头。

–零比雷埃夫斯(Zero Piraeus)
16 Dec 28'在21:37

谢谢,这是一个很好的答案。因此,可以肯定的是,实际上没有办法定义测试函数以使其实际更改为“ a”吗?即,没有办法通过一些更复杂的代码将外部重新分配步骤a = test(a)合并到函数本身中吗?

–user26866
12月23日19:21

#2 楼

我会这样做:

def test(a):
    a = a +10
    return a

print(test(15))


请注意,在此建议的版本中,有一些与您的有所不同。

首先,什么我写下来将创建一个函数,该函数具有一个值a(作为输入,在本例中,当我们调用函数-已在最后一行中定义-时设置为15),然后为该对象分配一个值a(是15)加10,然后返回a(已修改,现在是25),最后,由于最后一行代码,输出了out:

print(test(15))


请注意,可以这么说,您实际上所做的并不是纯粹的功能。通常,我们希望函数获得一个输入值(或多个)并返回一个输入值(或多个)。在您的情况下,您的输入值实际上为空,而没有输出值(因为您没有使用return)。此外,您尝试将此输入写到函数的外部(当您说test(a)时未加载值a时调用了它,这给您带来了错误-即在计算机看来,它是“空”的)。

此外,我鼓励您习惯于在函数内编写return,然后在调用它时使用打印指令(就像我在最后的编码行print(test(15))中所写的那样),而不是在函数内部使用它。最好仅在调用该函数并想查看该函数的实际功能时才使用print。

至少,这是他们在基础编程课程中向我展示的方式。这可以证明是合理的:如果您在函数中使用return,则该函数将为您提供一个值,该值以后可在其他函数中使用(即该函数返回您可以使用的东西)。否则,您只会在屏幕上显示带有打印件的数字,但计算机无法进一步使用它。

P.S.您可以这样做:

def test(a):
    a +=10      
    return a

print(test(15))


评论


为什么不简单地做一下:def test(a):返回+ 10?

–boardrider
16年12月30日在22:23

#3 楼

您正在修改在函数a的范围内创建的变量test()。如果要修改外部a,可以执行以下操作:

a = 15

def test():
    global a
    a = a + 1
    print(a)

test()


评论


虽然使用global解决了紧迫的问题,但这是不好的编程习惯,并且您不应该真正将它作为初学者的解决方案来教授,而无需指出这既不好实践又容易避免。尚未真正理解为什么这样做通常是错误的事情的人不应该真正使用global。

–零比雷埃夫斯(Zero Piraeus)
16年12月28日在21:33

您说的没错,我提出我的借口是不表达使用global的错误选择。我稍后会更新我的回答以表达这一点。非常感谢。 @ZeroPiraeus

– d4vsanchez
16 Dec 28 '21:45



#4 楼

除非使用关键字global明确定义,否则变量的作用域是块的局部变量。还有另一种使用globals函数访问函数局部变量的方法

a = 15

def test():
    a = globals()['a']
    a += 10
    print ( a )

test()


上面的示例将打印25,同时保持全局值不变,即15

#5 楼

# All the mumbo jumbo aside, here is an experiment 
# to illustrate why this is something useful 
# in the language of Python:
a = 15    # This could be read-only, should check docs

def test_1():
    b = a + 10    # It is perfectly ok to use 'a'
    print(b)

def test_2():
    a = a + 10    # Refrain from attempting to change 'a'
    print(a)

test_1()    # No error
test_2()    # UnboundLocalError: ...


#6 楼

错误与已被定义无关...
变量仅在所谓的作用域内有效:如果在函数中创建变量,则仅在此函数中定义。

def test():
   x=17
   print(x) # returns 17

test()
print(x) # results in an error.