【发布时间】:2015-08-04 08:48:45
【问题描述】:
在我的代码中,我有一个列表l,我正在从中创建一个列表字典。 (我正在对具有相同key 的对象进行分组)。通过try 语句和if 条件实现它,我在line_profiler 中注意到前者似乎更有效:
Line # Hits Time Per Hit % Time Line Contents
==============================================================
293 44378450 59805020 1.3 16.9 for element in l:
# stuff that compute 'key' from 'element'
302 2234869 2235518 1.0 0.6 try:
303 2234869 82486133 36.9 23.3 d[key].append(element)
304 57358 72499 1.3 0.0 except KeyError:
305 57358 1758248 30.7 0.5 d[key] = [element]
对比:
Line # Hits Time Per Hit % Time Line Contents
==============================================================
293 44378450 60185880 1.4 14.0 for element in l:
# stuff that compute 'key' from 'element'
307 2234869 81683512 36.5 19.1 if key in d.keys():
308 2177511 76393595 35.1 17.8 d.get(key).append(element)
309 else:
310 57358 1717679 29.9 0.4 d[key] = [element]
我知道使用try,只有在引发异常时才进入except(因此,除了少数例外,它的总体成本比每次测试条件的成本要低),但在这里,即使是@ 987654330@ 异常 (1.3+30.7 µs) 比测试条件 (36.5 µs) 慢。我认为引发异常比检查一个键是否在字典中更昂贵(in 只是测试哈希键,不是吗?这不是行搜索)。那为什么呢?
【问题讨论】:
-
这是 Python 2.x 吗?
-
这是 Python 3.4。顺便说一句,为什么要投反对票?
-
if版本必须查找key两次,一次在if测试中,一次在get中。如果这是 Python 2,它会更慢,因为d.keys()是一个列表,而不是一个视图,所以查找涉及线性搜索而不是基于哈希的集合测试。 -
Pythonic 的方法是使用
d = defaultdict(list)。然后d[key].append(element)将始终有效。 -
好的,但是您仍然在
if版本中进行 2 次查找(如果密钥存在)。 FWIW,在Using try vs if in python 中有一些关于if与except相对速度的好信息
标签: python performance try-catch python-3.4