== 와 is 비교

값이 같은지를 확인할 때 == 를 주로 사용한다.
그리고 None 인지를 확인할 때는 is 를 사용한다.

== 와 is 의 차이는 무엇일까?

== : value equality, 값이 같은지를 확인한다.
is : reference equality, 참조가 같은지를 확인한다.

1
2
3
4
5
l1 = []
l2 = []

print(l1 == l2) # True
print(l1 is l2) # False

위 결과 l1 == l2 는 True이고 l1 is l2 는 False이다.
리스트를 선언하여 변수에 할당할 때, 새로운 list object가 생성되어 변수에 할당되기 때문에 l1과 l2는 서로 다른 list object를 참조하게된다.
그렇기 때문에 l1, l2 모두 빈 list이기 때문에 값은 같지만 (==), 서로 다른 object 이기 때문에 참조는 같지 않다(is).

시각적으로 참조가 다름을 보고 싶다면 id()를 사용하여 확인하면 된다.

id(object)
Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

1
2
3
4
5
l1 = []
l2 = []

print('l1_id:', id(l1), ', l2_id:', id(l2))
print(id(l1) == id(l2)) # False

그럼 우리가 만든 class의 object 값 비교는 어떻게 할까?
이는 class의 __eq__를 사용하여 정의하면 된다.

아래 간단한 예제를 만들었다.
Foo 라는 class의 __eq__ 함수에 object 끼리 name이 대소문자 관계없이 같으면 값이 같다고 정의하였다.

1
2
3
4
5
6
7
8
9
10
class Foo():
def __init__(self, name):
self.name = name

def __eq__(self, other):
return self.name.lower() == other.name.lower()

a = Foo('hello')
b = Foo('HeLlO')
print(a == b) # True

물론 is로 하면 False가 나온다.


string의 경우 결과가 꽤 흥미롭게 나온다.

1
2
3
4
5
6
7
8
9
a = 'a'
aa = 'aa'
aa2 = 'a' + 'a'

print(aa == (a + a)) # True
print(aa == aa2) # True

print(aa is (a + a)) # False
print(aa is aa2) # False

‘aa’는 ‘a’ + ‘a’와 같지만 ‘a’를 담은 변수를 두 번 더한 것과는 다르다.
(내부적인 동작에 대해서는 자세히는 모르겠다….)
id() 메서드를 통해 확인 했을 때 변수 끼리 더했을 때 항상 새로운 객체를 생성한다.

1
2
3
4
5
print('aa_id:', id(aa))
print('aa2_id:', id(aa2))
print('a+a_id:', id(a + a)) # 3개의 결과가 서로 다르게 나옴
print('a+a_id:', id(a + a))
print('a+a_id:', id(a + a))

sys.intern() 메서드를 사용하면 파라미터로 전달된 string 객체와 값이 같은 interning string을 가져온다.
그래서 sys.intern() 메서드의 return 값의 identity는 항상 같다.
(그리고 interning string을 쓰는 것이 성능에 약간 도움이 된다고 한다. by Python docs)
https://docs.python.org/3.7/library/sys.html#sys.intern

1
2
3
4
5
6
7
8
from sys import intern

print('intern')
print('aa_id:', id(aa))
print('aa2_id:', id(aa2))
print('a+a_id:', id(intern(a + a)))
print('a+a_id:', id(intern(a + a)))
print('a+a_id:', id(intern(a + a)))
Share