静かなる名辞

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

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


【python】setのandとorには要注意

はじめに結論

 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 ドキュメントを見てください