首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Set与frozenset性能对比

Set与frozenset性能对比
EN

Stack Overflow用户
提问于 2016-04-12 01:21:18
回答 2查看 21.5K关注 0票数 50

我一直在摆弄Python的setfrozenset集合类型。

最初,我假设frozenset将提供比set更好的查找性能,因为它是不可变的,因此可以利用存储项的结构。

然而,对于下面的实验,情况似乎并非如此:

代码语言:javascript
复制
import random
import time
import sys

def main(n):
    numbers = []
    for _ in xrange(n):
        numbers.append(random.randint(0, sys.maxint))
    set_ = set(numbers)
    frozenset_ = frozenset(set_)

    start = time.time()
    for number in numbers:
        number in set_
    set_duration = time.time() - start

    start = time.time()
    for number in numbers:
        number in frozenset_
    frozenset_duration = time.time() - start

    print "set      : %.3f" % set_duration
    print "frozenset: %.3f" % frozenset_duration


if __name__ == "__main__":
    n = int(sys.argv[1])
    main(n)

我同时使用CPython和PyPy执行此代码,结果如下:

代码语言:javascript
复制
> pypy set.py 100000000
set      : 6.156
frozenset: 6.166

> python set.py 100000000
set      : 16.824
frozenset: 17.248

无论是在CPython中还是在PyPy中,frozenset的查找性能似乎都要慢一些。有没有人知道为什么会这样?我并没有深入研究这些实现。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-12 01:55:20

frozensetset实现在很大程度上是共享的;set只是一个添加了变异方法的frozenset,具有完全相同的哈希表实现。请参阅Objects/setobject.c source file;顶级PyFrozenSet_Type definitionPySet_Type definition共享功能。

这里没有对冻结集进行优化,因为在测试成员资格时,不需要计算frozenset中项目的哈希值。你用来测试集合的项目仍然需要计算它们的哈希值,以便在集合哈希表中找到正确的位置,这样你就可以进行相等性测试。

因此,您的计时结果可能由于系统上运行的其他进程而关闭;您测量了挂钟时间,并且没有禁用Python垃圾收集,也没有重复测试相同的东西。

尝试使用来自numbers的一个值和不在集合中的一个值使用timeit module运行测试:

代码语言:javascript
复制
import random
import sys
import timeit

numbers = [random.randrange(sys.maxsize) for _ in range(10000)]
set_ = set(numbers)
fset = frozenset(numbers)
present = random.choice(numbers)
notpresent = -1
test = 'present in s; notpresent in s'

settime = timeit.timeit(
    test,
    'from __main__ import set_ as s, present, notpresent')
fsettime = timeit.timeit(
    test,
    'from __main__ import fset as s, present, notpresent')

print('set      : {:.3f} seconds'.format(settime))
print('frozenset: {:.3f} seconds'.format(fsettime))

这会重复每个测试一百万次,并产生:

代码语言:javascript
复制
set      : 0.050 seconds
frozenset: 0.050 seconds
票数 91
EN

Stack Overflow用户

发布于 2018-07-16 22:12:44

使用这两种不同的数据类型的原因不是为了性能,而是为了实现功能。因为frozenset是不可变的,所以它们可以用作字典中的关键字。Set不能用于此目的。

票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36555214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档