今日は==
とis
の違いについてざっくりと。言葉で説明するよりまずは具体例を見せたほうが早いと思ったので以下を参照に。
>>> lst1 = [1,2,3]
>>> lst2 = [1,2,3]
>>> lst1 == lst2
True
>>> lst1 is lst2
False
>>> lst1 = lst2
>>> lst1 is lst2
True
isと==の違い
簡単に言うと==
は"value equality"(簡単にいえばぱっと見中身が同じかどうか)を確かめる。is
は各オブジェクトのポインターの方向を示している。一言で言えば"reference equality"実際にpythontutor.comで各オブジェクトの動きを見ると分かりやすいかもしれない。他の言語については分からないが(たしかCは同じだったと聞いた)少なくともpythonの世界ではlst1
とlst2
は中身は同じでも違うオブジェクトとして認識される。そのためis
判定を行うとFalse
と出る。極端な説明をすればlst1
とlst2
は各リストの出身地と考えてみてもいいかもしれない。
簡潔に言うと:
use
==
if you mean the objects should represent the same thing (most common usage) andis
if you mean the objects should be in identical pieces of memory (you'd know if you needed the latter).
>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
>>> b == a
True
>>> b = a[:] # b(=a[:])とa([1,2,3])はis判定ではfalse
>>> b is a
False
>>> b == a
True
SOFを参考にこの考え方を少しだけ広げてみる。int
でもこれは通じる:
>>> 1000 is 10**3
False
>>> 1000 == 10**3
True
そしてstr
でも同じことが言える:
>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True
中でも特に興味深かったのがクラスを用いて比較した例:
>>> class foo(object):
def __eq__(self, other):
return True
>>> f = foo()
>>> f == None
True
>>> f is None
False
>>> f = None
>>> f is None
True
読んでみて「たしかに!」と気付かされました。一度感覚をつかめばちょっとした応用にも使えそう。
isを使ってintを比較する際の注意点
どうやらint
に対してはis
は少し奇妙な振る舞いをするらしい。
>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False
と
>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True
を比較すると分かるかもしれないが、数に応じてpythonとやらが変わった振る舞いを行う用にできているらしい。これはpythonがint
の-5から256までしかreference implementation(=is
)に対応していないからだという。これがpythonのパフォーマンス向上の理由の一つなんだとか。
>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));
...
250: True
251: True
252: True
253: True
254: True
255: True
256: True
257: False
258: False
259: False
よってis
を用いてint
を扱うときは注意したほうが良さそうだ。ちなみにこれはid(int)
でも調べることが可能。