概要
nltkの学習中に以下のようなコードが。
>>> sorted(t for t in set(text2) if "cie" in t or 'cei' in t)
ここでのtext2はnltkに最初から備え付けてあるTextオブジェクトなのですが、中身としては"Sense and Sensibility"という小説になっています。日本語だと「分別と多感」という名前で知られているようですね(未読)。
アホな私は、
>>> sorted(t for t in set(text2) if ("cie" or "cei") in t)
と同じじゃない?と思って試してみると、チュートリアル側のコードでは"ceiling"が要素に含まれているのに、自作のコードでは含まれていないという状態に。実際にその部分だけ判定を抜き出して見ると、以下のようになります。
print("cie" in "ceiling" or "cei" in "ceiling")
print(("cie" or "cei") in "ceiling")
True
False
なんでこんなことに?
or演算子の挙動をしっかりと理解していなかったが故の末路です。こちらの記事を参考にさせていただくと、"cie" or "cei"は、以下のコードと等価です。
if bool("cie"):
return "cie"
else:
return "cei"
Pythonは1文字以上の文字列はTrueだと評価するので、if bool("cie"):は常にTrueになり、結果として"cie"しか返ってきません。そりゃ"ceiling"なんて入ってこないわけだ。
チュートリアル側のコードであれば、
if bool("cie" in "ceiling"):
return "cie" in "ceiling"
else:
return "cei" in "ceiling"
となり、if側でFalseとなりますが、elseでは"cei" in "ceiling"、すなわちTrueが返ってきます。結果として「文字列に"cei"か"cie"があれば」という判定をしっかりとこなせるわけですね。
オマケ
なお、勉強ついでにandの場合の挙動も確認しておくと、
if not bool("cie"):
return "cie"
else:
return "cei"
と等価になります。bool("cie")は常にTrueなので、この場合はelse文に入って必ず"cei"が入ってくることになりますね。
まとめ
前も似たようなことで引っかかった記憶があるのですが、その時は「何故か動く」の精神でスルーしていました。しっかりと調べて覚えて、記録しておくのは大事ですねホント。今後も頑張ります。
集合知に感謝。