Language/Python

[Effective Python] Better way 10. 대입식을 사용해 반복을 피하라

dashwood 2022. 8. 23. 21:56

Better way 10. 대입식을 사용해 반복을 피하라

 

fresh_fruit = {
    'apple': 10,
    'banana': 8,
    'lemon': 5,
}

def make_lemonade(count):
    print(f'Making {count} lemons into lemonade')

def out_of_stock():
    print('Out of stock!')

count = fresh_fruit.get('lemon', 0)
if count:
    make_lemonade(count)
else:
    out_of_stock()

위 코드에서 count 변수는 if 문의 첫 번째 블록 안에서만 쓰인다. if 앞에서 count를 정의하면 else 블록이나 그 이후의 코드에서 count 변수에 접근해야 할 필요가 있는 것 처럼 보이기 때문에 실제보다 변수가 중요해 보인다.

 

대입 연산자는 우선 count 변수에 값을 대입하고, if 문의 맥락에서 대입된 값을 평가해 프로그램 흐름을 어떻게 제어할 지 판단한다. 이런 두 단계의 동작(대입 후 평가)이 왈러스 연산자의 핵심!

if count := fresh_fruit.get('레몬', 0):
	make_lemonade(count)
else:
	out_of_stock()

 

 

바나나 슬라이스가 최소 두 개는 필요하고, 슬라이스가 부족하면 OutOfBananas 예외를 발생시켜야 한다면 다음과 같이 작성할 수 있다.

pieces = 0
if (count := fresh_fruit.get('바나나', 0)) >= 2:
	pieces = slice_bananas(count)
else:
	pieces = 0
    
try:
	smoothies = make_smoothies(pieces)
except OutOfBanans:
	out_of_stock()

 

 

파이썬에서 switch/case 문이나 do/while 루프를 쓸 수 없지만, 대입식을 사용하면 이런 기능을 깔끔하게 흉내낼 수 있다.

count = fresh_fruit.get('banana', 0)
if count >= 2:
    pieces = slice_bananas(count)
    to_enjoy = make_smoothies(pieces)
else:
    count = fresh_fruit.get('apple', 0)
    if count >= 4:
        to_enjoy = make_cider(count)
    else:
        count = fresh_fruit.get('lemon', 0)
        if count:
            to_enjoy = make_lemonade(count)
        else:
            to_enjoy = 'Nothing'


# switch/case 처럼 왈러스문을 사용하는 예
if (count := fresh_fruit.get('banana', 0)) >= 2:
    pieces = slice_bananas(count)
    to_enjoy = make_smoothies(pieces)
elif (count := fresh_fruit.get('apple', 0)) >= 4:
    to_enjoy = make_cider(count)
elif count := fresh_fruit.get('lemon', 0):
    to_enjoy = make_lemonade(count)
else:
    to_enjoy = 'Nothing'

 

 

FRUIT_TO_PICK = [
    {'apple': 1, 'banana': 3},
    {'lemon': 2, 'lime': 5},
    {'orange': 3, 'melon': 2},
]

def pick_fruit():
    if FRUIT_TO_PICK:
        return FRUIT_TO_PICK.pop(0)
    else:
        return []

def make_juice(fruit, count):
    return [(fruit, count)]


bottles = []
while True:                     # 무한 루프
    fresh_fruit = pick_fruit()
    if not fresh_fruit:         # 중간에서 끝내기
        break
    for fruit, count in fresh_fruit.items():
        batch = make_juice(fruit, count)
        bottles.extend(batch)


# 왈러스를 사용하는 예
bottles = []
while fresh_fruit := pick_fruit():
    for fruit, count in fresh_fruit.items():
        batch = make_juice(fruit, count)
        bottles.extend(batch)