无限嵌套列表中究竟发生了什么?

时间:2011-10-06 13:10:48

标签: python list infinite

可以在Python中创建无限的嵌套列表。这很清楚,虽然不受欢迎,但绝对没用,这是一个众所周知的事实。

>>> a = [0]
>>> a[0] = a
>>> a
[[...]]
>>> a[0] == a
True

我的问题是,这里发生了什么:

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

哪种方式更深入,当我试图理解它时,我感觉更像是我的大脑会爆炸。我看,a包含b,包含a等等......

现在我对这一个问题。我们这里真的有两个列表,还是只有一个?这样的东西如何存储在内存中?什么可以使程序员能够实现像这样奇怪的东西?

请不要把这个问题视为超级严肃。不要忘记,编程有时会很有趣。

5 个答案:

答案 0 :(得分:26)

答案 1 :(得分:11)

怀疑发生以下情况:

a[0]==b:Python查找值a[0]并查找对b的某种引用,因此它显示为True

a[0][0]==b:Python查找a[0],找到b,现在查找a[0][0],即(a[0]持有b b[0]b[0]。现在它看到,a拥有对b的某种引用,这与a[0]不完全相同。所以python必须比较元素,这意味着它必须将b[0]a[0]=b进行比较。现在,无限递归开始......

请注意,这只是因为Python在分配b时实际上并未复制列表。 Python而是创建对a[0]中存储的{{1}}的引用。

答案 2 :(得分:10)

a[0]表示bb[0]表示a。这是一个循环参考。正如glglgl所提到的,当你使用==运算符时,它会对值进行比较。

试试这个,这可能会让事情变得更加清晰 -

>>> id(a)
4299818696
>>> id(b)
4299818768
>>> id(a[0])
4299818768
>>> 
>>> id(b[0])
4299818696

答案 3 :(得分:7)

  

我知道,a包含b,其中包含

它们不相互包含 - A是对列表的引用,此列表中的第一件事是对B的引用,反之亦然

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

[0]的数量无关紧要,因为您可以根据需要进行多次列表查找 - 重要的是在示例#1和#3(以及所有奇数查找)中正在说“B等于B”,此时python比较内存地址并发现它们是同一个东西,所以说是的。使用示例#2(以及所有偶数查找),您说“A等于B”,python看到它们是不同的内存地址,然后尝试将整个(无限)数据结构加载到内存中以执行更多操作深度比较。

答案 4 :(得分:4)

这是两个清单。首先,您创建它们:

a = [0]
b = [0]

然后,将每个元素分配给另一个元素的第一个元素:

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

所以你可以说

a[0] is b

b[0] is a

与第一个例子的情况相同,但obe级别更深。

此外,您不会比较身份(is),而是进行相等(==)。这导致尝试比较它们 - 深入内部,导致递归的原因。