可以在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等等......
现在我对这一个问题。我们这里真的有两个列表,还是只有一个?这样的东西如何存储在内存中?什么可以使程序员能够实现像这样奇怪的东西?
请不要把这个问题视为超级严肃。不要忘记,编程有时会很有趣。
答案 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]
表示b
,b[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
),而是进行相等(==
)。这导致尝试比较它们 - 深入内部,导致递归的原因。