はじめに結論
and/orではなく&/|演算子を使う
概要
setに対して積集合・和集合を計算したいときがあると思うのですが、うっかり&/|の代わりにand, orを使ってしまうとひどい目に遭います。
たとえばこんな感じ。
>>> a = {0,1,2,3} >>> b = {1,3,5,7} >>> a and b {1, 3, 5, 7}
なにごと? と思いますよね。
and/orはブール値を返す訳ではない
pythonのこの手の演算子はboolを返さないで、オペランドをそのまま返します。
>>> "hoge" and "" '' >>> "hoge" or "" 'hoge'
boolに変換してよしなに扱うのは外側にあるもの(if文やwhileの条件節など)の役割です。
返ってくるのは最後に真理値が判定されたオペランドです。たとえば"hoge" and ""では"hoge"(True)だけでは全体の真理値が確定しないので""(False)も見て*1、真理値が確定したので""を返します。
参考:
Pythonにおける『and』と『or』の動作 - しゃちの備忘録
Python の or と and 演算子の罠 - Qiita
set型の場合は空のset以外はTrueなので、右側のオペランドが返ることが多いと思います。それが最初の結果になる理由です。
これの凶悪なところ
python的には普通の動作なのですが、ある意味とても凶悪なハマりどころを提供してくれています。
- 積集合、和集合はよく使う(と思う)
- 返り値の型がsetで、型だけ見れば期待通りなので気づかない(ロジックエラーが出てから「あれ?」となる)
怖いですね!
まとめ
知っていればハマらないので、気をつけましょう。とにかく&/|で計算すると覚えることが一番大切です。
*1:ここが意味不な人は 組み込み型 — Python 3.7.4 ドキュメントを見てください