我正在从 pythonset
与list
中计时元素删除。我的列表 timeit 代码正在引发ValueError: ... x not in list
,但前提是我使用timeit
!?? 运行多个迭代
对于列表,在设置代码中创建的变量似乎在后续迭代中重复使用(好像安装代码没有第二次运行??
这是我的代码:
In [1]: import timeit
In [2]: timeit.timeit(stmt='a.discard(10**5)', setup='a = set(range(10**6))', number=100000)
Out[2]: 0.02187999989837408
In [3]: timeit.timeit(stmt='a.remove(10**5)', setup='a = list(range(10**6))', number=1)
Out[3]: 0.023419374600052834
In [4]: timeit.timeit(stmt='a.remove(10**5)', setup='a = list(range(10**6))', number=2)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
...
ValueError: list.remove(x): x not in list
这是怎么回事??
它们的关键点是,即使number
为>1,setup
也只执行一次(因此,当您尝试使用已从列表中删除的唯一值调用list.remove
时,ValueError
(。 来自文档(强调我的(:
主语句的时间数字执行。这将执行设置 语句一次,然后返回执行 main 所需的时间 语句多次,以秒为单位作为浮点数进行测量。这 参数是循环的次数,默认为 1 百万。主语句、设置语句和计时器 要使用的函数将传递给构造函数。
因此,如果您想执行这样的代码片段的多个计时(例如为了获得更准确的计时(,那么您必须使用number=1
,但您可以将repeat
参数与timeit.repeat()
一起使用:
>>> timeit.repeat(stmt='a.remove(10**5)', setup='a = list(range(10**6))', number=1, repeat=2)
[0.002321417909115553, 0.0023121219128370285]
In [4]: timeit.timeit(stmt='a.remove(10**5)', setup='a = list(range(10**6))', number=2)
a.remove(10**5)
执行两次,但 10**5 只能删除一次。setup
只调用一次,因此您始终在同一列表或集合上工作。
这相当于
a = list(range(10**6))
a.remove(10**5) # works
a.remove(10**5) # fails with ValueError: list.remove(x): x not in list
对于集合,这不会失败,因为设置丢弃和列表删除的行为不同。 如果您使用设置删除方法,您最终也会收到错误(KeyError(
a = set(range(10**6))
a.discard(10**5) # works
a.discard(10**5) # works
但
a = set(range(10**6))
a.remove(10**5) # works
a.remove(10**5) # KeyError 10**5
如果被丢弃的元素不在集合中,则对集合的discard()
操作不执行任何操作。但是,当元素不存在时,对列表的remove()
操作会引发ValueError
。当您使用range(10**6)
初始化列表时,该值10**5
只出现一次;在集合中,这不是问题,但在列表中,它只能删除一次,并且在将来尝试删除相同值时会出现错误。