静かなる名辞

pythonとプログラミングのこと

2019/03/22:TechAcademyがteratailの質問・回答を盗用していた件
2019/03/26:TechAcademy盗用事件 公式発表と深まる疑念



【python】str.findとstr.indexの違い

はじめに

 pythonで文字列に対して部分文字列の検索を行うメソッドとして、str.findとstr.indexがあります。ほとんど同じものなのですが、どのような違いがあるのでしょうか?

 str.findとstr.indexはどちらも文字列のメソッドで、引数に渡した文字列の位置を返します。

>>> "hoge".find("og")
1
>>> "hoge".index("og")
1

 「一体なにが違うんだっけ」とふと思って調べてしまったので、メモします。

違い

 大きな違いはありません。ヒットする場合はほとんど同じです。しかし、ヒットしなかった場合の挙動だけ異なります。

 端的に言えばstr.findは見つからなかった場合-1を返しますが、str.indexは例外を送出します。

>>> "hoge".find("fuga")
-1
>>> "hoge".index("fuga")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found

str.index(sub[, start[, end]])(原文)
find() と同様ですが、部分文字列が見つからなかったとき ValueError を送出します。

組み込み型 — Python 3.7.3 ドキュメント

 それだけの違いのようです。単純ですね。

速度差

 まさかこんなのに速度差なんてないだろう、そう思っていた時期が私にもありました。

>>> s = "hoge"*1000 + "fuga"
>>> timeit.timeit(lambda : s.find("fuga"))
3.8523642780000955
>>> timeit.timeit(lambda : s.index("fuga"))
3.803682490000938

 ヒットする場合は互角です。

>>> def f1():
...     ret = s.find("piyo")
...     if ret == -1:
...         pass
...     else:
...         pass
... 
>>> def f2():
...     try:
...         ret = s.index("piyo")
...     except:
...         pass
... 
>>> timeit.timeit(f1)
3.907751840999481
>>> timeit.timeit(f2)
4.395755831001225

 例外処理は単純な比較より重いため、少し時間を食うようです。なんてこった。

 もちろん、処理目的にもよるため、「速いからfindの方が良い」とは一概には言えません。意図に応じて選ぶべきです。

 ただ、例外処理を書くのは少し面倒だし、行数も増えるので、findの方が便利に使えるケースが多いかな?

まとめ

 見つからなかったとき、str.findは-1を、str.indexはValueErrorを出すと覚えましょう。