2015年11月24日

Noneチェックにはis演算子

ある変数 a に対して、a が None であるどうかを調べるには、is演算子を用いて a is None という判定方法を用いるべきです。こちらで述べたように、これは is演算子の代表的な使い道です。


a is None と a == None の違いは何でしょうか?

まず、a is None の方が若干動作速度が速いです。
これは、a is None が単純な id の比較になるのに対し、a == None は a.__eq__()メソッドが呼ばれるからです。

次に、こちらの方が大きな理由なのですが、仮に a がクラスインスタンスで、__eq__() メソッドをオーバーライドしている場合に、a == None は思わぬ結果となることがあります。
以下の例を見てください。

# __eq__() をオーバーライドしているクラス
>>> class Sample(object):
...     def __init__(self):
...         self.value = 0
...
...     # rhs が None である場合を想定していない
...     def __eq__(self, rhs):
...         return self.value == rhs.value
...

>>> a = Sample()

# a is None は正しく動作
>>> a is None
False

# a == None なら a.__eq__(None) が呼ばれる
>>> a == None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in __eq__
AttributeError: 'NoneType' object has no attribute 'value'
オーバーライドした __eq__() メソッドが正しく型チェックを行っていれば、この問題は発生しません。しかし、全てのクラスが正しい作法で __eq__() メソッドを定義しているという保証はありません(特に他人が作ったクラスを使う場合)。

「Noneチェックには常に is演算子を用いる」という方針で Noneチェックをしておけば、__eq__() について悩む必要もなく、汎用的で動作も軽い Noneチェックを行うことができます。よって、Noneチェックには常に is演算子を用いるべきです。

0 件のコメント:

コメントを投稿