1

为什么 Python 不允许在函数中更改全局声明列表?

重新更新

numbers = []
num = 4

def add(n, thisnum=None):
    # changing global list without global declaration!
    numbers.append(n)
    if thisnum:
         num = thisnum
         print 'num assigned', thisnum
    ##numbers = ('one', 'two', 'three')
    ## adding this line makes error:
"""Traceback (most recent call last):
  File "J:\test\glob_vals.py", line 13, in <module>
    add(i)
  File "J:\test\glob_vals.py", line 6, in add
    numbers.append(n)
UnboundLocalError: local variable 'numbers' referenced before assignment
"""

for i in (1,2,3,564,234,23):
    add(i)

print numbers
add(10, thisnum= 19)
# no error
print num
# let the fun begin
num = [4]
add(10, num)
print num

# prints:
"""[1, 2, 3, 56, 234, 23]
num assigned 19
4
num assigned [4]
[4]

"""

如果我将分配给具有相同名称的变量,则该行之前的操作将变为错误,而不是添加的行(我猜是字节码编译器发现了它)。

4

3 回答 3

5

您没有分配给全局变量,而是在其上调用一个更改其内容的方法。这是允许的。

global没有关键字你不能做的是:

def add(n):
    #global numbers
    numbers = numbers + [n]

结果:

回溯(最近一次通话最后):
  文件“C:\Users\Mark\Desktop\stackoverflow\python\test.py”,第 8 行,在
    添加(一)
  文件“C:\Users\Mark\Desktop\stackoverflow\python\test.py”,第 5 行,添加
    数字 = 数字 + [n]
UnboundLocalError:分配前引用的局部变量“数字”

不同之处在于,在这里我没有改变现有列表 - 我正在尝试创建一个新列表并重新分配回全局范围。global但如果没有关键字,这将无法完成。


关于您的更新:

以下行是可以的,因为它num在函数范围内创建了一个新的本地名称。这不会影响全局范围内的变量值。

num = thisnum
于 2010-12-11T17:11:20.067 回答
1

global x 影响x = ...(即,它使 this 重新分配 globalx而不是创建独立的 local x)。它不影响x.member = ...(因为这是一个方法调用)或者x.mutating_method(...),因为 Python(不是静态与动态的问题,顺便说一句)不能知道(也不关心)这些方法self以某种方式修改 - 所以您必须防止对全局变量(指向的对象)进行方法调用……这当然是没有意义的。

关于更新:当你这样做时num = thisnum,你正在做一些完全不同的事情numbers.append(n)- 你正在创建一个局部变量(因为你没有声明global num)并为其分配一些值。这甚至从未触及全球num

于 2010-12-11T17:15:41.337 回答
0

因为您只是附加到列表中。

访问和分配是不同的概念。当您附加一个列表时,您只是在调用一个更改其值的方法。假设您这样做了+=,那将是分配。

如果你要这样做:

>>> numbers = []
>>> def add(n):
      numbers += n

>>> n = [1, 2]
>>> add(n)

它会失败,因为这是分配。

要解决此问题,请在add()函数中添加:

>>> def add(n):
        global numbers
        numbers += n
于 2010-12-11T17:11:24.563 回答