Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python set和frozenset在实现中的差异_Python - Fatal编程技术网

Python set和frozenset在实现中的差异

Python set和frozenset在实现中的差异,python,Python,我在这个链接上检查了set是可变的,而frozenset是不可变的,因此是可散列的。那么,集合是如何在python中实现的,元素查找时间是多少?实际上,我有一个元组列表[(1,2),(3,4),(2,1)],其中元组中的每个条目都是一个id,我想在此列表中创建一个集合/冻结集合。在这种情况下,集合应包含(1,2,3,4)作为元素。我可以使用frozenset从元组列表中一个接一个地向其中插入元素,还是只能使用集合?至于你的第一个问题,我实际上还没有检查源代码,但似乎可以安全地假设集合需要包含可哈

我在这个链接上检查了set是可变的,而frozenset是不可变的,因此是可散列的。那么,集合是如何在python中实现的,元素查找时间是多少?实际上,我有一个元组列表[(1,2),(3,4),(2,1)],其中元组中的每个条目都是一个id,我想在此列表中创建一个集合/冻结集合。在这种情况下,集合应包含(1,2,3,4)作为元素。我可以使用frozenset从元组列表中一个接一个地向其中插入元素,还是只能使用集合?

至于你的第一个问题,我实际上还没有检查源代码,但似乎可以安全地假设集合需要包含可哈希类型的对象,它是使用哈希表实现的,它的查找时间是,因此,O(1)

至于你的第二个问题,你不能一个接一个地将元素插入到
frozenset
中(很明显,因为它是不可变的),但是没有理由使用集合;只需从组成值的列表(或其他iterable)构建它,例如:

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

可以从生成器表达式或其他iterable实例化冻结集。在实例化完成之前,它不是不可变的

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

Python3.3还有一个优化,当用作操作符中
的右侧时,它可以将{1,2,3,4}等集合文字转换为预计算的冻结集。

集合和冻结集的实现方式与哈希表相同。(否则为什么他们会要求自己的元素实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
?)事实上,如果你看一下,他们几乎共享所有的代码。这意味着,只要哈希冲突不失控,查找和删除是O(1),插入是摊销O(1)

创建冻结集的常用方法是使用其他iterable对其进行初始化。正如gnibbler所建议的,这里最适合的可能是
itertools.chain.from\u iterable

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

这纯粹是猜测,但我认为它们都是以相同的方式实现的,但是frozenset有一个写锁(因此具有不变性)。在一般情况下,
frozenset
上的查找时间应该更快,因为具有可变性(在
set
s中),解释器可能需要更长的探测时间来查找/插入元素。不过,希望真正了解这一点的人会发布一个答案-我对
列表感兴趣。\uuuu add\uuuu
将为您提供二次性能。您应该使用
list.\uuuu iadd\uuuuu
代替,但这只是一个示例。为了演示起见,我尽量保持简单,但我不确定我最终的成功程度。:)那么这里的链接已经过时了?目前有两种内置集类型,set和frozenset。集合类型是可变的——可以使用add()和remove()等方法更改内容。因为它是可变的,所以它没有散列值,不能用作字典键或另一个集合的元素。frozenset类型是不可变和可散列的——其内容在创建之后不能更改;但是,它可以用作字典键或其他集合的元素。是什么让你认为它过时了?对我来说,这似乎是准确的。你在上面说:“我实际上没有检查源代码,但从集合需要包含可散列类型的对象这一事实来看,似乎可以安全地假设,它是使用散列表实现的,因此,它的查找时间是O(1)。”链接说“它没有哈希值,不能用作字典键或其他集合的元素。“你更喜欢set还是frozenset?查找时间有什么不同?@vkaul11,我不认为查找会有什么不同time@vkaul11,frozenset优化应该意味着在编译时创建集合,而不是每次执行代码时(在运行时)。根据具体情况,这种微优化可能会对performance.docs.python.org/2.4/lib/types-set.html产生显著影响,所以这里的链接过时了?目前有两种内置集类型,set和frozenset。集合类型是可变的——可以使用add()和remove()等方法更改内容。因为它是可变的,所以它没有散列值,不能用作字典键或另一个集合的元素。frozenset类型是不可变和可散列的——其内容在创建之后不能更改;但是,它可以用作字典键或其他集合的元素。虽然该链接是关于旧版本的,但其中的信息仍然基本正确。不过,这与我所说的并不矛盾。大多数frozenset和set代码都是完全相同的代码。他们甚至有相同的迭代器类型。根据链接,set没有散列值,那么如何用散列表实现它呢;它的键必须是可散列的。