我找了很多关于这方面的话题,但我无法理解真正发生的事情。
我有这段代码:
def altera(L1, L2):
for elemento in L2:
L1.append(elemento)
L2 = L2 + [4]
L1[-1] = 10
del L2[0]
return L2[:]
Lista1 = [1,2,3]
Lista2 = [1,2,3]
Lista3 = altera(Lista1, Lista2)
print Lista1
print Lista2
print Lista3
结果是:
[1, 2, 3, 1, 2, 10]
[1, 2, 3]
[2, 3, 4]
我无法理解Lista1
是如何被修改的,Lista2
没有被修改。但是在测试代码之前,我认为Lista1
和Lista2
将保持不变,因为它们是全局变量。
答案 0 :(得分:3)
列表在Python中通过引用传递。 Lista1
已修改,因为您直接致电.append
:
for elemento in L2:
L1.append(elemento)
未修改 Lista2
,因为您未修改列表。您使用了加法运算符L2 = L2 + [4]
,不会修改 L2
。相反,它会创建一个新列表并返回结果。
如果谷歌使用术语“通过引用传递”,你应该能够在Python中找到一些很好的解释性示例。
答案 1 :(得分:0)
执行L1.append(elemento)
时,您正在调用实际更改变量L1
命名的列表的方法。设置L1
和L2
值的所有其他命令实际上只是为新变量创建新名称。
此版本不会改变任何内容:
def altera(L1, L2):
for elemento in L2:
# create a new list and assign name L1
L1 = L1 + [elemento]
# create a new list and assign name L2
L2 = L2 + [4]
return L2
Lista1 = [1,2,3]
Lista2 = [1,2,3]
Lista3 = altera(Lista1, Lista2)
print Lista1
print Lista2
print Lista3
虽然这个:
def altera(L1, L2):
for elemento in L2:
# Call method on L1 that changes it
L1.append(elemento)
# Call method on L2 that changes it
L2.append(4)
# Change object pointed to by name L1 -- Lista1
L1[-1] = 10
# Change object pointed to by name L2 -- Lista2
del L2[0]
return L2[:]
Lista1 = [1,2,3]
Lista2 = [1,2,3]
Lista3 = altera(Lista1, Lista2)
print Lista1
print Lista2
print Lista3
然而,L += [2]
存在一个棘手的问题,与L = L + 2
并不完全相同。增强赋值语句的Python Language Reference部分解释了差异:
像x + = 1这样的增强赋值表达式可以重写为x = x + 1,以实现类似但不完全相同的效果。在增强版本中,x仅评估一次。此外,在可能的情况下,实际操作是就地执行的,这意味着不是创建新对象并将其分配给目标,而是修改旧对象。“
答案 2 :(得分:0)
当您使用L2
语句为名称L2 = L2 + [4]
分配新值时,它不再引用Lista2
。大多数其他语句都会更改它们已引用的对象的值。
答案 3 :(得分:0)
您的功能中发生了两件不同的事情:
def altera(L1, L2):
for elemento in L2:
L1.append(elemento)
# [1] this ^ alters L1 in place
L2 = L2 + [4]
# [2] this ^ creates a new list
L1[-1] = 10
del L2[0]
return L2[:]
要扩展我内联添加的评论:
altera
内,变量L1
是您传入的任何内容(因此 Lista1
)。它不是副本,具有相同内容的新列表 - 它引用相同的实际对象当您指定L2 = L2 + [4]
时,您会做两件事:
L2 + [4]
L2
设置为指向此新列表,而不是您传入的任何内容如果我们重新命名变量,它变得明确,并且完全相同:
L3 = L2 + [4]
del L3[0]
return L3[:]
或者,如果您想要修改原始L2
(即实际修改Lista2
),您可以
L2.append(4)
del L2[0]
return L2[:]
注意最后一行仍然意味着Lista3
将是Lista2
的不同列表对象,但它将具有相同的值。如果你只是return L2
,那么Lista3
将与<{1}} 相同,因此它们将是同一列表对象的两个名称。
如果您想阻止此行为,可以像这样致电L2
:
altera
现在,在Lista3 = altera(Lista1[:], Lista2[:])
内,它将处理自己的参数副本,并且不会影响原始altera
和Lista1
。