(충격) 이 둘이 다르다.
이 사실을 알게 된 계기는 어처구니 없는 실수로 인한 오류의 발견이었다! (== None으로 사용할 것을 !=None으로 사용하는 바람에;;;) 여튼 None과 비교를 하게 된 것은 새로생성한 함수의 기본파라미터에 대해서 None으로 지정해 주고, 파라미터가 입력이 되지 않았으면 그대로 실행하려던 것이 계기가 되었다. 사실 내용을 적다보니 비교를 하고자 하는 연산자 자체가 중요한 것이지 비교의 대상이 되는 None은 그다지 중요한게 아니었다.
간략하게 먼저 결론!!!
'==' 으로 비교하는 경우는 객체의 요소와 비교.
In [42]:
# 724는 필자의 생일. Thank you ;)
np.array([0.724, 0.724, 0.724]) == None
array([False, False, False])
'is' 으로 비교하는 경우는 객체 자체와 비교.
np.array([0.724, 0.724, 0.724]) is None
False
결론을 내리기 위한 과정이 궁금하다면????
스크롤을 내려가며 읽어주시면 됩니다...ㅋㅋㅋㅋㅋ Thank you 😁
1. Python Style Guide 내용
Style Guide for Python Code 에 의하면 None과 같은 싱글톤(단일객체?)과의 비교는 is 나 is not으로 수행되어야 하며, 절대로 평등 연산자로 비교 되어서는 안된다고 한다.(https://www.python.org/dev/peps/pep-0008/) 왜인지는 서술되어 있지 않다! (아마 위에서 말한 결론의 내용일 듯! 평등연산자 : 객체의 요소와 비교, is : 객체 자체 비교)
Comparisons to singletons like None should always be done with is or is not, never the equality operators.
2. 블로그 참고
따라서, 이 내용에 대해서 한 블로거가 실제로 ' == None' 과 ' is None ' 이 어떤 차이가 있는지 비교를 해 봤다.(http://jaredgrubb.blogspot.com/2009/04/python-is-none-vs-none.html)
이 블로그의 결론은
1. 이 둘을 구분하는 것이 크게 의미가 있지 않다.
2. 이 둘을 1만번 수행한 결과 상대적인 속도에는 차이가 있으나, 절대적으로 큰 차이는 아니다 (0.61초 vs 1.17초로 is None 우세)
2번 내용에 대한 부연설명은, is None의 경우 id를 단순히 비교하여 속도가 빠르지만, ==None으로 비교하는 경우 None 및 전체 객체에 대한 dict조회가 필요하기 때문에 시간이 조금 더 걸린다는 점이다.
(평등연산자 : 객체의 요소와 비교, is : 객체 자체 비교 이기 때문이지 않을까!)
이 내용에 실려 있는 예제를 살짝 변형하여 실제로 테스트 코드를 수행 해봤다. (속도측정 제외)
In [31]:
class Zero(): # a class that is zero
def __nonzero__(self):
return False
class One(): # a class that is one
def __nonzero__(self):
return True
class Len0(): # a class with zero length
def __len__(self):
return 0
class Equal(): # a class that is equal to everything
def __eq__(self, other):
return True
stuff = [None, False, 0, 0.0, 0j,
(), [], {}, set(), '', float('NaN'), float('inf'),
Zero(), Len0(), Equal()]
for x in stuff:
if x is None:
print(f" {x} is None ★★★")
elif x is not None:
print(f" {x} is not None ")
# end if 1
if x==None:
print(f" {x} == None ★★★")
elif x!=None:
print(f" {x} != None ")
# end if 2
print('\n=========================\n')
Out [31]:
None is None ★★★
None == None ★★★
=========================
False is not None
False != None
=========================
0 is not None
0 != None
=========================
0.0 is not None
0.0 != None
=========================
0j is not None
0j != None
=========================
() is not None
() != None
=========================
[] is not None
[] != None
=========================
{} is not None
{} != None
=========================
set() is not None
set() != None
=========================
is not None
!= None
=========================
nan is not None
nan != None
=========================
inf is not None
inf != None
=========================
<__main__.Zero object at 0x7f52d08af4c0> is not None
<__main__.Zero object at 0x7f52d08af4c0> != None
=========================
<__main__.One object at 0x7f52c814d040> is not None
<__main__.One object at 0x7f52c814d040> != None
=========================
<__main__.Len0 object at 0x7f52d08af430> is not None
<__main__.Len0 object at 0x7f52d08af430> != None
=========================
<__main__.Equal object at 0x7f52c814d0a0> is not None
<__main__.Equal object at 0x7f52c814d0a0> == None ★★★
=========================
'== None' 과 'is None' 에서 다른 결과를 보인 것은 마지막 객체인 Equal 클래스 인데, 클래스 내의 eq함수가 다른객체와의 비교 후 무조건 True를 return 하는 클래스 이다. 단순히 True를 return하는 One 클래스와 비교하는 것이 가장 포인트가 되는 것 같은데, 이는 다른 객체와의 비교가 들어갔다는 점이다.
그 결과, 단순 비교인 is None으로 비교를 한 경우 False로 판정되었고, == None으로 비교를 한 경우 True로 판정이 되었다. 아우 어려워.... 이 부분은 조금 더 확인이 필요할 듯 하다.
정리!!
Array와 같은 요소들과 비교를 위해선 비교연산자인 == 를 사용! (속도 ↓)
None과 같은 단일 객체 자체와의 비교는 is 를 사용!! (속도 ↑)
'Development > Python' 카테고리의 다른 글
[Python] 특정 디렉토리 복사 붙여넣기 (Copy & Paste) (0) | 2022.02.09 |
---|---|
[Python] Dictionary의 Value를 얻을 때, 존재하지 않는 Key는 넘어가야 하는 경우(KeyError 해결) (0) | 2022.02.09 |
[Python] 리스트의 첫 번째 순서로 Append 하는 방법 (0) | 2022.01.20 |
[Python] Dataframe 2개의 컬럼을 활용하여 Dictionary 생성 (0) | 2022.01.04 |
[Python] Jupyter Notebook 스크립트 브라우저 창에 맞추기 (사이즈 조절) (2) | 2021.12.15 |
댓글