그렇지 않은 경우 파이썬 == vs if! =


183

이 두 코드 줄의 차이점은 무엇입니까?

if not x == 'val':

if x != 'val':

하나는 다른 것보다 더 효율적입니까?

사용하는 것이 더 좋을까요

if x == 'val':
    pass
else:

101
읽을 수있는 것이 좋을수록 프로그램 병목 현상이 의심 될 것입니다.
Thomas Ayoub

1
이 질문은 "x in in list"및 "not x in list"경우에 관심이 있습니다.
SomethingSomething

5
@SomethingSomething은 동일하게 해석됩니다.
jonrsharpe

4
내 위의 의견에 대한 참조 @SomethingSomething stackoverflow.com/q/8738388/3001761
jonrsharpe

1
@SomethingSomething 그것도 마찬가지입니다. 구문이 해석되는 방식이므로 두 피연산자가 무엇인지는 중요하지 않습니다.
jonrsharpe

답변:


229

dis두 버전에 대해 생성 된 바이트 코드를 보는 데 사용 :

not ==

  4           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT           
             10 RETURN_VALUE   

!=

  4           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               3 (!=)
              9 RETURN_VALUE   

후자는 작업 수가 적으므로 약간 더 효율적일 수 있습니다.


그것은 지적했다 commments에 (감사, @Quincunx 당신이 가지고있는 곳) if foo != barif not foo == bar작업의 수는 정확히 같은, 그것은 단지 것을의 COMPARE_OP변화와 POP_JUMP_IF_TRUE전환 POP_JUMP_IF_FALSE:

not ==:

  2           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               2 (==)
              9 POP_JUMP_IF_TRUE        16

!=

  2           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               3 (!=)
              9 POP_JUMP_IF_FALSE       16

이 경우 각 비교에 필요한 작업량에 차이가 없다면 성능 차이가 전혀 없을 것입니다.


그러나, 두 가지 버전이 있습니다 항상 논리적으로 동일하지 않습니다 이의 구현에 따라 달라집니다로, __eq__그리고__ne__ . 문제 . 당 데이터 모델 문서 :

비교 연산자 사이에는 내재 된 관계가 없습니다. 진실x==y 그것이 x!=y거짓 임을 암시하지 않습니다 .

예를 들면 다음과 같습니다.

>>> class Dummy(object):
    def __eq__(self, other):
        return True
    def __ne__(self, other):
        return True


>>> not Dummy() == Dummy()
False
>>> Dummy() != Dummy()
True

마지막으로, 아마도 가장 중요하게는 : 일반적 으로 두 개가 논리적으로 동일한 경우 x != y보다 더 읽기 쉽습니다not x == y .


29
실제로 __eq__일치하지 않는 모든 클래스 __ne__는 플랫 아웃으로 나뉩니다.
Kevin

8
명령이 하나 이상있는 것이 항상 사실 은 아닙니다 not x == y. 코드를에 넣었을 때 if둘 다 동일한 수의 명령을 가지고 있음이 밝혀졌습니다. 하나는 POP_JUMP_IF_TRUE다른 것과 다른 것입니다 POP_JUMP_IF_FALSE(다른 것을 사용하는 것 이외 의 명령 의 유일한 차이점이었습니다 COMPARE_OP). ifs 없이 코드를 컴파일하면 얻은 것을 얻었습니다.
Justin

1
다른 예 ==!=상호 배타적이지는 구현 관련 SQL 형인 null값. SQL에 null반환하지 않는 true!=SQL 인터페이스 파이썬 구현이 또한 동일한 문제를 가질 수 있으므로, 임의의 다른 값과 비교.
Joe

not ==와 사이의 가능한 차이점을 언급하지 않았 으면 좋겠다 !=. 내 대답에서 가장 흥미로운 부분 인 것 같습니다! 나는이 경우에 거하는 장소라고 생각하지 않습니다, 그리고 그 이유 의미한다 때 - 예를 들어 볼 이유는 파이썬이 있는가 __ne__운영자 방법 대신에 단지를 __eq__?
jonrsharpe

29

@jonrsharpe는 무슨 일이 일어나고 있는지에 대한 훌륭한 설명을 가지고 있습니다. 나는 세 가지 옵션을 각각 10,000,000 번 실행할 때 시간의 차이를 보여 줄 것이라고 생각했습니다 (약간의 차이가 보일 정도로 충분합니다).

사용 된 코드 :

def a(x):
    if x != 'val':
        pass


def b(x):
    if not x == 'val':
        pass


def c(x):
    if x == 'val':
        pass
    else:
        pass


x = 1
for i in range(10000000):
    a(x)
    b(x)
    c(x)

그리고 cProfile 프로파일 러 결과 :

여기에 이미지 설명을 입력하십시오

