简体   繁体   English

set和frozenset在实现上的差异

[英]set and frozenset difference in implementation

I checked on this link that set is mutable https://docs.python.org/3/library/stdtypes.html#frozenset while frozenset is immutable and hence hashable. 我检查了这个链接,该集合是可变的https://docs.python.org/3/library/stdtypes.html#frozenset,而frozenset是不可变的,因此可以清除。 So how is the set implemented in python and what is the element look up time? 那么如何在python中实现集合以及元素查找时间是多少? Actually I had a list of tuples [(1,2),(3,4),(2,1)] where each entry in the tuple is a id and I wanted to create a set/frozenset out of the this list. 实际上我有一个元组列表[(1,2),(3,4),(2,1)],其中元组中的每个条目都是一个id,我想从这个列表中创建一个set / frozenset。 In this case the set should contain (1,2,3,4) as elements. 在这种情况下,集合应包含(1,2,3,4)作为元素。 Can I use frozenset to insert elements into it one by one from the list of tuples or I can only use a set? 我可以使用frozenset从元组列表中逐个插入元素,或者我只能使用一组吗?

You can instantiate a frozenset from a generator expression or other iterable. 您可以从生成器表达式或其他可迭代实例化冻结集。 It's not immutable until it's finished being instantiated. 在完成实例化之前,它不是不可变的。

>>> L = [(1,2),(3,4),(2,1)]
>>> from itertools import chain
>>> frozenset(chain.from_iterable(L))
frozenset([1, 2, 3, 4])

Python3.3 also has an optimisation that turns set literals such as {1, 2, 3, 4} into precomputed frozensets when used as the right-hand side of an in operator. Python3.3还有一个优化,当用作in运算符的右侧时,将{1,2,3,4}等集合文字转换为预先计算的frozensets。

Sets and frozensets are implemented the same way, as hashtables. 集合和frozensets以与哈希表相同的方式实现。 (Why else would they require their elements to implement __hash__ ?) In fact, if you look at Objects/setobject.c , they share almost all their code. (为什么他们还需要他们的元素来实现__hash__ ?)事实上,如果你看看Objects/setobject.c ,他们几乎可以共享所有代码。 This means that as long as hash collisions don't get out of hand, lookup and deletion are O(1) and insertion is amortized O(1). 这意味着只要哈希冲突不会失控,查找和删除就是O(1)并且插入是分摊的O(1)。

The usual way to create a frozenset is to initialize it with some other iterable. 创建冻结集的常用方法是使用其他可迭代函数对其进行初始化。 As gnibbler suggested, the best fit here would probably be itertools.chain.from_iterable : 正如gnibbler建议的那样,这里最合适的可能是itertools.chain.from_iterable

>>> L = [(1,2),(3,4),(2,1)]
>>> from itertools import chain
>>> frozenset(chain.from_iterable(L))
frozenset([1, 2, 3, 4])

As for your first question, I haven't actually checked the source, but it seems safe to assume from the fact that sets need to contain objects of hashable types, that it is implemented using a hash table, and that its lookup time is, therefore, O(1). 至于你的第一个问题,我实际上没有检查过源代码,但似乎可以安全地假设集合需要包含可散列类型的对象,它是使用哈希表实现的,并且它的查找时间是,因此,O(1)。

As for your second question, you cannot insert the elements into a frozenset one by one (obviously, since it's immutable), but there's no reason to use a set instead; 至于你的第二个问题,你不能frozenset将元素插入到frozenset (显然,因为它是不可变的),但是没有理由使用集合; just construct it from a list (or other iterable) of the constituent values, eg like this: 只是从组成值的列表(或其他可迭代的)构造它,例如像这样:

data = [(1, 2), (3, 4), (2, 1)]
result = frozenset(reduce(list.__add__, [list(x) for x in data], []))

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

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