딕셔너리에서 값을 꺼내 있으면 쓰고, 없으면 다른 처리를 하는 코드, 정말 자주 씁니다. 그런데 이걸 평범하게 쓰면 같은 키를 두 번 조회하거나, 같은 값을 두 번 변수에 담게 돼요.
if fruit_counts.get('apple'):
count = fruit_counts.get('apple') # 똑같은 호출 두 번
...
이런 중복은 성능 문제라기보다 가독성과 실수의 문제입니다. 한쪽은 apple, 한쪽은 apples로 오타 나면? 로직 전체가 꼬이죠. Python 3.8부터 등장한 왈러스 연산자 :=(공식 명칭은 대입식, assignment expression)는 이런 "값을 할당하면서 동시에 조건으로 쓰고 싶다"는 욕구를 정확히 해결합니다.
fruit_counts = {'apple': 10, 'banana': 8, 'lemon': 5}
# 같은 키를 두 번 조회
count = fruit_counts.get('apple', 0)
if count:
make_cider(count)
else:
out_of_stock()
# while 루프에서 "일단 값을 꺼내고, 소진될 때까지 반복"도 지저분해짐
bucket = next_bucket()
while bucket:
process(bucket)
bucket = next_bucket() # 두 번 호출, 초기화 라인과 갱신 라인이 따로 놂
count = ... 한 줄이 분기 바깥에서 혼자 외롭게 있으니 분기 조건의 의도가 한눈에 안 읽힙니다. while 루프는 더 심각해요. 루프 시작 전과 끝에서 같은 함수를 호출해야 해서 중복이 필연입니다. 파이썬에는 do/while이 없어서 예전부터 이 패턴이 아쉬웠어요.
# 대입과 조건 체크를 한 번에
if count := fruit_counts.get('apple', 0):
make_cider(count)
else:
out_of_stock()
# do/while 흉내 — 한 번만 호출하고 자연스럽게 반복
while bucket := next_bucket():
process(bucket)
# switch/case 흉내 (파이썬 3.10+에는 match 문도 있지만, 대입식도 충분히 깔끔)
if (kind := classify(item)) == 'fruit':
handle_fruit(item)
elif kind == 'veggie':
handle_veggie(item)
else:
handle_unknown(item, kind)
count := ...는 "count에 값을 넣으면서 그 값을 식으로도 사용한다"는 뜻입니다. 키 조회는 한 번만 일어나고, count 변수는 이후 분기에서 자연스럽게 쓸 수 있어요. while 루프에서는 "값이 있으면 반복, 없으면 탈출"이라는 의도가 한 줄로 표현됩니다. 단, 더 큰 식의 일부로 쓸 땐 괄호로 감싸야 합니다(if (kind := ...) == 'fruit':). 안 그러면 SyntaxError가 나요.
:=는 값을 대입하면서 그 값을 식으로도 사용하는 문법입니다(Python 3.8+).while value := next_item(): 형태로 파이썬에 없는 do/while을 자연스럽게 흉내 낼 수 있습니다.if ... == ..., while ... < ... 같은)일 때는 반드시 괄호로 감싸세요.파일/네트워크 스트림을 청크 단위로 읽는 루프에서 거의 교과서처럼 쓰입니다. while chunk := stream.read(8192): process(chunk) 한 줄이면 "EOF까지 읽어서 처리"가 완성돼요. 예전엔 chunk = stream.read(...)를 루프 밖과 안에 두 번 써야 했죠. 또 리스트 컴프리헨션 안에서 계산 비용이 큰 값을 재사용할 때도 유용합니다. [y for x in data if (y := expensive(x)) is not None]처럼 쓰면 expensive(x)를 한 번만 호출하면서 필터링과 변환을 동시에 할 수 있어요. 로그 파서, ETL 파이프라인처럼 "일단 꺼내고, 값이 있을 때만 처리"가 반복되는 코드에서 특히 체감이 큽니다.