为什么这个函数会返回不同的结果?

时间:2016-11-09 15:56:19

标签: python list

有人可以向我解释为什么这个函数会返回不同的结果:

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]

3 个答案:

答案 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]