Удивительно, но startswith
медленнее, чем in
:
In [10]: s="ABCD"*10
In [11]: %timeit s.startswith("XYZ")
1000000 loops, best of 3: 307 ns per loop
In [12]: %timeit "XYZ" in s
10000000 loops, best of 3: 81.7 ns per loop
Как мы все знаем, операция in
должна искать всю строку, а startswith
просто нужно проверить первые несколько символов, поэтому startswith
должен быть более эффективным.
Когда s
достаточно велико, startswith
выполняется быстрее:
In [13]: s="ABCD"*200
In [14]: %timeit s.startswith("XYZ")
1000000 loops, best of 3: 306 ns per loop
In [15]: %timeit "XYZ" in s
1000000 loops, best of 3: 666 ns per loop
Таким образом, кажется, что вызов startswith
имеет некоторые накладные расходы, что делает его медленнее, когда строка мала.
И чем я попытался выяснить, что накладные расходы на вызов startswith
.
Во-первых, я использовал переменную f
, чтобы уменьшить стоимость операции с точкой - как указано в этом - здесь мы видим, что startswith
все еще медленнее:
In [16]: f=s.startswith
In [17]: %timeit f("XYZ")
1000000 loops, best of 3: 270 ns per loop
Кроме того, я проверил стоимость пустого вызова функции:
In [18]: def func(a): pass
In [19]: %timeit func("XYZ")
10000000 loops, best of 3: 106 ns per loop
Независимо от стоимости операции с точкой и вызова функции время startswith
составляет около (270-106) = 164 нс, но операция in
занимает всего 81,7 нс. Кажется, есть еще некоторые накладные расходы для startswith
, что это?
Добавьте результат теста между startswith
и __contains__
, как предложено poke и lvc:
In [28]: %timeit s.startswith("XYZ")
1000000 loops, best of 3: 314 ns per loop
In [29]: %timeit s.__contains__("XYZ")
1000000 loops, best of 3: 192 ns per loop