我想知道为什么这不能按预期工作的细节:
def outer():
mylist = []
def inner():
mylist += [1]
inner()
outer()
Run Code Online (Sandbox Code Playgroud)
特别是因为mylist.__iadd__([1])工作正常.
问题是,当您在函数内部分配变量名时,Python假定您正在尝试创建一个新的局部变量,该变量将掩盖外部作用域中类似命名的变量.由于+=必须获得mylist之前可以修改它的值,它会抱怨,因为mylist尚未定义本地版本.MRAB的答案给出了语义的清晰解释.
另一方面,当您这样做时mylist.__iadd__([1]),您没有在函数内部分配新的变量名称.您只是使用内置方法来修改已分配的变量名称.只要您不尝试为其分配新值mylist,就不会有问题.出于同样的原因,该行mylist[0] = 5也将工作中inner,如果定义mylist在outer了mylist = [1].
但请注意,如果您尝试将新值分配给mylist函数中的任何位置,mylist.__iadd__([1])则确实会失败:
>>> outer()
>>> def outer():
... mylist = []
... def inner():
... mylist.__iadd__([1])
... mylist = []
... inner()
...
>>> outer()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in outer
File "<stdin>", line 4, in inner
UnboundLocalError: local variable 'mylist' referenced before assignment
Run Code Online (Sandbox Code Playgroud)
如果要为包含范围的变量分配新值,则可以使用3.0+ nonlocal,就像用于global为全局范围内的变量分配新值一样.所以不是这样的:
>>> mylist = []
>>> def inner():
... global mylist
... mylist += [1]
...
>>> inner()
>>> mylist
[1]
Run Code Online (Sandbox Code Playgroud)
你做这个:
def outer():
mylist = []
def inner():
nonlocal mylist
mylist += [1]
inner()
print(mylist)
outer()
Run Code Online (Sandbox Code Playgroud)
如果在函数中绑定了一个名称(已赋值变量),则该名称将被视为local,除非它被声明为global.
因此inner,mylist是本地的.
当你写x += y,在运行时Python将尝试:
x = x.__iadd__(y)
Run Code Online (Sandbox Code Playgroud)
如果失败,Python会尝试:
x = x.__add__(y)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1377 次 |
| 最近记录: |