元组,列表和字典如何存储在python的后端? 为什么我们不能在分配后改变元组?它在后台如何工作?
答案 0 :(得分:5)
对于每个Python实现,它们如何存储在后端中是不同的。
但是它们的存储方式几乎与你为什么不能改变元组无关。你不能改变元组,因为它们被设计成不可变的。他们没有实施__setitem__
方法或append
方法。在ABC术语中(几乎总是您真正关心的,而不是底层实现),它们只实现Sequence
,而不是MutableSequence
。在大多数实现中,它们与列表没有太大区别,只是它们可能不知道如何扩展;差异实际上只是变异方法没有实现。
在CPython中:
元组和列表是一个小标题和指向PyObject
的连续指针数组的指针。如果你已经填充数组时附加到列表,它会分配一个新的,更大的数组,复制现有指针,然后删除旧指针。
字典是一个小标题加上一个指向散列表的指针,*其中每个存储桶是一个散列值,一个键和一个值(键和值是指向PyObject
的指针)。
详细信息在Concrete Objects Layer中记录为C API的一部分。源代码位于Objects目录中。 (请注意,在C API级别,您实际上可以调用PyTuple_SetItem
,甚至_PyTuple_Resize
,但如果任何Python代码可能能够看到元组,则强烈建议不要这样做。)< / p>
*实际上,在最新版本中,哈希表可以分为两部分,这样多个字典可以共享相同的密钥。有关如何运作的详细信息,请参阅PEP 412和dictobject.c
中的评论。
在PyPy中,Python list,tuple和dict对象实际上是在RPython(Python的一个子集)中实现的,它通过通常的PyPy魔法转换为C.元组和列表几乎是你所期望的,但是dict有一些值得阅读的聪明技巧。*
*它基本上采用了相同的“分裂表”思想 - 或者更准确地说,CPython借用了PyPy的分裂表思路,并没有把它当作远。
在Jython和IronPython中,它们分别用Java和C#实现。 IIRC,Jython的早期版本直接使用Python类型的Java集合类型,但它们很久以前停止了,代码更类似于CPython(仅在Java数组之上而不是C指针到a- { {1}} - 区域)。在2.5-2.7天内,实现与CPython非常相似。我认为IronPython很相似,但我没看过。
在我所知道的两个部分Python-in-JavaScript实现中,所有三种类型都是在JS malloc
之上实现的,但它们必须使用{{1}的键来做一些丑陋的事情。 }。