Вы можете сравнить три различных метода с помощью timeit
. get1
- это try...except
, get2
использует встроенные .get
и get3
первые проверки.
In [1]: def get1(d, k):
......: try:
......: return d[k]
......: except KeyError:
......: return None
In [3]: def get2(d, k):
......: return d.get(k)
In [4]: def get3(d, k):
......: if k in d: return d[k]
......: else: return None
В небольшом словаре (100 элементов)
In [8]: %timeit -n 100 [get1(little_d, e) for e in range(len(little_d))]
18.8 µs ± 270 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [9]: %timeit -n 100 [get2(little_d, e) for e in range(len(little_d))]
22.5 µs ± 352 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [10]: %timeit -n 100 [get3(little_d, e) for e in range(len(little_d))]
19.3 µs ± 862 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
И в большем (1M элементов)
In [11]: %timeit -n 100 [get1(big_d, e) for e in range(len(little_d))]
19.4 µs ± 469 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [12]: %timeit -n 100 [get2(big_d, e) for e in range(len(little_d))]
21.8 µs ± 241 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [13]: %timeit -n 100 [get3(big_d, e) for e in range(len(little_d))]
19.2 µs ± 128 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
В словаре (1M) с ~ 50% "промахов" (random.choices(range(0, 2*len(big_id)), k=len(big_d))
) видно больше различий:
In [20]: %timeit -n 100 [get1(big_d, e) for e in choices]
514 ms ± 10.4 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [21]: %timeit -n 100 [get2(big_d, e) for e in choices]
416 ms ± 4.54 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [22]: %timeit -n 100 [get3(big_d, e) for e in choices]
367 ms ± 4.89 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
.get
все равно будет быстрее в этот случай.
In [23]: %timeit -n 100 [big_id.get(e) for e in choices]
334 ms ± 3.6 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
Они кажутся близкими, одинаково подвержены влиянию размера словаря, но по-разному подвержены промахам. Единственный реальный размер воздействия будет иметь место, когда python начинается побеждает (как это, вероятно, здесь происходит). Важным примечанием является то, что get2
просто медленнее, поскольку вызваны накладные расходы двух вызовов функций (get2
и .get
), которые стоят дорого - i sh в python (как показано в последнем тесте). Промахи приведут к более медленным результатам по разным причинам, как указывает @ user2864740 .
tl; dr
Я бы использовал .get
.
Ответ также будет в значительной степени зависеть от скорости реализации ваших ключей в __hash__
и __eq__
. Если __hash__
и __eq__
медленные, различия в двух вызовах hash
могут показать улучшение метода 1 или 2 (без дополнительной функции).