Python의 내장 숫자 비교에서 a < next_value() < b는 가운데 식 next_value()를 한 번만 평가합니다. 첫 비교가 참이면 그 값을 오른쪽 상수와 비교하고, 첫 비교가 거짓이면 두 번째 비교는 건너뜁니다.

따라서 호출 횟수와 비교 횟수를 따로 세어야 합니다. 사용자 정의 비교 연산자가 참·거짓 대신 객체를 돌려주는 특수한 상황은 이 설명의 범위에서 제외합니다.

연쇄 비교는 중간 값을 한 번만 사용합니다

Python에서 a < b < c는 수학 표기처럼 세 값의 순서를 연결해 검사합니다. 가운데 표현식은 반복 계산되지 않고 한 번만 평가됩니다. 왼쪽 비교가 참일 때만 다음 비교가 진행되며, 결과는 두 비교가 모두 참인지에 따라 정해집니다. 개념상 (a < b) and (b < c)와 비슷하지만, 가운데 표현식이 두 번 계산되지 않는 점이 중요합니다. 이 글은 int와 기본 비교를 대상으로 하며, 사용자 정의 객체가 비교 결과로 특별한 객체를 반환하는 경우는 다루지 않습니다.

호출 수와 두 번째 비교 여부를 분리합니다

교육용 예시이며 공식 기출이나 유료 카드 문항이 아닙니다.
calls = 0
def next_value():
    global calls
    calls += 1
    return 5

result = 2 < next_value() < 9
print(result, calls)
내장 정수 비교로 추적한 결과
단계계산상태
1next_value() 실행호출 횟수 1, 값 5
22 < 5참
35 < 9평가, 참
4연쇄 비교 결과True, 호출 횟수 1

next_value()를 먼저 한 번 계산해 5를 얻습니다. 2 < 5가 참이므로 다음 비교 5 < 9도 진행합니다. 결과는 True이고 함수 호출은 한 번입니다. 함수가 0을 반환하도록 바꾸면 첫 비교 2 < 0이 거짓이 되어 뒤쪽 비교는 실행되지 않지만, 가운데 함수 자체는 이미 한 번 실행됐습니다. 따라서 ‘우항 비교 생략’과 ‘중간 식 호출 횟수’는 같은 숫자를 묻지 않습니다.

추적표에는 식 평가와 비교 결과를 별도로 적습니다

  1. 연쇄식의 피연산자를 왼쪽부터 적습니다.
  2. 함수 호출이나 부수 효과가 있는 중간 표현식을 한 번만 실행해 값을 기록합니다.
  3. 첫 비교 결과를 구합니다.
  4. 첫 결과가 참일 때만 다음 비교를 기록하고, 거짓이면 연쇄식을 종료합니다.
  5. 최종 Boolean 결과와 함수 호출 횟수를 따로 답합니다.

비교식을 AND로 풀어 쓰면서 함수를 복사하지 않습니다

초심자는 a < f() < b를 (a < f()) and (f() < b)라고 다시 써서 호출이 두 번 일어난다고 계산하곤 합니다. 이런 변환은 부수 효과가 있는 가운데 식에서 원래 연쇄 비교와 다르게 동작합니다. 직접 만든 클래스에서는 비교 연산자가 Boolean이 아닌 객체를 돌려줄 수 있으므로, 단순한 and 설명만으로 모든 상황을 덮을 수는 없습니다. 시험 예제의 자료형과 함수가 명확하다면 해당 조건에 한정해 평가 횟수를 추적하세요.

연쇄 비교는 가운데 식이 한 번만 계산된다는 점에서 두 개의 비교를 무심코 복사하는 것과 다릅니다. 가운데 식이 함수 호출이면 결과를 임시 변수처럼 기록해 두 비교에 같은 값을 사용합니다. 첫 비교가 참일 때만 다음 비교를 하므로 오른쪽의 부수 효과도 조건에 따라 생략됩니다. 식을 두 비교로 풀어 쓰면서 함수 호출을 각각 복사하면 호출 횟수와 프로그램 결과가 달라질 수 있습니다. 이 글은 기본 정수의 순서 비교를 대상으로 합니다. 사용자 정의 비교 메서드가 특수한 결과 객체를 돌려주는 상황까지 단순한 참·거짓 식으로 넓혀 설명하지 않습니다.

중간 값이 첫 비교에서 경계와 같아 거짓이 되는 경우를 한 번 더 연습하면 단락 흐름이 선명해집니다. 가운데 함수는 그 순간 이미 실행되었으므로 호출 횟수는 1입니다. 그러나 다음 비교에 도달하지 않기 때문에 그 뒤에 놓인 표현식의 호출 수는 0입니다. 한 줄에 함수가 두 번 적혀 있지 않더라도 연쇄 연산자가 평가 순서를 규정한다는 점을 기억하세요. 식을 왼쪽부터 해석하고 이미 구한 중간 값을 다시 호출로 바꾸지 마세요.

정답을 가리고 확인해 보세요

이 글을 위해 만든 학습 예시이며 공식 기출문제나 판매 카드의 인용이 아닙니다.

2 < f() < 9에서 내장 정수를 반환하는 f가 0을 반환하면 f 호출 수와 비교 결과는 무엇인가요?

정답과 해설 확인f는 한 번 호출되고 연쇄 비교 결과는 False입니다. 첫 비교가 거짓이므로 두 번째 비교는 하지 않습니다.

Python 3.12 언어 레퍼런스는 중간 표현식을 한 번만 평가하며 왼쪽부터 단락하는 연쇄 비교 의미를 규정합니다.