描述列表如何工作的这个属性是什么术语?

时间:2012-03-20 15:02:22

标签: python list terminology definition

我正在寻找适当的术语来描述这个集合对象的众所周知的属性,更重要的是,当变量用于引用它们的元素时,堆栈图的变化方式:

>>> x = 5
>>> l = [x]
>>> x += 1
>>> l
[5]
>>> x
6

列表对变量x执行的操作的名称是什么,以防止它绑定到x原始值的任何更改?屏蔽?共享结构?列表绑定?使用这些条款从谷歌搜索中找不到任何东西。

这是一个更详细的例子(但不幸的是没有定义)。

an example of list structure sharing

信用ocw.mit.edu

5 个答案:

答案 0 :(得分:5)

  

列表对变量x执行的操作的名称是什么,以防止它绑定到x的原始值的任何更改?屏蔽?共享结构?列表绑定?使用这些条款从谷歌搜索中找不到任何东西。

因为列表不是做任何事情,并且它不是集合的属性。

在Python中,变量是名称。

>>> x = 5

这意味着:x应为值5的名称。

>>> l = [x]

这意味着:l应该是获取x名称(5)的值,并使用该值创建一个元素列表所产生的值的名称( [5])。

>>> x += 1

x += 1在这里被重写为x = x + 1,因为整数是不可变的。您不能使值5增加1,因为它将再次为5

因此,这意味着:x将不再是其当前名称的名称,并开始成为数学表达式x + 1产生的值的名称。即,6

这就是参考语义的发生方式。没有理由期望列表的内容发生变化。


现在,让我们看看价值语义会发生什么,用一种假设的语言看起来就像Python,但处理变量的方式与在C中处理它们的方式相同。

>>> x = 5

现在这意味着:x是一块内存的标签,其中包含数字5的表示。

>>> l = [x]

现在这意味着:l是一块内存的标签,它包含一些列表结构(可能包括一些指针等),它们将以某种方式初始化,以便它代表一个包含1个元素的列表,具有值5(从x变量复制)。它不能在逻辑上包含x,因为它是一个单独的变量,我们有值语义;所以我们存储了一份副本。

>>> x += 1

现在这意味着:增加x变量中的数字;现在是6。该列表再次不受影响。

无论您的语义如何,都不能以这种方式影响列表内容。期望更改列表内容意味着您的解释不一致。 (如果将代码重写为l = [5]; x = l[0]; x += 1,这将变得更加明显。)

答案 1 :(得分:4)

我称之为所包含对象的“不变性”。

我认为你将你的情况与下面的情况进行比较:

x = []
l = [x]
x += [1]
print l # --> [[1]]

区别在于:

在这种情况下(可变的情况),你会改变列表x中包含的原始对象l

但是,在您的情况下,您x指向一个不可变对象(5),然后将其添加到列表中。之后,此引用将替换为6,但仅适用于x,而不是列表。

所以x += <something>要么修改x,要么用另一个对象替换它,具体取决于对象类型的性质。


编辑:它也与列表的性质无关。您可以使用2个变量实现相同的目标:

x = 5
y = x
print x, y, x is y
x += 1
print x, y, x is y

VS

x = []
y = x
print x, y, x is y
x += [1]
print x, y, x is y

由于x的不变性导致int变为x is y,导致x is y变为假,而第二个变为xy仍为真,因为对象(列表)发生了变异,{{1}}和{{1}}引用的对象的标识保持不变。

答案 2 :(得分:1)

list在您的示例中对x所做的唯一事情就是阅读它;它以其他方式与变量交互。事实上,由表达式[x]生成的列表根本不会与变量x进行交互。

如果你不得不为它引入一条行话,那就是价值捕获,或者只是独立

我认为没有一个特殊术语的原因是它是(a)不是需要太多讨论的东西(b)是严格按值语义的一个方面,其中变量总是包含引用。那些类型的语义现在几乎是常态(除非通过引用实际命名包含对象的内存的变量)。我认为OP期待着名字或懒惰的语义。

答案 3 :(得分:1)

您所描述的行为与引用有关。如果你熟悉c,你可能也熟悉“指针”。 c中的指针可以使真正复杂化,而Python使用的数据模型可以极大地简化事情。但是在c中有一些背景知识有助于理解Python在这里的行为,这与c指针的行为密切相关。因此,“指针”,“引用”和“取消引用”都是与您所谈论的内容相关的所有术语,尽管它们都不是它的“名称”。也许最好的名字是“间接” - 虽然这有点过于抽象和包容;这是一种非常特殊的间接方式。也许“参考语义”?这是来自GvR自己使用该术语的演讲中的slide,而google search会出现一些有用的点击。

但如果你在c中没有任何背景,这是我最好的解释。简而言之,您可以将Python名称视为指向对象的指针。因此,当您为某个值指定名称时,您将该名称“指向”该值。然后,当您为名称指定新值时,将其指向新值;但是旧的价值根本没有改变。在将名称视为指针时,这似乎很自然; “名称的值”被更改,但“值的值”不是。

有点令人困惑的是+=行为不一致。当你对一个数字使用+=时,使用上面的比喻结果很有意义:

x = 5
y = x
x += 1
print x, y 
# 6 5

行为与x = x + 1时的行为完全相同。

但有时+=会以就地突变的方式过载。这是一个务实的,但略有不一致的习语:

x = [5]
y = x
x += [6]
print x, y
# [5, 6] [5, 6]

所以在这里,“值”的值被改变了。这实际上不是我最喜欢的Python,但它有很好的理由。

答案 4 :(得分:0)

您实际在做的是构建一个列表,其中一个元素引用x相同的对象。然后将新值绑定到x,同时列表仍引用旧元素。这是因为+=引用返回给新对象(6)并保留旧5对象。 Python中的整数是 immutable