자동차를 만들 때, 혼자 모든 부품을 담당할 수 없는 거랑 같다.
각자의 역할을 나누고, 서로 호환되는 부품을 제작한 뒤에, 조립하는 것이 효율이 좋다.
속성(attributes): 객체가 가지고 있는 속성, 클래스 속성과 인스턴스 속성이 있다.
메소드(methods): 클래스의 연산 수행을 의미한다. 클래스의 동작이라고 생각하면 편하다.
청사진을 만들거나 가져온 뒤에, 그것을 활용하여 여러 객체들을 제작 할 수 있다.


거북이의 색을 바꾸고 싶다면 어떻게 해야 할까?
- timmy.color() 라는 메소드를 이용한다. () 안에는 바꾸고 싶은 색을 입력한다.
- 예) timmy.color("coral")
거북이를 움직이려면 어떻게 해야 할까?
- timmy.forward(100)
다른 개발자가 작성한 코드를 사용하는 일반적인 방법은 코드 패키지를 사용하는 것이다.

파이썬에 기본으로 깔려있는 터틀 패키지와는 다르게, 파이썬 패키지 인덱스에서 찾은 패키지를 사용하려면, 설치가 필요하다.



이렇게 하면 설치가 완료된다.
그 다음, 패키지에 대한 설명을 읽고 어떻게 사용하는지 확인을 한 후 사용하면 된다.

다음은, 속성을 이용하여 정렬을 바꾸는 방법이다.

coffee_maker.py는 아래와 같다.
class CoffeeMaker:
"""Models the machine that makes the coffee"""
def __init__(self):
self.resources = {
"water": 300,
"milk": 200,
"coffee": 100,
}
def report(self):
"""Prints a report of all resources."""
print(f"Water: {self.resources['water']}ml")
print(f"Milk: {self.resources['milk']}ml")
print(f"Coffee: {self.resources['coffee']}g")
def is_resource_sufficient(self, drink):
"""Returns True when order can be made, False if ingredients are insufficient."""
can_make = True
for item in drink.ingredients:
if drink.ingredients[item] > self.resources[item]:
print(f"Sorry there is not enough {item}.")
can_make = False
return can_make
def make_coffee(self, order):
"""Deducts the required ingredients from the resources."""
for item in order.ingredients:
self.resources[item] -= order.ingredients[item]
print(f"Here is your {order.name} ☕️. Enjoy!")
menu.py는 아래와 같다.
class MenuItem:
"""Models each Menu Item."""
def __init__(self, name, water, milk, coffee, cost):
self.name = name
self.cost = cost
self.ingredients = {
"water": water,
"milk": milk,
"coffee": coffee
}
class Menu:
"""Models the Menu with drinks."""
def __init__(self):
self.menu = [
MenuItem(name="latte", water=200, milk=150, coffee=24, cost=2.5),
MenuItem(name="espresso", water=50, milk=0, coffee=18, cost=1.5),
MenuItem(name="cappuccino", water=250, milk=50, coffee=24, cost=3),
]
def get_items(self):
"""Returns all the names of the available menu items"""
options = ""
for item in self.menu:
options += f"{item.name}/"
return options
def find_drink(self, order_name):
"""Searches the menu for a particular drink by name. Returns that item if it exists, otherwise returns None"""
for item in self.menu:
if item.name == order_name:
return item
print("Sorry that item is not available.")
main.py는 아래와 같다.
from menu import Menu
from coffee_maker import CoffeeMaker
from money_machine import MoneyMachine
money_machine = MoneyMachine()
coffee_maker = CoffeeMaker()
menu = Menu()
is_on = True
while is_on:
options = menu.get_items()
choice = input(f"What would you like? ({options}): ")
if choice == "off": # 자판기를 끔.
is_on = False
elif choice == "report": # 보고를 받는 명령.
coffee_maker.report()
money_machine.report()
else:
drink = menu.find_drink(choice)
if coffee_maker.is_resource_sufficient(drink) and money_machine.make_payment(drink.cost):
coffee_maker.make_coffee(drink)
money_machine.py는 아래와 같다.
class MoneyMachine:
CURRENCY = "$"
COIN_VALUES = {
"quarters": 0.25,
"dimes": 0.10,
"nickles": 0.05,
"pennies": 0.01
}
def __init__(self):
self.profit = 0
self.money_received = 0
def report(self):
"""Prints the current profit"""
print(f"Money: {self.CURRENCY}{self.profit}")
def process_coins(self):
"""Returns the total calculated from coins inserted."""
print("Please insert coins.")
for coin in self.COIN_VALUES:
self.money_received += int(input(f"How many {coin}?: ")) * self.COIN_VALUES[coin]
return self.money_received
def make_payment(self, cost):
"""Returns True when payment is accepted, or False if insufficient."""
self.process_coins()
if self.money_received >= cost:
change = round(self.money_received - cost, 2) # 소수점 둘째자리.
print(f"Here is {self.CURRENCY}{change} in change.")
self.profit += cost
self.money_received = 0
return True
else:
print("Sorry that's not enough money. Money refunded.")
self.money_received = 0
return False