Python 自引用列表
假设您执行以下操作:Python 自引用列表,python,Python,假设您执行以下操作: a = [1] a[0] = a 最后的a等于[…]。这是怎么回事?这个隐式定义的无限链a引用a,最终如何成为[…]?该列表包含对自身的引用。[[…]]是打印列表时呈现的方式 实现会不遗余力地确保它不会以无限递归结束。它通过呈现对已打印为[…]的对象的引用来实现这一点 这使得它也适用于间接自引用: >>> a = [] >>> b = [a] >>> a.append(b) >>> a [[[...]
a = [1]
a[0] = a
最后的
a
等于[…]
。这是怎么回事?这个隐式定义的无限链a
引用a
,最终如何成为[…]
?该列表包含对自身的引用。[[…]]
是打印列表时呈现的方式
实现会不遗余力地确保它不会以无限递归结束。它通过呈现对已打印为[…]
的对象的引用来实现这一点
这使得它也适用于间接自引用:
>>> a = []
>>> b = [a]
>>> a.append(b)
>>> a
[[[...]]]
>>> b
[[[...]]]
如果你真的很好奇,你可以研究CPython的源代码。在Python 2.7.3中,相关的代码位于
Objects/listobject.c
我们这里有a==[a]
,因此理论上a
应该打印为包含一个元素的列表,即a
——即它本身是一个包含一个元素的列表,它本身就是一个包含一个元素的列表,依此类推。或打印:无限数量的[
,后跟无限数量的]
。事实上,我们得到的是[[…]]
只是Python试图提供帮助,而不是实际打印无限数量的[
您什么也看不到:
>>> a = []
>>> a[:] = [a] * 4
>>> a
[[...], [...], [...], [...]]
如果您对CPython中的工作方式感兴趣,请参阅和类似的函数。基本上,任何可能打印自引用对象的函数在打印对象之前调用对象上的Py_ReprEnter
,打印完成后调用对象上的Py_ReprEnter
。(请参阅。)前者检查对象是否在当前正在打印的对象的线程本地堆栈中找到(如果没有,则推送);后者从堆栈中弹出对象。因此,如果Python正在打印列表并发现该列表位于堆栈上,这一定意味着这是一个自引用列表,并且该列表应缩写,以避免无限循环:
i = Py_ReprEnter((PyObject*)v);
if (i != 0) {
return i > 0 ? PyString_FromString("[...]") : NULL;
}
// ...
Py_ReprLeave((PyObject *)v);
return result;
这是怎么隐含的?你完全知道自己在做什么是Python将自引用表示为字符串的方式。请看,只是想突出显示OP的某些内容,它不是无限递归,因为它只是一个引用,实际上并不试图传递自身value@jamylak:对。我的意思是,一个试图盲目遍历
a
的方法将以无限递归结束。哦,我可能我应该在这个问题上留下这样的评论,我不是在引用你的答案