Por que o início da string é mais lento do que em?

Surpreendentemente, achostartswith é mais lento quein:

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

Como todos sabemos, oin A operação precisa pesquisar toda a cadeia estartswith só precisa verificar os primeiros caracteres, parastartswith deve ser mais eficiente.

Quandos é grande o suficiente,startswith é mais rápido:

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

Então parece que chamarstartswith tem alguma sobrecarga, o que a torna mais lenta quando a corda é pequena.

E então eu tentei descobrir qual é a sobrecarga dostartswith ligar.

Primeiro, eu usei umf variável para reduzir o custo da operação do ponto - como mencionado nesteresponda - aqui podemos verstartswith ainda é mais lento:

In [16]: f=s.startswith

In [17]: %timeit f("XYZ")
1000000 loops, best of 3: 270 ns per loop

Além disso, testei o custo de uma chamada de função vazia:

In [18]: def func(a): pass

In [19]: %timeit func("XYZ")
10000000 loops, best of 3: 106 ns per loop

Independentemente do custo da operação do ponto e da chamada de função, o tempo destartswith é sobre (270-106) = 164ns, mas oin operação leva apenas 81.7ns. Parece que ainda existem algumas despesas gerais parastartswith, o que é isso?

Adicione o resultado do teste entrestartswith e__contains__ como sugerido por poke e 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

questionAnswers(2)

yourAnswerToTheQuestion