우리는 ~ 0.7 %의 매우 작은 차이가 있음을 알 수 있습니다 if not x == 'val': 하고 if x != 'val':. 이들의,if x != 'val': 가장 빠릅니다.

그러나 가장 놀랍게도

if x == 'val':
        pass
    else:

실제로 가장 빠르며 if x != 'val':~ 0.3 % 가량 높습니다. 이것은 읽기 쉽지는 않지만 무시할만한 성능 향상을 원한다면이 경로를 따라갈 수 있습니다.


31
모든 사람들 이이 정보에 대해 행동 하지 않기를 바랍니다 . 0.3 % 개선 또는 심지어 10 % 개선을 위해 읽을 수없는 변경을하는 것은 좋은 생각이 아니며, 이런 종류의 개선은 소멸 될 가능성이 높습니다 (그리고 좋은 방식은 아님) . : 파이썬 런타임에 아주 약간의 변화
Malvolio

1
@Malvolio 또한 파이썬 에는 다른 구현 이 있습니다.
Cees Timmerman

6

첫 번째 파이썬에서 파이썬은 필요 이상으로 하나 이상의 연산을 실행해야합니다 (동일하지 않은 것을 확인하는 대신 그것이 동일한 지 여부를 확인해야하므로 하나의 연산이 더 필요합니다). 한 실행과의 차이점을 구분하는 것은 불가능하지만 여러 번 실행하면 두 번째 실행이 더 효율적입니다. 전반적으로 두 번째 것을 사용하지만 수학적으로는 동일합니다.


5
>>> from dis import dis
>>> dis(compile('not 10 == 20', '', 'exec'))
  1           0 LOAD_CONST               0 (10)
              3 LOAD_CONST               1 (20)
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT
             10 POP_TOP
             11 LOAD_CONST               2 (None)
             14 RETURN_VALUE
>>> dis(compile('10 != 20', '', 'exec'))
  1           0 LOAD_CONST               0 (10)
              3 LOAD_CONST               1 (20)
              6 COMPARE_OP               3 (!=)
              9 POP_TOP
             10 LOAD_CONST               2 (None)
             13 RETURN_VALUE

여기서 not x == y보다 더 많은 명령이 있음 을 알 수 있습니다 x != y. 따라서 수백만 번의 비교를 수행하지 않는 한 대부분의 경우 성능 차이가 매우 작으며 병목 현상의 원인이 아닐 수도 있습니다.


5

다른 답변은 대부분 제대로 질문에 대답하기 때문에 추가 노트, 클래스 만 정의하는 경우이다 __eq__()가 아니라 __ne__(), 다음 COMPARE_OP (!=)실행 __eq__()하고 부정. 당시 세 번째 옵션은 조금 더 효율적일 수 있지만, 속도를 필요로하는 경우에만 고려해야합니다. 빨리 이해하기 어렵 기 때문입니다.


3

그것은 당신이 그것을 읽는 방법에 관한 것입니다. not연산자가 역동적이므로 적용 할 수있는 이유

if not x == 'val':

그러나 !=더 나은 맥락에서 작동하는 것과 반대되는 연산자로 읽을 수 있습니다 ==.


3
" notoperator is dynamic"은 무엇을 의미 합니까?
jonrsharpe 2016 년

1
@jonrsharpe I 그가 "X 없음"호출된다는 것을 의미 생각 X .__ BOOL __ () 파이썬 3 - 2 개 파이썬 용도 제로 ] 볼 (결과를 되돌려 docs.python.org/3/reference/datamodel.html#object. __bool__ )
jdferreira 2016 년

1

위의 가독성 주석을 확장하고 싶습니다.

다시 한 번 나는 (성능이 중요하지 않은) 다른 문제를 무시하는 가독성에 전적으로 동의합니다.

제가 지적하고자하는 것은 뇌가 "음성"보다 "양성"을 더 빨리 해석한다는 것입니다. 예를 들어, "중지"대 "가지 마라"(단어 수의 차이로 인해 다소 시끄러운 예).

선택의 여지가 있습니다.

if a == b
    (do this)
else
    (do that)

기능적으로 동등한 것보다 바람직합니다.

if a != b
    (do that)
else
    (do this)

가독성 / 이해가 적 으면 더 많은 버그가 발생합니다. 아마도 초기 코딩에는 없지만 (당신만큼 똑똑하지는 않습니다!) 유지 보수가 변경됩니다 ...


1
뇌는 "음성"보다 "양성"을 더 빨리 해석합니다. 이것은 경험에서 비롯된 것입니까, 아니면 이것에 관한 연구를 읽었습니까? 나는 (이 작업) 또는 (그 작업)의 코드에 따라 이해하기 더 쉽다는 것을 알기 때문에 묻습니다.
lafferc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.