LoginSignup
0
0

More than 3 years have passed since last update.

比較演算でつまづいた話

Last updated at Posted at 2019-11-26

ちょっとイキって比較演算子を使っていい感じに書いてコード量を減らそうとしたら、想定外のところでつまづいたので備忘録的に残しておこうと思います.

環境

  • macOS Catalina 10.15.1
  • Python 3.7.5

対象読者

自分

演算子一覧

pythonには以下のような比較演算子があり、分岐などの条件文に使用したりします。

演算子 結果
x < y x が y より小さければ True
x <= y x が y より小さいか等しければ True
x > y x が y より大きければ True
x >= y x が y より大きいか等しければ True
x == y x と y の値が等しければ True
x != y x と y の値が等しくなければ True
x is y x と y が同じオブジェクトであれば True
x is not y x と y が同じオブジェクトでなければ True
x in y x が y に含まれていれば True
x not in y x が y に含まれていなければ True

他にも以下のような論理演算子が存在し、これらを組み合わせることで自由度の高い条件文を作成することが可能です。

演算子 結果
x and y x が True で y も True のとき y を返す。x が False のとき x を返す
x or y x が True のとき x を返す。x が False のとき y を返す
not x x が True であれば False、x が False であれば True を返す

論理演算子の結果が妥当か確認する方法

andorの場合は、左辺がTrueになるかFalseになるかが重要になってきます。これについてはboolを使えば簡単に確認できます。

bool

TrueやFalseは当然そのままの結果が返ってきます。

>>> bool(True)
True
>>> bool(False)
False

数値

数値型の場合は0以外はTrueが返ってきます。

>>> bool(1)
True
>>> bool(0)
False
>>> bool(-1)
True
>>> bool(0.5)
True
>>> bool(1j)
True
>>> bool(0j)
False
>>> bool(-1j)
True

文字列

文字列型では文字が存在している場合にTrueになります。

>>> bool('')
False
>>> bool('hoge')
True
>>> bool(' ')
True

これはstrのインスタンスが生成されているかを見ているわけではないので、注意が必要です。

>>> type('')
<class 'str'>

None

NoneもFalseとして扱われます。

>>> bool(None)
False

配列

配列は要素が1つ以上存在する時にTrueが返ってきます。

>>> bool([])
False
>>> bool([""])
True
>>> bool([None])
True

つまづいた点

これまで見てきた通り非常に容易だとは思うのですが、注意するべき点は要素が存在している時にTrueが返ってくるとは限らないということです。

どういう意味かを説明する前に、一旦Falseになる条件を以下にまとめてみました。

>>> bool(False)
False
>>> bool(0)
False
>>> bool('')
False
>>> bool(None)
False
>>> bool([])
False

これを見る限り中身がなければFalseになりそうなところです。

そこで以下のようなコードを実行してみました。

>>> import numpy as np
>>> hoge = None
>>> fuga = True
>>> if fuga:
...     hoge = np.arange(10)
>>> bazz = hoge if hoge else list(range(10))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

まさかのエラー!
個人的にやりたかったこととしては、条件式(fuga)がTrueのときndarrayを生成する関数が存在しており、別の関数ではhogeが生成されているかを判断し、新たに生成し直すかそのまま使用したいと考えていました。

解決策としてはインスタンスを生成しているかの確認ではなく、Noneであるかを判断基準に用いました。

>>> import numpy as np
>>> hoge = None
>>> fuga = True
>>> if fuga:
...     hoge = np.arange(10)
>>> bazz = hoge if hoge is not None else list(range(10))
>>> bazz
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

ただし、この場合だとhogeにndarray以外が生成されていてもhogeを返すので、ndarray限定にしたい場合は要検討という感じですね...

追記 (2020/3/10)

hogeの中身がndarrayか確認する方法としては、isinstanceという組み込み関数があるので、それを用いることで確認することが可能です。

>>> hoge = np.arange(10)
>>> hoge
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>
>>> isinstance(hoge, np.ndarray)
True
>>>
>>> hoge = None
>>> fuga = True
>>> if fuga:
...     hoge = np.arange(10)
...
>>>
>>> bazz = hoge if isinstance(hoge, np.ndarray) else list(range(10))
>>> bazz
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>
>>> bazz = hoge if isinstance(hoge, list) else list(range(10))
>>> bazz
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

雑談

外部ライブラリをboolで判定するとFalseが返ってくることには驚きでした。まぁ、イキって変な書き方しようとした自分が悪いわけですが...
使いこなすにはまだまだ知識が足りてないことを痛感してしまいますが、めげずに日々精進していきたいものです(・∀・)

参考

Pythonのif文による条件分岐の書き方

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0