python的timeit未初始化设置代码中的列表

时间:2018-08-08 14:47:58

标签: python list set timeit

我正在从python setlist中移除计时元素。我的列表的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

怎么回事?

3 个答案:

答案 0 :(得分:2)

In [4]: timeit.timeit(stmt='a.remove(10**5)', setup='a = list(range(10**6))', number=2)

a.remove(10**5)执行两次,但10 ** 5只能删除一次。 setup仅被称为ONCE,因此您始终使用相同的列表或集合。

这等效于

a = list(range(10**6))
a.remove(10**5)  # works
a.remove(10**5)  # fails with ValueError: list.remove(x): x not in list

对于集合来说这不会失败,因为集合丢弃和列表删除的行为有所不同。 如果使用set remove方法,也会导致出现错误(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

答案 1 :(得分:2)

关键点在于,即使setup大于1,number也只能执行一次(em)(因此,当您尝试调用{{1 }},其中的唯一值已从列表中删除。来自docs(重点是我):

  

执行主语句的次数。 这将执行设置   语句一次,然后返回执行主语句所需的时间   语句多次,以秒为单位,以浮点数表示。的   参数是循环的次数,默认为1   百万。主语句,设置语句和计时器   将要使用的函数传递给构造函数。

因此,如果您要像这样对代码段执行多个计时(例如,以获得更准确的计时),则必须使用ValueError,但可以将list.remove参数与{改为{1}}:

number=1

答案 2 :(得分:0)

如果要丢弃的元素不在集合中,则对集合的discard()操作将不执行任何操作。但是,当元素不存在时,列表上的remove()操作将引发ValueError。当您使用range(10**6)初始化列表时,值10**5仅出现一次;在集合中这不是问题,但在列表中只能删除一次,并且在以后尝试删除相同值时会出错。