왈러스 연산자 vs 일반 대입

Python 3.8에 들어온 := 연산자는 표현식 안에서 대입을 합니다. 일반 대입과 무엇이 다른지, 어디서 코드를 간결하게 만들고 어디서 오히려 해치는지 정리합니다.

· 7 min read · PALDYN Team

지난 글에서 복사의 함정을 정리했다면, 이번 글은 비교적 가벼운 주제 하나를 다룬다. Python 3.8에서 들어온 왈러스 연산자(walrus operator) :=다. 생긴 모양이 바다코끼리(walrus)의 눈과 엄니를 닮았다고 해서 붙은 별명이고, 정식 명칭은 할당 표현식(assignment expression)이다. 이 작은 연산자 하나가 일반 대입 =과 어떻게 다른지, 그리고 언제 쓰는 게 좋고 언제 자제하는 게 좋은지 살펴본다.

대입을 표현식으로

핵심부터 말하면, 일반 대입 =(statement)이고 왈러스 :=표현식(expression)이다. 문은 그 자체로 값을 갖지 않아서 다른 표현식의 일부로 끼워 넣을 수 없다. 그래서 다음은 문법 오류다.

if (n = len(data)) > 10:   # SyntaxError — = 는 표현식이 아니다
    ...

반면 왈러스는 “이름에 값을 대입하면서, 그 값을 표현식의 결과로도 내놓는다.” 덕분에 ifwhile의 조건 안에서 대입과 검사를 한 번에 할 수 있다.

if (n := len(data)) > 10:   # n에 길이를 담으면서 동시에 10과 비교
    print(f"{n}개는 너무 많습니다")

여기서 n은 대입되고, 그 값(len(data))이 곧바로 > 10 비교에 쓰인다. 대입과 사용을 한 자리에 모은 것이 왈러스의 전부다.

가장 잘 어울리는 자리 — while 루프

왈러스가 가장 빛나는 곳은 “값을 읽어서, 그 값이 어떤 조건이면 계속하는” 반복문이다. 왈러스가 없던 시절에는 같은 읽기 코드를 루프 앞과 루프 끝에 두 번 적어야 했다.

# 왈러스 없이 — readline()을 두 번 적는다
line = f.readline()
while line:
    process(line)
    line = f.readline()

# 왈러스로 — 대입과 조건을 한 줄에
while (line := f.readline()):
    process(line)

읽는 코드가 한 곳으로 모이면서 중복이 사라지고, “읽은 게 있는 동안 처리한다”는 의도가 한 줄에 또렷해진다. 이처럼 읽기·계산과 그 결과의 검사가 짝을 이루는 패턴이 왈러스의 가장 자연스러운 용도다.

대입하면서 동시에 검사하기

컴프리헨션에서 계산 재사용

또 다른 좋은 자리는 컴프리헨션이다. 같은 계산을 조건과 결과 양쪽에서 써야 할 때, 왈러스가 없으면 그 비싼 계산을 두 번 적게 된다.

# 왈러스 없이 — f(x)를 두 번 호출한다
result = [f(x) for x in data if f(x) is not None]

# 왈러스로 — 한 번만 계산해서 재사용
result = [y for x in data if (y := f(x)) is not None]

아래쪽은 f(x)를 단 한 번 호출해 y에 담고, 그 y를 조건 검사와 결과 양쪽에서 함께 쓴다. 계산이 무겁거나 부작용이 있는 함수일수록 이 중복 제거의 가치가 크다.

자제해야 할 때

좋은 도구도 남용하면 독이 된다. 왈러스가 코드를 오히려 읽기 어렵게 만드는 경우들이 있다.

가장 흔한 오용은 그냥 한 줄짜리 평범한 대입을 굳이 왈러스로 바꾸는 것이다. 표현식 안에 끼워 넣을 이유가 없는데 :=을 쓰면 괄호만 늘고 가독성은 떨어진다.

# 나쁨 — 그냥 대입이면 되는데 표현식으로 위장
print(total := a + b)

# 좋음 — 의도가 분명한 평범한 대입
total = a + b
print(total)

또 하나는 한 표현식에 왈러스를 여러 개 욱여넣거나, 함수 인자 한가운데서 깜짝 대입을 하는 것이다. 읽는 사람이 “여기서 변수가 언제 어떤 값으로 생겼지?”를 추적하게 만들면, 간결함을 얻은 대가로 명확함을 잃는다.

왈러스가 빛날 때 vs 흐릴 때

판단 기준은 예전 글에서 본 그 한 줄로 돌아간다 — “읽기 쉬움이 우선한다.” 왈러스가 중복을 없애고 의도를 또렷하게 하면 좋은 사용이고, 단지 줄 수를 줄이려고 흐름을 숨기면 나쁜 사용이다.

정리

왈러스 연산자 :=은 일반 대입 =과 달리 표현식이어서, 값을 대입하면서 동시에 그 값을 조건 검사나 다른 계산에 쓸 수 있다. while (line := f.readline()):처럼 읽기와 검사가 짝을 이루는 반복문, 그리고 컴프리헨션에서 무거운 계산을 한 번만 하고 재사용하는 경우에 특히 잘 어울린다. 반대로 평범한 대입을 굳이 표현식으로 위장하거나 한 식에 여러 번 끼워 넣어 흐름을 숨기는 것은 피해야 한다. 변수의 범위를 좁게 유지하면서 중복을 없애는 도구로 쓸 때, 왈러스는 코드를 더 파이썬답게 만든다.

언어의 본질과 설치에서 시작해 자료형과 제어문, 함수와 클래스, 모듈과 패키지, 파일과 예외, 이터레이터와 제너레이터, 동시성과 타입 힌트, 패키징과 테스트, 그리고 실무 라이브러리와 보안·함정까지 — 파이썬을 다루는 데 필요한 지형을 한 바퀴 돌았다. 각 주제의 공통된 교훈은 하나였다. “파이썬이 무엇을, 언제, 어떻게 처리하는가”를 정확히 이해하면, 대부분의 혼란은 예측 가능한 동작으로 바뀐다는 것이다. 그동안 함께해 주셔서 감사하다.


지난 글: 얕은 복사 vs 깊은 복사


읽어주셔서 감사합니다. 😊