有人可以向我解释为什么这个函数会返回不同的结果:
def g(x, z):
x.append(z)
return x
y = [1, 2, 3]
g(y, 4).extend(g(y[:], 4))
y = [1, 2, 3]
g(y[:], 4).extend(g(y, 4))
第一个返回
[1, 2, 3, 4, 1, 2, 3, 4, 4]
和第二个
[1, 2, 3, 4]
答案 0 :(得分:1)
在这两种情况下,都会返回None
,因为list.extend()
会扩展列表就地。所以你必须看看y
最终会是什么。那就是摩擦的地方;你没有在第二个例子中扩展y
。
在第一个示例中,您基本上是这样做的:
y.append(4) # y = [1, 2, 3, 4]
temp_copy = y[:] # temp_copy = [1, 2, 3, 4]
temp_copy.append(4) # temp_copy = [1, 2, 3, 4, 4]
y.extend(temp_copy) # y = [1, 2, 3, 4, 1, 2, 3, 4, 4]
del temp_copy
print(y)
永远不会真正创建temp_copy
名称;该列表仅在堆栈中可用,并在x
内简单地显示为g()
,这就是为什么我在最后再次删除temp_copy
以清除此内容。
首先附加y
,然后使用另一个列表进行扩展(恰好是y
的副本,并添加了另一个元素)。
在你的第二个例子中,你改为:
temp_copy = y[:] # temp_copy = [1, 2, 3]
temp_copy.append(4) # temp_copy = [1, 2, 3, 4]
y.append(4) # y = [1, 2, 3, 4]
temp_copy.extend(y) # temp_copy = [1, 2, 3, 4, 1, 2, 3, 4]
del temp_copy
print(y)
您将一个元素附加到y
,并且所有其他操作都适用于副本。该副本再次被丢弃,因为在您的代码中没有对它的引用。
答案 1 :(得分:0)
你在那里搞了一些任务和副本。请注意:
append()
就地修改列表,而不创建新列表extend()
y[:]
会创建新列表您的表达式返回None
。您只对列表进行修改,不保存对新列表的引用。
让我“展开”您的代码,以显示差异:
# First snippet:
y = [1, 2, 3]
y.append(4)
y_copy = list(y)
y_copy.append(4)
y.extend(y_copy)
# Second snippet:
y = [1, 2, 3]
y_copy = list(y)
y_copy.append(4)
y.append(4)
y_copy.extend(y)
如您所见,在第二个示例中,您对副本应用了大多数修改,而不是原始修改。首先,所有更改都将转换为原始版本。
从主观上讲,这段代码很难理解。你是自己编写的,无法遵循它,我有多年的Python经验,仍然需要拉动“展开”技巧。尽量保持代码更简单,以便可以跟踪和推理对象。
答案 2 :(得分:-1)
在第一个电话中,您通过引用传递列表,在第二个电话上,您制作了列表的副本(将其列入子列表)。 解释:
>>> one = [1,2,3]
>>> ref = one
>>> copy = one[:]
>>> one
[3, 2, 3]
>>> ref
[3, 2, 3]
>>> copy
[1, 2, 3]