繁体   English   中英

自引用列表

[英]Self-referencing lists

假设您执行以下操作:

a = [1]
a[0] = a

你最终得到a等于[[...]] 这里发生了什么? 请问这个隐含定义的无限链a的指a的结束为[[...]]

你什么都没有看到:

>>> a = []
>>> a[:] = [a] * 4
>>> a
[[...], [...], [...], [...]]

如果您对CPython中的工作方式感兴趣,请参阅list_repr中的listobject.c和类似函数。 基本上,任何可能打印自引用对象的函数在打印之前调用Py_ReprEnter上的Py_ReprLeave ,并在完成时调用Py_ReprEnter (有关这些函数的定义,请参阅object.c 。)前者检查对象是否在当前正在打印的对象的线程局部堆栈中找到(如果没有,则推送它); 后者从堆栈中弹出对象。 因此,如果Python正在打印列表并发现列表在堆栈上,那必须意味着这是一个自引用列表,并且列表应该缩写,以避免无限循环:

 i = Py_ReprEnter((PyObject*)v);
 if (i != 0) {
     return i > 0 ? PyString_FromString("[...]") : NULL;
 }

 // ...

 Py_ReprLeave((PyObject *)v);
 return result;

该列表包含对自身的引用。 [[...]]是打印列表时的呈现方式。

实现方式不再确保它不会以无限递归结束。 它通过渲染对已经打印为[...]对象的引用来实现这一点。

这使得它也适用于间接自引用:

>>> a = []
>>> b = [a]
>>> a.append(b)
>>> a
[[[...]]]
>>> b
[[[...]]]

如果你真的很好奇,你可以学习CPython的源代码。 在Python 2.7.3中,相关代码位于Objects/listobject.c

我们在这里有a == [a] ,所以理论上a应该打印成一个包含一个元素的列表,它是a ---也就是一个包含一个元素的列表,它本身就是一个包含一个元素的列表,依此类推。 或者在印刷品中:无数个[ ,后跟无数个] 我们得到[[...]]的事实只是Python试图提供帮助而不是实际打印无限数量的[

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM