環境
- Python 3.6.4
結論
Pythonの数値比較ではisを使ってはいけません。
Pythonにおけるis
と==
はそれぞれに用意されていてる用途に従って使いましょう。
- is オブジェクトのidの比較
- == オブジェクトの数値の比較
処理速度が速いからといってisで数値比較とかするのはNGです。
コード
例えば、大抵の環境では
>>> a = 1
>>> a is 1
>>> True
となるので、うまく行っているように見えますが
実はこれはPythonがシングルトンで確保してくれてるだけです。
for i in range(255, 260):
a = i
print '{}: {}'.format(i, a is i+1-1)
>>> 255: True
>>> 256: True
>>> 257: False
>>> 258: False
>>> 259: False
実際のobjectのidを出力する方はこっち
for i in range(255, 260):
a = i
print '{}: {}: {}'.format(i, id(i), id(a+1-1))
>>> 255: 4406286672: 4406286672
>>> 256: 4406286704: 4406286704
>>> 257: 4409913072: 4410306320
>>> 258: 4410306384: 4410306320
>>> 259: 4409913072: 4410306320
Pythonは-5~256の整数値をシングルトンで確保しているようで、これら以外の数値は比較で使われるべきではありません。
ガーベジコレクトもありますし、少なくとも安全に使えるとはいえない気がします。
(gccollectが行われた場合の挙動については詳しくないです(´・ω・`))
きっかけ
is
で整数値判定をしてたら時々挙動がおかしくなったことで判明
isの使い道
自分で生成したオブジェクトの同一性判定に使うべきだと思います。
巷でよく取り上げられる「None
判定の時にis
を使う方が良い」については経験的に多分正しいです。
ただ、例外的な使い方である気はします。
よく分からないこと
a = None
a is None
b = True
b is True
c = False
c is False
これらが常に安全にTrue
になるかはよく分かりません。。
分かる人いたら教えてください(´・ω・`)