Better Way 10 대입식 반복을 피하라

김승환·2021년 7월 11일

코딩의 기술

목록 보기
2/36

#Better Way 10 대입식 반복을 피하라
왈러스 연산자
:= 는 if나 while문등 조건식에 대입후 실제 평가가 이루어짐. (왈러스는 바다코끼리 눈과 어금니 처럼 생겨서 붙여진 이름)
예시 코딩을 위한 코드들 pass 해도 무관

fresh_fruit = {
    '사과': 10,
    '바나나': 8,
    '레몬': 5,
}

def make_lemonade(count):
    n = 1
    print(f'레몬 {count*n} 개로 레모네이드 {count//n} 개를 만듭니다.')
    fresh_fruit['레몬'] -= (count * n)
    print(f'레몬이 {fresh_fruit["레몬"]} 개 남았습니다.')

def out_of_stock():
    print(f'제료가 부족합니다. 재료를 보충해 주세요.')코드를 입력하세요

기존에는 레몬의 개수를 읽은 후 if문을 통해 그 값이 0인지 아닌지 확인이 가능하다.
count = fresh_fruit.get('레몬', 0) #따로 count는 무엇이다 설정이 불편하다라고 생각할 수 있음.

if count:
    make_lemonade(count)
else:
    out_of_stock()

레몬 5 개로 레모네이드 5 개를 만듭니다.
레몬이 0 개 남았습니다.

왈러스를 사용한 코딩은 if문 식에 직접 왈러스를 이용하여 대입

fresh_fruit['레몬'] = 5  # 테스트를 위해 갯수 리셋
if count := fresh_fruit.get('레몬', 0):   #길벗 코드에 lemon이라고 잘못 입력 되어있음.
                                     # 값이 0이면 flase로 else가 실행
    make_lemonade(count)
else:
    out_of_stock()

레몬 5 개로 레모네이드 5 개를 만듭니다.
레몬이 0 개 남았습니다.

또 하나의 예제
사과 4개가 1개의 주스를 만들 수 있게 설정

