다른 언어를 다뤄본 사람이라도 Python(파이썬) 연산자에서 몇 군데는 헷갈릴 수 있다. 대표적으로 /와 //의 차이, ==와 is의 차이가 그렇다. 이 글에서는 파이썬의 연산자 종류를 실제 코드 실행 결과와 함께 정리한다.
산술 연산자
>>> 7 + 2, 7 - 2, 7 * 2
(9, 5, 14)
>>> 7 / 2
3.5
>>> 7 // 2
3
>>> 7 % 2
1
>>> 7 ** 2
49
/는 몫과 나머지 상관없이 항상 float를 반환하고, 몫만 정수로 필요하면 //(floor division)를 쓴다. 음수에서는 이 //가 0 방향이 아니라 더 작은 값(음의 무한대) 방향으로 내림한다는 점을 주의해야 한다.
>>> -7 // 2
-4
C 계열 언어의 정수 나눗셈(0 방향 내림)과 다르게 동작하는 부분이라, 음수를 다루는 계산식에서는 결과를 한 번 더 확인하는 게 좋다.
비교 연산자
>>> a = 5
>>> a == 5, a != 3, a > 3, a <= 5
(True, True, True, True)
>>> 1 < a < 10
True
1 < a < 10처럼 비교를 연쇄해서 쓸 수 있는 게 파이썬의 특징이다. 이 식은 1 < a and a < 10과 동일하게 동작한다.
논리 연산자
&&, ||, ! 대신 and, or, not 키워드를 쓴다. 그리고 이 연산자들은 True/False만 돌려주는 게 아니라 피연산자 자체를 그대로 반환한다.
>>> 0 or "기본값"
'기본값'
>>> "첫값" and "둘째값"
'둘째값'
왼쪽 값만으로 결과가 정해지면 오른쪽은 아예 평가하지 않는 단락 평가(short-circuit) 방식이라, x or default 형태로 기본값을 지정하는 패턴이 자주 쓰인다.
대입 연산자
= 외에 산술·비트 연산과 대입을 한 번에 처리하는 복합 대입 연산자(+=, -=, *=, /=, //=, %=, **=, &=, |=, ^=, >>=, <<=)를 지원한다.
>>> a = 5
>>> a += 3
>>> a
8
비트 연산자
>>> 5 & 3, 5 | 2, 5 ^ 1, ~5, 5 << 1, 5 >> 1
(1, 7, 4, -6, 10, 2)
~5가 -6인 이유는 파이썬 정수가 2의 보수 표현을 따르기 때문이다. ~x는 항상 -(x + 1)과 같은 값이 된다.
멤버십 연산자
>>> nums = [1, 2, 3]
>>> 3 in nums, 3 not in nums
(True, False)
>>> "py" in "python"
True
in/not in은 리스트뿐 아니라 튜플, 문자열, 딕셔너리(키 기준) 등 대부분의 컨테이너 타입에 똑같이 쓸 수 있다.
식별 연산자 (is / is not)
is는 값이 같은지가 아니라 같은 객체(동일한 id)인지를 비교한다. ==와 가장 많이 헷갈리는 부분이다.
>>> x = [1, 2]
>>> y = [1, 2]
>>> x == y, x is y, x is x
(True, False, True)
x와 y는 내용이 같아서 ==는 True지만, 서로 다른 리스트 객체라 is는 False다. None 비교는 관례적으로 x == None 대신 x is None을 쓴다.
주의사항
/는 피연산자가 둘 다 정수여도 항상 float를 반환한다. 정수 몫이 필요하면//를 쓴다.- 값이 같은지 확인할 땐
==, 같은 객체인지 확인할 땐is. 작은 정수(-5~256)나 짧은 문자열은 인터프리터가 캐싱해서is비교가 우연히True가 나올 수 있으니, 값 비교 목적으로는is를 쓰지 않는다. and/or는 불리언이 아니라 피연산자 자체를 반환한다. 진짜True/False가 필요하면bool(...)로 감싼다.
마무리
파이썬 연산자 자체는 어렵지 않지만, /와 //의 반환 타입 차이, ==와 is의 의미 차이, and/or의 단락 평가는 실수가 잦은 지점이다. 특히 is는 값이 아니라 객체 동일성을 비교한다는 점을 항상 기억해두는 게 좋다.