Удивительно, но 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