Python global list modification inside and outside of functions
2我对Python相对较新(使用3.3.3),并且有一个与列表有关的问题。在函数内部修改全局列表变量时(请不要讲授关于全局变量的弊端),通常不需要使用函数内部的global关键字声明列表-只要您坚持使用列表方法即可。特别是,您可能必须先使用global关键字才能使用增强加法。令我惊讶的是,在函数外部使用加法运算显然并没有修改list变量(仅列表内容),因此我希望可以在不使用global关键字的情况下在函数内部使用它。这是我无法调和的两个示例:
1 2 3 4 5 6 7 8
| list_1 = []
def my_func():
list_1.append(0)
#list_1 += [0]
my_func()
print('list_1 =', list_1) |
正如预期的那样,这将打印list_1 = [0],而注释掉的增强加法运算会产生有关在分配之前使用局部变量的投诉。
这是一个我无法与前一个示例保持一致的示例:
1 2 3 4
| list_1 = [0]
list_2 = list_1
list_1 += [1]
print('list_2 =', list_2) |
这会打印list_2 = [0, 1],这向我暗示list_1 += [1]并未修改list_1变量。我知道list_1 = list[1] + [1]符合修改list_1的资格,但是增强添加似乎没有。为什么在函数内部的加法运算要求使用全局关键字?感谢您的帮助,以帮助您理解这一点。
-
您是否尝试打印出list_1来检查您的假设,即list_1 += [1]没有修改list_1?
-
您说:"这打印出list_2 = [0, 1],这向我提示list_1 += [1]并未修改list_1变量。" 为什么这样向您暗示?
-
@BrenBarn我相信Jon的意思是list_1 += [1]不会导致list_1指向其他列表,而list_1 = list_1 + [1]创建一个新列表,并且list_1指向该新列表。
-
@ Rob Watts是的,这就是我的意思。
-
Python中UnboundLocalError的可能重复项
问题在于,当解析函数主体时,所有在常规分配或扩充分配中使用的变量都被视为局部变量,因此在调用函数时,Python将不会在全局范围内查找这些变量,因此会引发错误。 因此,您需要将这些变量指定为global,以告诉Python在全局范围内查找它们。
另一种选择是使用list.extend()代替+=。
有关:
-
当变量具有值时,为什么会得到UnboundLocalError?
-
Python列表+=可迭代的行为是否记录在任何地方?
-
我要说的是可读性和一致性。如果list_1是一个int,则+=将重新分配,因此必须使用global是有意义的。有道理+=将对所有类型的全局性产生相同的影响
-
仅供参考,OP询问了有关Python 3.x的信息,但您的第一个链接是Python 2.x文档。
-
@ njzk2如果我正确理解了您的观点,那么对于不可变类型而言,使用+=还是普通的=都没有关系,因为无论如何它只会更新单个变量,而所有其他引用都不会受到影响。因此,+=将根据对象类型产生不同的影响。
-
@RobWatts更新了链接,除了nonlocal部分基本相同。
-
@A?wini?haudhary:是的。如果您查看a = 3; id(a); a += 1; id(a)与lst = []; id(lst); lst += [0]; id(lst),您会看到+=重新分配了不可变类型(显然是),但没有重新分配列表。
-
(所有这些都是因为对于未定义__iadd__的类,__iadd__依赖于__add__)
-
@A?wini?haudhary听起来很合理。那么,识别调用方法的对象有不同的处理方式吗?意思是,当在my_func()中解析list_1.append(0)时,list_1不被视为局部变量吗?造成这种差异的原因是什么? (extend()方法看起来很有帮助!)
-
@Jon是的,其他类似获取对象值的操作都遵循LEGB规则。原因之一可能是优化,对本地人的值查找非常快。
-
@Jon Id建议您阅读Python和Python内部知识的理解UnboundLocalError:符号表,第1部分。
-
@A?wini?haudhary当我阅读上面的UnboundLocalError链接时,无法识别说明,但我能够理解您刚刚发布的UnboundLocalError链接。我的简单理解是,由于list_1.append(0)仅涉及名称解析,而不涉及赋值或绑定,因此list_1由最近的封闭范围来解析。一个有趣的区别,它也解释了为什么我可以在函数中使用局部变量,前提是我不尝试修改它们。谢谢!
-
我刚刚在上次回复中注意到一个错字-" ...为什么可以使用局部变量..."应该是" ...为什么可以使用全局变量..."。