タイトルの通りである。 python setの和集合・積集合の計算にand/orは使えない。
ミスってからすぐ気づいたので大きな手戻りにはならなかったが、備忘録として今後忘れないように書き留めておく。
setに対してand/orを使うと何が起きるか
PowerShellでpythonと打ってインタプリタ形式で起動した。
>>> x = {1, 2, 3} >>> y = {2, 3, 4} >>> x and y {2, 3, 4} # 集合のand、積集合ならば{2, 3}になるはず >>> x or y {1, 2, 3} # 集合のor、和集合ならば{1, 2, 3, 4}になるはず
上記の例では、意図したとおりに動いていないのが明らかである。 しかし、実際に作業をしていたときは、両方の集合が色々と演算した結果だったので、返ってきた集合が意図通りでないということがすぐには分からず、その後コードを書き進めて「あれ?何かおかしくないか?」となった。 幸い、「python set 積集合」で検索してすぐに正解にたどり着いた。
正しい書き方
和集合には | 、積集合には& を使う。
>>> x = {1, 2, 3} >>> y = {2, 3, 4} >>> x & y # 集合のand、積集合 {2, 3} >>> x | y # 集合のor、和集合 {1, 2, 3, 4}
他にも、差集合、対称差集合の演算子もある。詳しくは公式ドキュメントを参照のこと。
組み込み型 — Python 3.8.0 ドキュメント
仕組み
では、何でand/orを使ったら上記のような挙動になったのか?この理由は、以下の2点によって説明できる。
1点目の公式ドキュメントはここ。
組み込み型 — Python 3.8.0 ドキュメント
PyQのブログによる、もう少し詳しい解説はここ。
Pythonのandとorはif文以外でも使える?andとorの動作が面白いという話をします - Python学習チャンネル by PyQ
2点目の公式ドキュメントはここ。
組み込み型 — Python 3.8.0 ドキュメント
ここを見ると、bool()を使えば真偽値を判定した結果(ブール値にキャストした結果)が返ってくるのね。
組み込み関数 — Python 3.8.0 ドキュメント
int()はよく使うけど、bool()は違和感があるな……
やってみよう。
>>> bool({1, 2, 3}) True >>> bool(set()) False
1つ以上の要素の入ったsetはTrue、空のsetはFalseになっている。
({}
と書くと、空のsetではなく空の辞書になってしまう。空のsetはset()
と書く。)
以上の2点を踏まえて、もう一度最初の例に戻ろう。
>>> x = {1, 2, 3} >>> y = {2, 3, 4} >>> x and y {2, 3, 4} # 最初にxの真偽値を評価する。xは空でないsetなのでTrueである。したがってyを返す。 >>> x or y {1, 2, 3} # 最初にxの真偽値を評価する。xは空でないsetなのでTrueである。したがってxを返す。
文法規則に従っているから、言われてみればその通りだけど、初見だとビックリするなぁ。 「おいおい、そこで使ってるand/orは和集合・積集合の演算子じゃない、論理演算子だぞ。大丈夫か?」という警告をしてくれるわけでもない。仕様をちゃんと理解して気を付けよう……