왈러스 연산자(`:=`)로 "값 꺼내고 또 꺼내는" 중복 없애기

Tasker_Jang·2026년 4월 19일

🤔 이게 왜 문제인가

딕셔너리에서 값을 꺼내 있으면 쓰고, 없으면 다른 처리를 하는 코드, 정말 자주 씁니다. 그런데 이걸 평범하게 쓰면 같은 키를 두 번 조회하거나, 같은 값을 두 번 변수에 담게 돼요.

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 파이프라인처럼 "일단 꺼내고, 값이 있을 때만 처리"가 반복되는 코드에서 특히 체감이 큽니다.

profile
ML Engineer 🧠 | AI 모델 개발과 최적화 경험을 기록하며 성장하는 개발자 🚀 The light that burns twice as bright burns half as long ✨

0개의 댓글