列表中是否使用自引用列表或循环引用,例如将列表附加到其自身

问题描述 投票:-1回答:2

因此,如果我有一个列表a并附加a,我将得到一个包含它自己的引用的列表。

>>> a = [1,2]
>>> a.append(a)
>>> a
[1, 2, [...]]
>>> a[-1][-1][-1]
[1, 2, [...]]

这基本上导致看似无限的递归。

不仅在列表中,而且在字典中:

>>> b = {'a':1,'b':2}
>>> b['c'] = b
>>> b
{'a': 1, 'b': 2, 'c': {...}}

这可能是将列表存储在最后一个元素中并修改其他元素的一种好方法,但是那样行不通,因为在每个递归引用中都会看到更改。

我知道为什么会这样,即由于它们的可变性。但是,我对这种行为的实际用例感兴趣。有人可以启发我吗?

python list dictionary circular-reference mutability
2个回答
0
投票

但是,我对这种行为的实际用例感兴趣。有人可以启发我吗?

我不认为有很多有用的用例。允许这样做的原因可能是因为禁止它会使这些容器的性能变差或增加其内存使用率。

Python是动态类型的,您可以将任何Python对象添加到list。这意味着您需要采取特殊的预防措施,以禁止向自己添加列表。这与(大多数)键入语言不同,后者由于键入系统而无法发生这种情况。

因此,为了禁止这种递归数据结构,如果新添加的对象已经参与了数据结构的更高层,则要么需要检查每个添加/插入/变异。这意味着在最坏的情况下,它必须检查新添加的元素是否为anywhere,在其中它可以参与递归数据结构。这里的问题是,同一列表可以在多个位置引用,并且可以已经是多个数据结构的一部分,并且诸如list / dict之类的数据结构可以(几乎)任意深度。这种检测要么很慢(例如线性搜索),要么会占用大量内存(查找)。因此,简单地允许它会更便宜。

Python在打印时检测到此错误的原因是,您不希望解释器进入无限循环,或者得到RecursionError或StackOverflow。这就是为什么对于某些操作(如打印(但也包括深拷贝)),Python会临时创建一个查找以检测这些递归数据结构并适当地对其进行处理。]


0
投票

考虑构建一个状态机来解析数字字符串,您可以将每个节点建模为具有10个传出方向的列表,并考虑将一些连接本身传递给他们

© www.soinside.com 2019 - 2024. All rights reserved.