用什么术语来描述列表工作的这种特性?

2024-06-16 13:22:25 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

列表对变量x所做的操作的名称是什么,以防止它绑定到x的原始值的任何更改?屏蔽?共享结构?列表绑定?谷歌不会再使用这些搜索词了。在

下面是一个更详细的例子(不幸的是,没有一个定义)。在

{1美元^

贷记ocw.mit.edu


Tags: 对象名称元素列表属性定义堆栈mit
3条回答

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

我想你可以把你的情况和下面的情况比较一下:

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

区别在于:

在这种情况下(可变的情况),您可以对列表l中包含的原始对象x进行变异。在

但是,在您的情况下,x指向一个不可变的对象(5),然后将其添加到列表中。{{cd5>之后不仅仅是对这个列表的引用。在

因此x += <something>要么修改x,要么根据对象类型的性质用另一个对象替换它。在


编辑:这也与列表的性质无关。你可以用两个变量实现同样的效果:

^{pr2}$

对比

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

由于int的不变性,第一个将改变x,导致x is y为false;而在第二个示例中,x is y保持为真,因为对象(列表)发生了变化,x和{}引用的对象的标识保持不变。在

What is the name of what the list is doing to the variable x to prevent it from being bound to any changes to the original value of x? Shielding? Shared structure? List binding? Nothing is coming back from a Google search using those terms.

因为list没有做任何事情,也不是集合的属性。在

在Python中,变量是名称。在

>>> x = 5

这意味着:x应该是值5的名称。在

^{pr2}$

这意味着:l应该是由x命名的值(5)并使用该值([5])生成的一个元素列表所产生的值的名称。在

>>> x += 1

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

因此,这意味着:x将不再是它当前名称的名称,而是开始成为数学表达式x + 1产生的值的名称。一、 例如,6。在

引用语义就是这样发生的。没有理由期望清单的内容会发生变化。在


现在,让我们来看看值语义会发生什么,在一种类似Python的假设语言中,变量的处理方式与在C中处理变量的方式相同

>>> x = 5

这意味着:x是内存块的一个标签,它包含一个数字5的表示形式。在

^{pr2}$

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

>>> x += 1

这意味着:增加x变量中的数字;现在它是6。同样,这个列表是不受影响的。在

不管您的语义如何,您都不能这样影响列表内容。期望列表内容发生变化意味着您的解释不一致。(如果您将代码重写为l = [5]; x = l[0]; x += 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完全相同。在

但有时{}以一种发生原位突变的方式过载。一个稍微不一致的成语:

^{pr2}$

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

相关问题 更多 >