Conditional Expression
Conditional Expression이란?
파이썬 조건부 표현식이라 하고, 조건에 따라 값을 하나 선택하는 문법이다.
C에서 삼항연산자와 매우 비슷하다.
기본 문법은 다음과 같다.
값1 if 조건 else 값2
조건이 참이면 값1 이고, 조건이 거짓이면 값2이다.
다음 예시를 봐보자.
age = 20
result = "성인" if age >= 20 else "미성년자"
age에는 20이 들어가있고, result는 조건부 표현식으로 값이 결정됨을 알 수 있다.
우선, age가 20이상이면 “성인”을 result에 넣고, 그게 아니라면 “미성년자”를 넣는 것이다.
if문과 같은 if문과 똑같은 역할을 하는 것이다.
왜 if문을 사용하지 않고 조건부 표현식을 사용할 때도 있는가?
우선 성능에 대한 오해부터 바로 잡고 가겠다.
if문 대신 조건부 표현식을 쓴다고 성능이 좋아지거나, 인터프리터가 특별히 더 쉽게 해석할 수 있다고 볼 수 없다.
코드 양으로 보면 조건부 표현식이 if문보다 더 적으니까 성능도 더 빠르겠지 라는 오해가 있다.
그럼 왜 성능의 차이가 거의 없는 것인가?
첫 번째로, 둘 다 결국 조건을 검사하고 점프하는 과정이다.
조건부 표현식과 if문은 내부적으로 다음과 같은 흐름을 가진다.
조건을 평가한다.
조건이 참인지 거짓인지 판단한다.
참이면 A쪽으로 간다.
거짓이면 B쪽으로 간다.
선택된 값을 사용한다.
여기서, 둘 다 조건검사와 분기 점프가 필요하다는 점에서 명령어 실행 관점에서는 성능 차이가 크게 나지 않을 수밖에 없다.
두 번째로, 조건부 표현식이 바이트코드를 더 짧게 만들 수는 있지만 그렇다고 해서 성능의 차이가 난다라고 보기에는 어렵다.
예를 들어 이런 구조를 먼저 봐보자.
x = a if cond else b
조건부 표현식은 x에 저장이 한 번만 나오는 구조가 될 수 있다.
반면, 일반 if문은
if cond:
x = a
else:
x = b
각 분기마다 x에 저장이 들어가 있을 수 있다.
그래서 경우에 따라 조건부 표현식이 바이트코드 수가 약간 적을 가능성은 있다.
하지만! 중요한 것은 바이트코드 수가 조금 적다고 해서 실제 프로그램 성능이 빨라졌다라고 보긴 어렵다.
다음과 같은 상황에서 성능 차이가 발생할 수 있기 때문에 항상 성립한다고 보기에는 어려운 것이다.
어떤 객체를 다루는가
함수를 호출하는가
메모리에 접근하는가
타입 검사가 필요한가
분기 예측이 어떻게 되는가
CPU 캐시 상태가 어떤가
파이썬 버전이 무엇인가
결국, 조건부 표현식과 if문의 바이트코드 차이는 전체 프로그램 관점에서 거의 잡음 수준이라고 보면 된다.
세 번째로, 파이썬에는 인터프리터 오버헤드가 더 크다.
조건부 표현식과 if문의 차이는 거의 잡음 수준이라고 보면 되는데, 그래도 조건부 표현식이 더 유리한 것 아니냐 라고 생각할 수 있다. 물론, 이론적으로는 아주 조금 유리할 수 있다.
하지만, Python은 코드를 바로 실행하는 것이 아니라 다음과 같은 단계를 거친다.
파이썬 소스 코드
↓
바이트코드로 변환
↓
파이썬 인터프리터가 바이트코드를 하나씩 해석하며 실행
↓
실제 CPU 명령 실행
여기서 중요한 것은 인터프리터가 중간에서 계속 해석 작업을 하는 오버헤드가 발생한다는 것이다.
파이썬에서는 바이트코드 하나를 실행하는 것 자체가 많은 일들을 포함하기 때문에, 바이트코드 1~2개 줄어드는 차이는 대부분의 상황에서 전체 시간에 비해 너무 작다.
결국 중요한 것은 분기 문법이 아니라 분기 안에서의 작업이다.
조건부 표현식이냐 if문이냐 보다 훨씬 중요한 것은 분기 내부에서 무엇을 실행하느냐가 중요하다는 것을 망각하면 안 된다.
진짜 최적화해야 하는 것은 다음과 같다.
x = heavy_function() if cond else 0
heavy_function()이 꼭 필요한가?
결과를 캐싱할 수 있는가?
반복문 안에서 계속 호출되고 있는가?
입력 크기가 너무 큰가?
라이브러리 함수로 대체할 수 있는가?
계속 말하지만, 어떤 방식을 쓰느냐가 아니라 분기 안에서 어떤 식으로 최적화를 할 수 있을지를 고민해야 한다.
어떨 때 조건부 표현식을 사용하고, if문을 사용하는가?
우선 가독성을 위한 것이 가장 크다.
만약, 조건에 따라 변수에 값 하나를 넣는 상황이라면 if문으로 여러 줄을 나누는 것보다 한 줄로 표현하는 것이 더 가독성이 좋고 직관적이다.
다음 예시를 보면 확연히 체감할 수 있을 것이다.
status = "성공" if ret else "실패"
if ret:
status = "성공"
else:
status = "실패"
이제 역으로 생각해보면, if문은 실행할 코드가 여러 줄일 때 보통 사용한다고 보면 된다.
이것 또한 비교를 해보겠다.
result = "A" if score >= 90 and attendance >= 80 and submitted else "B"
if score >= 90 and attendance >= 80 and submitted:
result = "A"
else:
result = "B"
확실히 코드가 길어지게 되면 조건부 표현식보다 if문이 더 직관적이다.
항상 코드는 성능 측면도 중요하지만, 얼마나 코드를 가독성 있고 직관적으로 짜냐가 더 중요한 것 같다.