C.W.K.
Stream
Lesson 07 of 07 · published

Walrus / ternary 체이닝 / 작은 flow 트릭들

~18 min · walrus, assignment-expression, short-circuit, or-default

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

walrus 연산자 (3.8+) — :=

walrus 는 한 식 안에서 할당 + 평가. if (n := len(items)) > 10:n 바인딩하고 결과 테스트. 사용처 — if/while 안의 read-and-test, 컴프리헨션 안에서 중간 값 캡쳐, 체인 안에서 재계산 피하기. 작은 기능인데 패턴 보이기 시작하면 의외로 넓게 쓰여.

or 디폴트 / and guard

x or defaultx 가 truthy 면 x, 아니면 default. 좋음 — name = user_input or "anonymous". 조심 — 이건 *모든 falsy 값* 을 같이 취급. 0 이나 "" 가 합법적 사용자 입력이고 *없을 때만* fallback 하고 싶으면 x if x is not None else default 또는 명시적 체크.

다중 return path vs 단일 return

일부 스타일 가이드는 "함수당 return 하나" 외쳐. Python 은 그렇지 않아. 엣지 케이스 처리하는 early return ("guard clause" 패턴) 이 모든 걸 if 안에 중첩하는 것보다 보통 더 깔끔. 깊은 들여쓰기는 로직이 진짜 그걸 요구할 때 아껴 둬.

pass / ... / raise NotImplementedError

placeholder 세 가지 — pass (아무것도 안 함, 문 단위), ... (Ellipsis 리터럴, 문으로 받아들여짐, stub 파일과 추상 메서드에 idiomatic), raise NotImplementedError (서브클래스가 반드시 override 해야 한다는 신호). 선택은 *의도* 를 독자한테 말해 — no-op, stub, 미완성 메서드.

Pythonic Way: 함수가 "이거 아니면, 저거 아니면, 또 그거 아니면" 체크하고 다 깨끗할 때만 진행한다 — 부정 체크들을 early return 으로. 남은 코드는 happy path 에 들여쓰기 없이 살아. "guard clause" 패턴, validation 많은 코드의 가장 읽기 좋은 모양.

Code

walrus — if/while 안의 read-and-test·python
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# walrus 없이
n = len(items)
if n > 5:
    print(f"big list ({n})")

# walrus 로 — 한 줄
if (n := len(items)) > 5:
    print(f"big list ({n})")

# while 안에서 — 청크 단위 읽기
import io
stream = io.BytesIO(b"hello world this is some data")
while chunk := stream.read(8):
    print(chunk)
# b'hello wo'
# b'rld this'
# b' is some'
# b' data'
컴프리헨션 안의 walrus·python
values = [10, 20, 30, 40, 50]

# walrus 없이 — 비싼 부분 매번 재계산
result = [v*v for v in values if v*v > 500]

# walrus 로 — 한 번 계산, 결과에 이름
result = [sq for v in values if (sq := v*v) > 500]
print(result)              # [900, 1600, 2500]
or 디폴트와 falsy 함정·python
# or 디폴트는 0/빈값 = 없음 일 때 좋음
user_input = ""
name = user_input or "anonymous"
print(name)                # 'anonymous'

# 근데 0 이 유효 값이면 or 디폴트 잘못됨
def get_quantity(x):
    return x or 1          # 잘못됨: 0 도 1 로 변함

print(get_quantity(0))     # 1   <- 버그!
print(get_quantity(None))  # 1

# 맞음 — 명시적 None 체크
def get_quantity_v2(x):
    return x if x is not None else 1

print(get_quantity_v2(0))  # 0
print(get_quantity_v2(None))  # 1
Guard clause — 들여쓰기 평탄화·python
# 중첩 if — 안 읽힘
def process_v1(user, msg):
    if user is not None:
        if user.is_active:
            if msg:
                if len(msg) <= 280:
                    return f"sending: {msg}"
                else:
                    return "too long"
            else:
                return "empty"
        else:
            return "inactive"
    else:
        return "no user"

# Guard clause — 평탄한 happy path
def process_v2(user, msg):
    if user is None:
        return "no user"
    if not user.is_active:
        return "inactive"
    if not msg:
        return "empty"
    if len(msg) > 280:
        return "too long"
    return f"sending: {msg}"
pass / ... / NotImplementedError — 세 placeholder·python
# 1. pass — 명시적 no-op
def nothing():
    pass

# 2. ... — Ellipsis 가 stub 으로. .pyi stub 파일과 추상 메서드에 흔함.
def stub():
    ...

# 3. NotImplementedError — 서브클래스가 *반드시* override
class Base:
    def required(self):
        raise NotImplementedError("subclass must override")

External links

Exercise

fetch_or_compute(cache, key, compute_fn) 작성 — cache[key] 있으면 반환, 없으면 compute_fn() 호출, 결과를 cache[key] 에 저장하고 반환. walrus 를 최소 한 번 써. 그 다음 validate_email(s) 의 guard clause 버전 — None, 빈 문자열, @ 없음, @ 두 개 이상, @ 뒤에 . 없음 중 하나라도면 "invalid", 아니면 "ok". 둘 다 최소 4 입력 테스트.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.