为什么在地球上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]
"""
如果我对具有相同名称的变量进行分配,则该行之前的操作会变为错误,而不是添加的行(字节代码编译器会发现它,我猜)。
答案 0 :(得分:5)
您没有分配给全局变量,而是在其上调用一个更改其内容的方法。这是允许的。
如果没有global
关键字,您无法做到这一点:
def add(n):
#global numbers
numbers = numbers + [n]
结果:
Traceback (most recent call last): File "C:\Users\Mark\Desktop\stackoverflow\python\test.py", line 8, in add(i) File "C:\Users\Mark\Desktop\stackoverflow\python\test.py", line 5, in add numbers = numbers + [n] UnboundLocalError: local variable 'numbers' referenced before assignment
不同之处在于,我不是在改变现有列表 - 我正在尝试创建一个新列表并重新分配回全局范围。但如果没有global
关键字,就无法做到这一点。
关于您的更新:
以下行是正常的,因为它在函数范围内创建了一个新的本地名称num
。这不会影响全局范围内变量的值。
num = thisnum
答案 1 :(得分:1)
global x
仅感情x = ...
(即,它会重新分配全局x
,而不是创建独立的本地x
) 。它不会影响x.member = ...
(因为这是一个方法调用)或x.mutating_method(...)
,因为Python(这个不是静态与动态的问题,顺便说一句)不能知道(并且不关心)这些方法以某种方式修改self
- 所以你必须防止对全局变量(全局变量所指向的对象)的方法调用......这当然是没有意义的。
关于更新:
执行num = thisnum
时,您正在执行与numbers.append(n)
完全不同的操作 - 您正在创建一个局部变量(因为您没有声明global num
)并为其分配了一些值。这甚至从未触及全球num
。
答案 2 :(得分:0)
因为您只是将附加到列表中。
访问和分配是不同的概念。附加列表时,您只是调用一个更改其值的方法。假设你做了+=
,那将是分配。
如果你这样做:
>>> numbers = []
>>> def add(n):
numbers += n
>>> n = [1, 2]
>>> add(n)
它会失败,因为这是作业。
要解决此问题,请在add()
函数中添加:
>>> def add(n):
global numbers
numbers += n