无限嵌套列表中到底发生了什么?

无限嵌套列表中到底发生了什么?,第1张

无限嵌套列表中到底发生了什么?

免责声明:我不使用Python,所以我说的某些话可能是错误的。Python专家,随时纠正我。

好问题。我认为中心的误解 (如果我什至不能这样称呼;您到达所用思维过程的方式是完全合理的) ,这会提示您提出以下问题:

当我写的

b[0] = a
,这并不意味着
a
b
。这意味着其中
b
包含指向所指事物的参考
a

变量

a
b
它们本身甚至都不是“事物”,它们本身也只是指向内存中其他匿名“事物”的指针。

引用的概念是从非编程世界的一大飞跃,因此,请牢记这一点,逐步完成程序:

>>> a = [0]

您创建一个列表,其中恰好有东西(暂时忽略该列表)。重要的是列表。该列表将存储在内存中。假设它存储在内存位置1001中。然后,赋值

=
创建一个变量
a
,编程语言允许您稍后使用该变量。此时,内存中存在一些列表对象,并可以使用name对其进行引用
a

>>> b = [0]

这样做与相同

b
。有一个新列表存储在内存位置1002中。编程语言创建了一个引用
b
,您可以使用该引用来引用内存位置,进而引用该列表对象。

>>> a[0], b[0] = b, a

这样做有两件事是完全相同的,所以让我们专注于一个:

a[0] =b
。这确实很花哨。
b
由于
b
它是对它的引用,因此它首先计算等式的右侧,查看变量并获取内存中的相应对象(内存对象#1002)。同样,在左侧发生的事情也很奇特。
a
是指向列表(内存对象#1001)的变量,但是内存对象#1001本身具有许多引用。这些引用具有数字索引,而不是您使用的那些引用,例如,
a
和。所以,现在,这是
b``0``a
拉起一堆索引引用的内存对象#1001,然后转到索引为0的引用(以前,此引用指向实际编号
0
,这是您在第1行所做的 *** 作),然后重新指向该引用(也就是说,在存储对象#1001中,第一个也是唯一的参考是等式右边的东西求值。因此,现在,对象#1001的第0个引用指向对象#1002。

>>> a[[[...]]]>>> b[[[...]]]

这只是编程语言的幻想。当您只是要求它评估时

a
,它会拉出内存对象(位置#1001的列表),使用自身的魔术来检测它是无限的,并如此渲染自身。

>>> a == bTraceback (most recent call last):  File "<stdin>", line 1, in <module>RuntimeError: maximum recursion depth exceeded in cmp
该语句的失败与Python如何进行比较有关。当您将一个对象与其自身进行比较时,它会立即求值为true。当您比较并反对另一个对象时,它使用“魔术”来确定相等性是对还是错。对于Python中的列表,它将查看每个列表中的每个项目并检查它们是否相等(依次使用项目自己的相等性检查方法)。所以,当你尝试`a

b

。它的工作是首先挖掘b(对象#1002)和a(对象#1001),然后意识到它们在内存中是不同的,因此转到其递归列表检查器。它通过遍历两个列表来做到这一点。对象#1001具有一个索引为0的元素,该元素指向对象#1002。对象#1002具有一个索引为0的元素,该元素指向对象#1001。因此,程序得出以下结论:如果对象#1001和#1002的所有引用都指向同一事物,则它们相等;如果#1002(#1001的唯一引用指向)和#1001(#1002的唯一引用指向),则认为是错误。同样的事情。这种平等检查永远不会停止。在任何不停止的列表中都会发生同样的事情。您可以这样做,
c
= [0]; d = [0]; c[0] = d; d[0] = c
并且
a == c`会引发相同的错误。

>>> a[0] == bTrue

正如我在上一段中所暗示的那样,由于Python采用了快捷方式,因此这立即变为true。它不需要比较列表内容,因为

a[0]
指向对象#1002和
b
对象#1002。Python检测到它们在字面意义上是相同的(它们是相同的“事物”),甚至不用费心检查内容。

>>> a[0][0] == bTraceback (most recent call last):  File "<stdin>", line 1, in <module>RuntimeError: maximum recursion depth exceeded in cmp

这回到错误状态,因为

a[0][0]
最终指向对象#1001。身份检查失败,然后退回递归内容检查,该检查永远不会结束。

>>> a[0][0][0] == bTrue

再次

a[0][0][0]
指向对象#1002
b
。跳过递归检查,比较立即返回true。


与您的特定代码段不直接相关的高级jibber jabber:

  • 由于所有引用都指向其他对象,因此即使存在“无限”嵌套,由
    a
    (如我称为对象#1001)所引用的对象和由
    b
    (#1002)所引用的对象也是两者在内存中的大小相同。实际上,该大小非常小,因为它们都是指向各个其他内存位置的列表。
  • 还需要注意的是,在“通用”语言较少的情况下, 仅* 当两个引用指向的内存对象相同 时才 将两个引用与
    ==
    返回值进行比较,即两个引用都指向内存中的同一位置。Java就是一个例子。此类语言中出现的风格惯例是在对象本身上定义方法/功能(对于Java,通常称为)以进行自定义相等性测试。Python为列表开箱即用。我不知道Python的特别,但至少在Ruby中,在这个意义上,当你做的是超载,它实际上调用了一个名为方法上(也可以覆盖)。从理论上讲,没有什么可以阻止您
    true
    *
    equals()``==``someobject == otherobject``==``someobject``someobject == otherobject
    返回布尔值以外的其他值。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5647288.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存