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