我正在从python set
与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
怎么回事?
答案 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
仅出现一次;在集合中这不是问题,但在列表中只能删除一次,并且在以后尝试删除相同值时会出错。