开发者社区> 问答> 正文

在Python中对集合,列表和元组进行速度测试可得出令人惊讶的结果

我尝试在setlisttuple之间测试速度,并得到了令人惊讶的结果。

在此之前,基于此答案,我知道setlist更快。

这是我的测试代码:

import timeit,time
from sys import getsizeof as Size

List_Test = [range(1000)]
print("The Size of List is : {}".format(Size(List_Test)))
Set_Test = set(range(1000))
print("The Size of Set is : {}".format(Size(Set_Test)))
Tuple_Test = tuple(range(1000))
print("The Size of Tuple is : {}".format(Size(Tuple_Test)))


print("\nNow is to test speed\n")
time.sleep(3)

def Create_List():
    List = [i for i in range(1000)]

def Test_List():
    for i in List_Test:
        if i == 6:
            break

def Create_Set():
    Set = set(i for i in range(1000))

def Test_Set():
    for i in Set_Test:
        if i == 6:
            break

def Create_Tuple():
    Tuple = tuple(i for i in range(1000))

def Test_Tuple():
    for i in Tuple_Test:
        if i == 6:
            break

t = timeit.repeat(stmt="Create_List()",number=1000,setup="from __main__ import Create_List", repeat=30)
print("The Time of Create_List : {}".format(sum(t)/len(t)))
t = timeit.repeat(stmt="Create_Tuple()",number=1000,setup="from __main__ import Create_Tuple", repeat=30)
print("The Time of Create_Tuple : {}".format(sum(t)/len(t)))
t = timeit.repeat(stmt="Create_Set()",number=1000,setup="from __main__ import Create_Set", repeat=30)
print("The Time of Create_Set : {}".format(sum(t)/len(t)))

print("\n")

t = timeit.repeat(stmt="Test_List()",number=1000,setup="from __main__ import Test_List", repeat=30)
print("The Time of Test_List : {}".format(sum(t)/len(t)))
t = timeit.repeat(stmt="Test_Tuple()",number=1000,setup="from __main__ import Test_Tuple", repeat=30)
print("The Time of Test_Tuple : {}".format(sum(t)/len(t)))
t = timeit.repeat(stmt="Test_Set()",number=1000,setup="from __main__ import Test_Set", repeat=30)
print("The Time of Test_Set : {}".format(sum(t)/len(t)))

print("\nThe end")

最后,我发现:

Size: Set > Tuple > List
Speed: List > Tuple > Set

我认为我的测试代码是错误的。它出什么问题了?

  • 编辑:

我更改了测试代码:

List_Test = list(range(500000))
......

def Test_List():
    randomNumber = random.randint(0,500000)
    for i in List_Test:
        if i == randomNumber:
            break

# Other test code is the same

测试的结果总是list≈tuple> set

当将数字500000(x20)更改为10000000时,

它有时是list≈tuple≈set,但经常是list≈tuple> set

May I infer that only when all of them have the same length(And the number of length is large),we can use set (Although its size is much larger than tuple and list )?

问题来源: stackoverflow

展开
收起
is大龙 2020-03-23 15:59:34 1211 0
1 条回答
写回答
取消 提交回答
  • 这个测试套件有很多问题。

    [range(1000)]不等同于其他两个声明。这将形成一个包含一个元素的列表,并且该单个元素指向该范围。getsizeof不是递归的,因此它仅给出外部对象的大小。这可以通过创建具有不同范围大小的单个元素的列表并注意到getsizeof调用始终给出相同的结果来说明。

    如果使用list(range(1000)),您将得到一个合理的结果,该结果与元组的大小大致相同。我不确定将这些列表设为1000后会获得什么信息-为什么不比较三个空元素的大小?即使在这里,就我所知,这基本上还是一个与实现有关的测试,实际上与如何编写Python程序没有太大关系。当然,set会比您期望的大一些(基于哈希的结构通常比列表具有更多的开销),并且版本之间会有所不同。

    至于“创建”测试,请考虑`set(i for range(1000)中的i)。绝不会测试创建set所花费的时间,因为大部分时间都花在创建和运行作为参数传递的生成器上。与上一个测试一样,即使测试是公平的,我也不知道这能证明什么(即您使用了list()初始化方法而不是列表推导方法)。与“ size”测试一样,您可以使用空列表调用初始化程序,但是所有这些表明,创建时间实际上是相同的:存在一些函数调用和对象分配开销,这些开销是特定于实现的。

    最后,对查找操作进行速度测试:

    for i in Set_Test:
        if i == 6:
            break
    

    这将对最佳情况进行硬编码。列表和元组查找执行线性搜索,因此始终在7个比较中找到目标。这将几乎与集合查找相同,后者为O(1),但需要一些复杂的哈希运算,这会增加开销。该测试应使用随机索引,其中的分布意味着列表和元组将定期遇到最坏情况的情况。该集合应胜过列表,并且元组正确完成。

    此外,诸如“集合比列表快”这样的语句几乎没有意义-不能像这样对数据结构进行比较,“更快”之类的词表示特定的运行时条件,这些条件高度可变且区分大小写-具体。比较数据结构需要比较其操作的时间复杂度,这有助于描述它们是否适合某些目的。

    总结一下:即使正确编写,前两个测试也不值得执行,最后一个测试将显示集合查找为O(1),而列表/元组查找为O(n)(如果使用随机目标项目使它们公平) 。

    回答来源:stackoverflow

    2020-03-23 16:01:12
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
移动互联网测试到质量的转变 立即下载
给ITer的技术实战进阶课-阿里CIO学院独家教材(四) 立即下载
F2etest — 多浏览器兼容性测试整体解决方案 立即下载