def make_cider(count):
    n = 4

    print(f'사과 {count} 개로 사과주스 {count//n} 개를 만듭니다.')
    fresh_fruit['사과'] -= (n *(count//n))
    print(f'사과가 {fresh_fruit["사과"]} 개 남았습니다.')

fresh_fruit['사과'] = 10  # 테스트를 위해 갯수 리셋
#기존 사과 4개로 몇개의 주스를 만들 수 있는지 코드
count = fresh_fruit.get('사과', 0)  #따로 count는 무엇이다 설정이 불편하다라고 생각할 수 있음.
if count >= 4:                # 개수가 4보다 작을 경우 flase로 else 실행
    make_cider(count)
else:
    out_of_stock()

사과 10 개로 사과주스 2 개를 만듭니다.
사과가 2 개 남았습니다.

왈러스를 이용한 코드

fresh_fruit['사과'] = 10  # 테스트를 위해 갯수 리셋

if (count := fresh_fruit.get('사과', 0)) >= 4: # 왈러스를 이용하여 대입한 값이 4보다 크면 True로 실행하기 위해 괄호 사용.
    make_cider(count)
else:
    out_of_stock()

사과 10 개로 사과주스 2 개를 만듭니다.
사과가 2 개 남았습니다.

또 또 하나의 예제

고객이 바나나 스무디를 주문했을 때

#스무디를 만들려면 바나나 슬라이스가 최소 두 개는 필요하고 
#슬라이스가 부족하면 OutOfBananas 예외 발생시킴


def slice_bananas(count):
    print(f'바나나 {count} 개를 슬라이스합니다.')
    fresh_fruit['바나나'] -=  count
    return count

class OutOfBananas(Exception):
    pass

def make_smoothies(count):
    n=2
    if count > n:
        print(f'바나나 슬라이스 {count} 개로 스무디 {count//n} 개를 만듭니다.')
        print(f'바나나가 {fresh_fruit["바나나"]} 개 남았습니다.')
    else:
        raise OutOfBananas
#기존 방식인 두가지 예시
#첫번째 pieces를 조건문 밖에 둔 경우

pieces = 0
count = fresh_fruit.get('바나나', 0)
if count >= 2:
    pieces = slice_bananas(count)

try:
    smoothies = make_smoothies(pieces)
except OutOfBananas:
    out_of_stock()

바나나 8 개를 슬라이스합니다.
바나나 슬라이스 8 개로 스무디 4 개를 만듭니다.
바나나가 0 개 남았습니다.

#두번째 pieces를 조건문 안에 둔 경우


fresh_fruit['바나나'] = 1  # 테스트를 위해 갯수 리셋

count = fresh_fruit.get('바나나', 0)
if count >= 2:
    pieces = slice_bananas(count)
else:
    pieces = 0

try:
    smoothies = make_smoothies(pieces)
except OutOfBananas:
    out_of_stock()

재료가 부족합니다. 재료를 보충해 주세요.

#왈러스를 이용한 개선된 방식
#첫번째 개선 pieces가 외부

fresh_fruit['바나나'] = 8  # 테스트를 위해 갯수 리셋

pieces = 0
if (count := fresh_fruit.get('바나나', 0)) >= 2: #괄호의 이유는 위에 확인
    pieces = slice_bananas(count)

try:
    smoothies = make_smoothies(pieces)
except OutOfBananas:
    out_of_stock()

바나나 8 개를 슬라이스합니다.
바나나 슬라이스 8 개로 스무디 4 개를 만듭니다.
바나나가 0 개 남았습니다.

두번째 개선 pieces가 내부

fresh_fruit['바나나'] = 8  # 테스트를 위해 갯수 리셋

if (count := fresh_fruit.get('바나나', 0)) >= 2:
    pieces = slice_bananas(count)
else:
    pieces = 0

try:
    smoothies = make_smoothies(pieces)
except OutOfBananas:
    out_of_stock()

바나나 8 개를 슬라이스합니다.
바나나 슬라이스 8 개로 스무디 4 개를 만듭니다.
바나나가 0 개 남았습니다.

#파이썬에는  switch/ case 문이 따로 없음
#if, elif, else 문 사용
# 가장 좋은 주스 바나나 스무디 --> 애플 주스 --> 레모네이드 순으로 제공
# 기존 방식을 이용한 첫번째 예시

fresh_fruit = {
    '사과': 10,
    '바나나': 1,
    '레몬': 5,
}
count = fresh_fruit.get('바나나', 0)

if count >= 2:
    pieces = slice_bananas(count)
    to_enjoy = make_smoothies(pieces)
else:
    count = fresh_fruit.get('사과', 0)
    if count >= 4:
        to_enjoy = make_cider(count)
    else:
        count = fresh_fruit.get('레몬', 0)
        if count:
            to_enjoy = make_lemonade(count)
        else:
            to_enjoy = '아무것도 없음'

사과 10 개로 사과주스 2 개를 만듭니다.
사과가 2 개 남았습니다.

#왈러스를 이용한 방식
fresh_fruit = {
    '사과': 10,
    '바나나': 8,
    '레몬': 5,
}

if (count := fresh_fruit.get('바나나', 0)) >= 2:
    pieces = slice_bananas(count)
    to_enjoy = make_smoothies(pieces)
elif (count := fresh_fruit.get('사과', 0)) >= 4:
    to_enjoy = make_cider(count)
elif count := fresh_fruit.get('레몬', 0):
    to_enjoy = make_lemonade(count)
else:
    to_enjoy = '아무것도 없음'

바나나 8 개를 슬라이스합니다.
바나나 슬라이스 8 개로 스무디 4 개를 만듭니다.
바나나가 0 개 남았습니다.

# do / while루프가 없음.
# while 루프의 예시
#신선한 과일이 배달돼서 이 과일을 모두 주스로 마든 후 병에 담기로 하는 코드
import random

def pick_fruit():
    if random.randint(1,10) > 2:   # 80% 확률로 새 과일 보충
                                # random.randint를 이용하여 랜덤으로 int값을 불러옴.
        return {
            '사과': random.randint(0,10), 
            '바나나': random.randint(0,10),
            '레몬': random.randint(0,10),
        }
    else:
        return None

def make_juice(fruit, count):
    if fruit == '사과':
        return [('사과주스', count/4)]
    elif fruit == '바나나':
        return [('바나나스무디',count/2)]
    elif fruit == '레몬':
        return [('레모네이드',count/1)]
    else:
        return []
#기존의 첫번째 예시
# while에서 fresh_fruit = pick_fruit() 를 반복사용

bottles = []
fresh_fruit = pick_fruit()
while fresh_fruit: # pick_fruit안의 random.randint 값이 0이 아닌 이상 True로 무한 루프 실행
    for fruit, count in fresh_fruit.items():
        batch = make_juice(fruit, count)
        bottles.extend(batch)
    fresh_fruit = pick_fruit() # pick_fruit안의 random.randint 값이 0이 나온다면 바로 멈춤

print(bottles)

[('사과주스', 1.25), ('바나나스무디', 1.0), ('레모네이드', 6.0)]

# 두번째 예시
#while의 무한 루프와 break을 이용하여 단순화

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)

print(bottles)
[('사과주스', 2.5), ('바나나스무디', 4.0), ('레모네이드', 6.0)]
#왈러스를 이용한 단순화

bottles = []
while fresh_fruit := pick_fruit():
    for fruit, count in fresh_fruit.items():
        batch = make_juice(fruit, count)
        bottles.extend(batch)

print(bottles)

[('사과주스', 1.5), ('바나나스무디', 1.0), ('레모네이드', 6.0), ('사과주스', 0.25), ('바나나스무디', 2.5), ('레모네이드', 4.0), ('사과주스', 0.5), ('바나나스무디', 3.0), ('레모네이드', 6.0), ('사과주스', 0.25), ('바나나스무디', 3.0), ('레모네이드', 8.0), ('사과주스', 2.0), ('바나나스무디', 2.0), ('레모네이드', 6.0), ('사과주스', 0.75), ('바나나스무디', 2.0), ('레모네이드', 5.0), ('사과주스', 2.25), ('바나나스무디', 2.0), ('레모네이드', 1.0), ('사과주스', 2.25), ('바나나스무디', 2.5), ('레모네이드', 5.0), ('사과주스', 2.5), ('바나나스무디', 0.5), ('레모네이드', 8.0), ('사과주스', 1.25), ('바나나스무디', 2.0), ('레모네이드', 2.0), ('사과주스', 1.0), ('바나나스무디', 3.0), ('레모네이드', 8.0), ('사과주스', 2.25), ('바나나스무디', 3.0), ('레모네이드', 10.0)]

# 총 몇 병이 담겨있는지 확인 인터폴레이션 활용해보고 싶어서 사용.
apple_count=0
banana_count=0
lemon_count=0

for fruit, count in bottles:
    if fruit == "사과주스":
        apple_count=apple_count+count
    if fruit == "바나나스무디":
        banana_count=banana_count+count
    if fruit == "레모네이드":
        lemon_count=lemon_count+count
        
a=f"""
사과 주스 병은 총 {apple_count}개 입니다.
바나나스무디 병은 총 {banana_count}개 입니다.
레모네이드 병은 총 {lemon_count} 개 입니다.
"""
print(a)

사과 주스 병은 총 16.75개 입니다.
바나나스무디 병은 총 26.5개 입니다.
레모네이드 병은 총 69.0 개 입니다.

왈러스(:=)를 이용하여 반복식를 단순화 한다.
swich / case, do / while 루프를 쓸 수 없지만, 대입식으로 깔끔하게 표현이 가능하다.

profile
인공지능 파이팅!

0개의 댓글