<질문>
다음 두 코드 줄의 차이점은 무엇입니까?
if not x == 'val':
그리고
if x != 'val':
하나가 다른 것보다 더 효율적입니까?
사용하면 더 좋겠죠?
if x == 'val':
pass
else:
<답변1>
사용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
후자는 작업이 적으므로 약간 더 효율적일 수 있습니다.
지적했다in the commments(감사해요,@Quincunx) 당신이 있는 곳if foo != bar
대if 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__
문제의 객체에 대해. 당the data model documentation:
비교 연산자 사이에는 암시적인 관계가 없습니다. 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
보다 훨씬 읽기 쉽습니다..
<답변2>
@jonrsharpe는 진행 상황에 대한 훌륭한 설명을 제공합니다. 3가지 옵션을 각각 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%만큼 이깁니다. 가독성이 좋지는 않지만 무시할 정도의 성능 향상을 원한다면 이 방법을 사용할 수 있습니다.
<답변3>
첫 번째에서 Python은 필요한 것보다 하나 더 많은 작업을 실행해야 합니다(단순히 같지 않음을 확인하는 대신 동일하지 않은지 확인해야 하므로 작업을 하나 더 수행해야 함). 한 번의 실행과 차이점을 구분하는 것은 불가능하지만 여러 번 실행하면 두 번째 실행이 더 효율적입니다. 전반적으로 두 번째 것을 사용하지만 수학적으로는 동일합니다.
<답변4>
다른 답변이 귀하의 질문에 대부분 올바르게 답변했기 때문에 추가 참고 사항은 클래스가__eq__()
그리고 아니다__ne__()
, 다음 당신의COMPARE_OP (!=)
달릴 것이다__eq__()
그리고 그것을 부정하십시오. 이때 세 번째 옵션이 조금 더 효율적일 수 있지만 빠르게 이해하기 어렵기 때문에 속도가 필요한 경우에만 고려해야 합니다.
<답변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
. 따라서 수백만 건의 비교를 수행하지 않는 한 대부분의 경우 성능 차이는 매우 작으며 심지어 이것이 병목 현상의 원인이 되지 않을 가능성이 높습니다.
<답변6>
그것은 그것을 읽는 당신의 방법에 관한 것입니다.not
연산자는 동적이므로 다음에 적용할 수 있습니다.
if not x == 'val':
하지만!=
무엇과 반대되는 연산자로 더 나은 맥락에서 읽을 수 있습니다.==
하다.
<답변7>
위의 가독성 설명을 확장하고 싶습니다.
다시 말하지만, 다른 (성능에 중요하지 않은) 문제를 무시하는 가독성에 전적으로 동의합니다.
제가 지적하고 싶은 것은 뇌가 "부정적"보다 "긍정적"을 더 빨리 해석한다는 것입니다. 예: "그만" 대 "가지마"(단어 수의 차이로 인한 다소 형편없는 예).
그래서 주어진 선택:
if a == b
(do this)
else
(do that)
기능적으로 동등한 것보다 바람직합니다.
if a != b
(do that)
else
(do this)
가독성/이해력이 낮으면 더 많은 버그가 발생합니다. 아마도 초기 코딩에서는 아니지만 (당신만큼 똑똑하지는 않습니다!) 유지 관리 변경 사항...
'개발 > Python' 카테고리의 다른 글
[파이썬] 문자열의 마지막 3개 문자 제거 (0) | 2022.12.07 |
---|---|
[파이썬] logging을 비활성화하는 방법은? (0) | 2022.12.07 |
[파이썬] 두 개의 데이터 프레임을 결합하는 방법? (0) | 2022.12.07 |
[파이썬] pandas 데이터 프레임 인덱스에 값이 있는지 확인하는 방법 (0) | 2022.12.07 |