python / 클래스(이해, 클래스 멤버/인스턴스 멤버, 메소드, 생성자, 소멸자)
049 클래스 이해하기(class)
클래스 코드 작성시 필요한 이유? "상속"때문에 필요함.
예제. 영화할인카드 프로그램을 개발하는데 지금까지 만든 커피 키오스크처럼 몇 일에 걸쳐서 개발을 해야함. 기존에 카드의 기본 기능을 수행하는 카드라는 프로그램이 있다면 카드의 기본 기능이 있는 카드프로그램을 상속받고 나는 그냥 영화 할인코드에만 집중해서 코드를 구현하면 됨.
(카드의 가장 중요한 기능들은 연차가 있는 팀장님이 만들고 card라는 클래스로 생성했다면 나는 팀장님이 만든 card클래스를 상속받고 영화 할인에 대한 코드만 생성한 후에 내가 만든 코드에 대한 클래스 이름을 movie_card라고 하면 됨.)
클래스(class)란?
설계도와 같은 것.
ex) 총 설계도 (클래스) --------------------> 총 완성제품 (객체)
커피 키오스크도 만약 클래스(설계도)로 만들어서 사용한다면 어떤 장점이 있는가?
커피 키오스크(클래스) -------상속------> 스타벅스 키오스크(클래스) --------> 객체(제품) 생산
코드를 상속받으면 내가 짜야할 코드의 양을 줄일 수 있고 정말 중요한 코드는 관리자가 짜고 나는 내가 해야할 다른 코드에만 집중할 수 있게 해줌.
객체지향 프로그램이 무엇인가요?(면접질문) "상속을 받을 수 있는 프로그램 입니다."
예제. 총 클래스(설계도)를 생성하시오.
총의 기능 : 1. 총알 장전(charge)
2. 발사(shoot)
클래스로 만들기 전에 함수로 만들어보겠음.
문제189. 다음과 같이 숫자를 입력하고 실행하면 다음의 결과가 출력되는 함수를 생성하시오.
def shoot(num1):
for i in range(num1):
print('탕!')
# def shoot(num1):
# print('탕!\n' * num1)
shoot(3)
문제190. 총알을 장전하는 기능인 charge라는 함수를 다음과 같이 생성하시오.
def charge(num2):
print(num2,'발 장전 되었습니다.')
charge(5)
shoot과 charge함수는 총의 기능을 갖는 함수. 지금은 따로 따로 만들어서 별개로 작동되고 있음.
그런데 만약 총알이 장전(충전)된 만큼 총을 shoot하려면 이 함수들을 하나의 클래스에 넣어야함.
*총 클래스(설계도) 생성
class Gun(): # 총 설계도를 만듦
def charge(self, num): # 총알 충전하는 함수
self.bullet = num # 총알을 num 숫자만큼 장전
print(self.bullet, '발이 장전되었습니다.')
def shoot(self, num): # 총을 쏘는 함수
for i in range(1, num+1): # 입력된 숫자만큼 반복
if self.bullet > 0: # 총알이 있다면 쏘고
print('탕!')
self.bullet -= 1 # 한 발 차감
elif self.bullet == 0: # 총알이 없다면 메시지를 출력
print('총알이 없습니다.')
break # 그리고 loop문을 종료
class 명을 대문자로 쓰는 이유 > 코드의 가독성을 높이기 위해서 낙타 표기법을 사용함. ex) GunCharge 낙타 등처럼 문자에 굴곡을 줘서 확인하기 쉽게 함.
예제. 설계도(클래스)를 가지고 총 제품(객체)를 하나 만듭니다.
gun1 = Gun()
# gun1 = 제품이름, Gun() = 설계도 이름
print(type(gun1)) # <class '__main__.Gun'>
예제. 총알을 충전합니다.
gun1.charge(10)
예제. 총을 3발 쏘아보세요.
gun1.shoot(3)
ㅇ클래스 생성시 self를 쓰는 이유
charge(self, num): < 클래스(설계도) 생성시 이렇게 self를 넣어서 만듦.
gun1이라는 총에 장전을 한다는 의미. 구분을 위해 씀.
ex) gun2라는 제품을 만들었다면 gun1에 대한 메모리 공간과 gun2에 대한 메모리 공간이 각각 필요함. self를 쓰지 않으면 어느 제품에 num1이 충전하는것인지 모름. 따라서 self를 사용해서 어느 제품에 num1이 들어가는 것인지 확실하게 해줌.
문제191. 총 설계도(Gun)로 gun2를 만들고 100발 장전해서 90발 쏘시오.
gun2 = Gun()
gun2.charge(100)
gun2.shoot(90)
문제192. (점심시간 문제) 총 설계도에 print하는 함수를 추가해서 다음과 같이 총알이 몇발 남았는지 출력되게 하시오.
class Gun():
def charge(self, num1):
self.bullet = num1
print(self.bullet, '발이 장전되었습니다.')
def shoot(self, num):
for i in range(1, num+1):
if self.bullet > 0:
print('탕!')
self.bullet -= 1
elif self.bullet == 0:
print('총알이 없습니다.')
break
def print(self): # self를 꼭 써줘야함
print('총알이 %d 발 남았습니다.'%self.bullet) # self.bullet 자체가 총알의 갯수임. shoot을 해도 남아있는 총알의 수
gun3 = Gun()
gun3.charge(5)
gun3.shoot(2)
gun3.print()
ㅇclass(설계도) 생성시 self를 사용하는 경우
1. 변수이름 앞
2. 함수 생성시 괄호 안
ㅇ파이썬에서는 예약어를 함수이름이나 클래스 이름으로 사용가능 하지만 웬만해서는 피하는게 좋음.
문제193. 스타벅스처럼 gift_card를 제공하기 위해서 coffee_gift_card 클래스를 생성하시오!
class Coffee_Gift_Card():
def charge(self,num):
self.money = num
print(self.money,'원이 충전되었습니다.')
def consume(self,num):
if self.money > 0:
print(num,'원이 사용되었습니다.')
self.money -= num
elif self.money == 0:
print('잔액이 없습니다.')
print('남은 잔액은 %d원 입니다.'%self.money)
# 기프트 카드를 발급하세요
gift_card1 = Coffee_Gift_Card()
# 30000원을 충전하시오
gift_card1.charge(30000)
문제194. 카드를 발급할 때 "카드가 발급되었습니다. "라는 메세지가 나오게 하시오.
class Coffee_Gift_Card():
def __init__(self): # 클래스를 가지고 객체(제품)를 만들때 자동으로 호출되는 함수(메소드)
self.money = 0
print('카드가 발급되었습니다. %d원이 충전되어 있습니다.'%self.money)
def charge(self,num):
self.money = num
print(self.money,'원이 충전되었습니다.')
def consume(self,num):
if self.money > 0:
print(num,'원이 사용되었습니다.')
self.money -= num
elif self.money == 0:
print('잔액이 없습니다.')
print('남은 잔액은 %d원 입니다.'%self.money)
gift_card1 = Coffee_Gift_Card()
# 카드가 발급되었습니다. 0원이 충전되어 있습니다. (__init__함수로 자동호출됨)
문제195. 위의 코드를 수정해서 카드 발급할때 카드 이미지가 출력되게 하시오.
class Coffee_Gift_Card():
def __init__(self):
self.money = 0
print('카드가 발급되었습니다. %d원이 충전되어 있습니다.'%self.money)
#이미지 출력
import PIL.Image as pilimg
import numpy as np
import matplotlib.pyplot as plt
im = pilimg.open("c:\\data\\스타벅스.png")
pix = np.array(im)
plt.imshow(pix)
ax = plt.gca()
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.show()
def charge(self,num):
self.money = num
print(self.money,'원이 충전되었습니다.')
def consume(self,num):
if self.money > 0:
print(num,'원이 사용되었습니다.')
self.money -= num
elif self.money == 0:
print('잔액이 없습니다.')
print('남은 잔액은 %d원 입니다.'%self.money)
문제196. 지금 현재 기프트카드 설계도는 카드충전이 누적되지 않고 있음. 누적이 되도록 코드를 수정하세요.
class Coffee_Gift_Card():
def __init__(self):
self.money = 0
print('카드가 발급되었습니다. %d원이 충전되어 있습니다.'%self.money)
#이미지 출력
import PIL.Image as pilimg
import numpy as np
import matplotlib.pyplot as plt
im = pilimg.open("c:\\data\\스타벅스.png")
pix = np.array(im)
plt.imshow(pix)
plt.axis('off')
plt.show()
def charge(self,num):
self.money += num
print(num,'원이 충전되었습니다.')
print('현재 카드의 남아있는 금액은 %d원 입니다.'%self.money)
def consume(self,num):
if self.money > 0:
print(num,'원이 사용되었습니다.')
self.money -= num
elif self.money == 0:
print('잔액이 없습니다.')
print('남은 잔액은 %d원 입니다.'%self.money)
a = [1,2,3,4,5]
print(type(a)) # <class 'list'>
클래스에는 메소드(함수)가 있음.
a.count(2) # a라는 리스트 객체의 count라는 함수를 실행한 것
파이썬 개발자가 리스트를 클래스로 만들었기 때문에 리스트 클래스를 객체(제품)화 시키고 나면 설계도(클래스) 안에 함수를 사용할 수 있는 것.
ㅇ리스트 클래스의 함수(메소드) - 파이썬 책 p.10 참고
1. count()
2. append()
3. insert()
4. delf()
5. sort()
6. shuffle()
7. enumerate()
050 클래스 멤버와 인스턴스 멤버 이해하기
클래스에서 선언된 변수는 클래스 멤버(변수)와 인스턴스 멤버(변수)가 있음.
클래스 멤버는 클래스 메소드(함수) 바깥에서 선언되고 인스턴스 멤버는 클래스 메소드 안에서 self와 함께 선언되는 변수.
인공지능 시킬 키오스크 프로그램을 고객들이 잘 사용할 수 있도록 기프트 카드 시스템을 도입했는데 스타벅스처럼 우리 기프트 카드를 홍보하려면 스타벅스보다 더 좋은 마케팅을 해야하니까 충전할 때마다 10%의 캐쉬를 더 넣어주게끔 코드를 수정하겠음.
class Coffee_Gift_Card():
#raise_amount = 1.1 # 클래스 멤버(변수)
def __init__(self):
self.money = 0
self.raise_amount = 1.1 # 인스턴스 멤버(변수)
print('카드가 발급되었습니다. %d원이 충전되어 있습니다.'%self.money)
#이미지 출력
import PIL.Image as pilimg
import numpy as np
import matplotlib.pyplot as plt
im = pilimg.open("c:\\data\\스타벅스.png")
pix = np.array(im)
plt.imshow(pix)
plt.axis('off')
plt.show()
def charge(self,num2):
print(num2,'원을 받았습니다.')
num = int(num2*self.raise_amount)
self.money += num
print(num,'원이 충전되었습니다.')
print('현재 카드의 남아있는 금액은 %d원 입니다.'%self.money)
def consume(self,num):
if self.money > 0:
print(num,'원이 사용되었습니다.')
self.money -= num
elif self.money == 0:
print('잔액이 없습니다.')
print('남은 잔액은 %d원 입니다.'%self.money)
그런데 이번에 발급하는 카드의 경우는 이 손님이 좀 특별한 손님이어서 충전할 때 20%를 더 충전할 수 있도록 설계도를 고치고 객체를 만들어야 함. 그런데 설계도를 고치지 않고 그냥 이 손님만 20%를 더 충전해드리고 싶다면?
gift_card2 = Coffee_Gift_Card()
gift_card2.raise_amount = 1.2
gift_card2.charge(10000)
# 인스턴스 멤버가 self.raise_amount로 되어있으므로 gift_card2만 1.2로 적용되고
# 다른 카드들은 설계도에 나온대로 1.1로 적용됨.
만약 위와 같이 하지 않고 설계도를 고치면 전국의 모든 고객들이 카드를 발급 받을때 20%를 적용한 상태로 충전이 될 것. 설계도를 고치지 않고 지금 이 고객만 20% 적용하고 싶다면 인스턴스 멤버(self.raise_amount)로 설계도를 만들고gift_card2.raise_amount = 1.2 적용하면 됨.
이렇게 하다가 나중에 문제가 생겨 위와같이 수정되는 것을 방지하고 싶다면 어떻게 해야 하는가?
> raise_amount를 클래스 멤버(변수)로 생성하면 됨.
class Coffee_Gift_Card():
raise_amount = 1.1 # 클래스 멤버(변수), 클래스 변수 앞에는 self가 없음
def __init__(self):
self.money = 0
#self.raise_amount = 1.1 # 인스턴스 멤버(변수)
print('카드가 발급되었습니다. %d원이 충전되어 있습니다.'%self.money)
#이미지 출력
import PIL.Image as pilimg
import numpy as np
import matplotlib.pyplot as plt
im = pilimg.open("c:\\data\\스타벅스.png")
pix = np.array(im)
plt.imshow(pix)
plt.axis('off')
plt.show()
def charge(self,num2):
print(num2,'원을 받았습니다.')
num = int(num2 * Coffee_Gift_Card.raise_amount)
self.money += num
print(num,'원이 충전되었습니다.')
print('현재 카드에 남아있는 금액은 %d원 입니다.'%self.money)
def consume(self,num):
if self.money > 0:
print(num,'원이 사용되었습니다.')
self.money -= num
elif self.money == 0:
print('잔액이 없습니다.')
print('남은 잔액은 %d원 입니다.'%self.money)
클래스 멤버로 설정할 경우 raise_amount를 함부로 바꿀 수 없음. 아래와 같은 코드를 작성해도 코드가 먹히지 않음(클래스에서 코드가 변경되지 않음)
gift_card3.raise_amount=1.2
따라서 raise_amount와 같은 중요변수들은 악용되거나 실수로 크게 캐쉬 충전이 될 수 있으므로 인스턴스 변수로 선언하면 안되고 클래스 변수로 선언해서 사용해야함.
( ex. 등급별 포인트를 제공한다고 할 경우 등급별 튜플을 만들고, 인스턴스 멤버를 만들어서 적용하면 됨)
# 참고
Coffee_Gift_Card.raise_amount=1.2
# 위 코드로 Coffee_Gift_Card 클래스 자체의 클래스 멤버값(raise_amount)을 변경시킴.
gift_card3.charge(10000)
# 클래스 멤버값 변경 후 다시 charge하면 변경값으로 적용됨.
051 클래스 메소드 이해하기
클래스(설계도) 안의 함수가 method(기능) 입니다.
문제197. 커피 키오스크 함수를 가지고 class를 생성하시오. (클래스 이름 : Coffee_Class)
class Coffee_Class():
def __init__(self):
print('키오스크 시스템을 시작합니다.')
def coffee_image(self):
import PIL.Image as pilimg
import numpy as np
import matplotlib.pyplot as plt
im = pilimg.open("c:\\data\\coffee.png")
pix = np.array(im)
plt.imshow(pix)
plt.axis('off') #x,y축 없애기
plt.show() # 이미지 출력할때 넣어주면 됨
def coffee_kiosk(self):
#커피 이미지
self.coffee_image() #self를 붙여서 위의 함수를 가져옴.
import pandas as pd
print('='*16,' CAFE ','='*16)
print('1 : 아메리카노:1500원 \n2 : 카페라떼:2500원 \n3 : 카페모카:3500원 \n4 : 녹차라떼:3500원 \n\n10 > 결산(관리자용)')
print('='*40)
c_type = ['아메리카노','카페라떼','카페모카','녹차라떼']
c_stock = [20,10,30,20] # [0]: 아메리카노 재고, [1] : 카페라떼 재고, [2] : 카페모카 재고, [3] : 녹차라떼 재고
c_price = [1500,2500,3500,3500] # [0]: 아메리카노 가격, [1] : 카페라떼 가격, [2] : 카페모카 가격, [3] : 녹차라떼 가격
coupon = 0
order_no = 1
cafe_dict = {}
cafe_dict['주문번호'] = []
cafe_dict['주문시간'] =[]
cafe_dict['커피종류'] = []
cafe_dict['수량'] = []
cafe_dict['가격'] = []
while True:
# 전체 품절
if c_stock[0] == 0 and c_stock[1] == 0 and c_stock[2] == 0 and c_stock[3] == 0:
print('\n\n\n모든 커피가 품절입니다.')
print('='*40,'\n')
break
num = int(input('\n%d번손님,주문하시겠습니까? \n메뉴를 골라주세요. 번호를 눌러주세요.'%order_no))
# 주문
if num < 5:
print('%s를 선택하셨습니다.'%c_type[num-1])
if c_stock[num-1] == 0:
print('\n%s : 품절'%c_type[num-1])
print('\n다시 입력해주세요~')
continue
cup = int(input('몇 잔 주문하시겠습니까? '))
if cup > c_stock[num-1]:
print('\n죄송합니다. 주문량에 비해 %s가 부족합니다.'%c_type[num-1])
print('현재 주문 가능한 수량은 %d잔 입니다.' %c_stock[num-1], '다시 입력해주세요.')
cup = int(input('몇 잔 주문하시겠습니까? '))
price = c_price[num-1] * cup
print('\n결제하실 금액은 %d원 입니다.'%price)
# 쿠폰x, 정상결제 시
if coupon < 20:
money = int(input('돈을 입력하시오~ '))
if c_stock[num-1] >= cup and money >= price:
print('\n[주문번호 %d]'%order_no)
print('%s가 나왔습니다. 거스름돈은 '%c_type[num-1],money - price,'원 입니다.')
print('쿠폰이 %d개 발급되었습니다.(20개 모으면 한잔 무료)'%cup)
c_stock[num-1] -= cup
coupon += cup
print('현재 보유한 쿠폰 : %d개 '%coupon)
print('='*40,'\n')
from datetime import datetime
now = str(datetime.now())
cafe_dict['주문번호'].append(order_no)
cafe_dict['주문시간'].append(now)
cafe_dict['커피종류'].append(c_type[num-1])
cafe_dict['수량'].append(cup)
cafe_dict['가격'].append(price)
order_no += 1
elif c_stock[num-1] >= cup and money < price:
print('금액이 부족합니다. 돈을 반환합니다.')
print('='*40,'\n')
continue
#쿠폰 20개 이상
elif coupon >= 20:
question1 = int(input('쿠폰을 사용하시겠습니까?(1일 1회 1잔만 가능) \n예 : 1번\n아니오 : 2번 '))
# 쿠폰사용
if question1 == 1:
print('\n쿠폰 20개가 차감됩니다.')
coupon -= 20
if cup == 1:
price -= price
print('\n[주문번호 %d]'%order_no)
print('%s가 나왔습니다. 쿠폰은 발급되지 않습니다.'%c_type[num-1])
print('현재 보유한 쿠폰 : %d개 '%coupon)
print('='*40,'\n')
else:
price -= c_price[num-1]
money2 = int(input('결제할 차액은 %s 원 입니다. 돈을 입력하세요~ '%price))
if money2 >= price:
print('\n[주문번호 %d]'%order_no)
print('%s가 나왔습니다. 거스름돈은 %s원 입니다. 쿠폰은 발급되지 않습니다.'%(c_type[num-1],money2 - price))
print('현재 보유한 쿠폰 : %d개 '%coupon)
print('='*40,'\n')
elif money2 < price:
print('금액이 부족합니다. 돈을 반환합니다.')
print('='*40,'\n')
continue
from datetime import datetime
now = str(datetime.now())
cafe_dict['주문번호'].append(order_no)
cafe_dict['주문시간'].append(now)
cafe_dict['커피종류'].append(c_type[num-1])
cafe_dict['수량'].append(cup)
cafe_dict['가격'].append(price)
order_no += 1
#쿠폰 사용 안함
elif question1 == 2:
print('\n쿠폰을 사용하지 않습니다')
money = int(input('돈을 입력하시오~ '))
if c_stock[num-1] >= cup and money >= price:
print('\n[주문번호 %d]'%order_no)
print('%s가 나왔습니다. 거스름돈은 '%c_type[num-1],money - price,'원 입니다.')
print('쿠폰이 %d개 발급되었습니다.(20개 모으면 한잔 무료)'%cup)
c_stock[num-1] -= cup
coupon += cup
print('현재 보유한 쿠폰 : %d개 '%coupon)
print('='*40,'\n')
from datetime import datetime
now = str(datetime.now())
cafe_dict['주문번호'].append(order_no)
cafe_dict['주문시간'].append(now)
cafe_dict['커피종류'].append(c_type[num-1])
cafe_dict['수량'].append(cup)
cafe_dict['가격'].append(price)
order_no += 1
elif c_stock[num-1] >= cup and money < price:
print('금액이 부족합니다. 돈을 반환합니다.')
print('='*40,'\n')
continue
else:
print('번호를 잘못 입력했습니다. 처음 화면으로 돌아갑니다.')
# 결산(관리자용)
elif num == 10:
print('\n\n------- 관리자 모드로 실행됩니다 -------')
password = int(input('비밀번호를 입력하세요~ '))
if password == 1234:
print('\n정산 내역을 출력합니다')
break
else:
print('비밀번호가 틀렸습니다. 처음 화면으로 돌아갑니다.')
continue
# 메뉴 없음
else:
print('메뉴가 없습니다. 처음 화면으로 돌아갑니다.')
print('='*40,'\n')
continue
cafe = pd.DataFrame(cafe_dict)
time = now[:10]+'일_'+now[11:13]+'시_'+now[14:16]+'분_'+now[17:19]+'초' #현재시간
cafe.to_csv("c:\\data\\coffee_report_"+ time +".csv",encoding = "ANSI") #판다스 dataframe 자동저장
print('\n 오늘 지금까지 총 수익은 ',cafe['가격'].sum(),'원 입니다.')
# 원형그래프
from matplotlib import font_manager, rc
import matplotlib.pyplot as plt
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name) #폰트설정
result = cafe.groupby('커피종류')['가격'].sum().reset_index()
result.columns=['커피종류','총매출']
result.plot.pie(y = '총매출',labels = result['커피종류'], startangle=100, autopct='%1.1f%%')
plt.legend(loc='best',bbox_to_anchor=(1, 1))
plt. title('커피종류별 총 매출액')
plt.savefig("c:\\data\\coffee_piechart_"+ time+".png") #파이차트 이미지 자동저장
return cafe
클래스 생성 후 실행하기
kiosk1 = Coffee_Class()
kiosk1.coffee_kiosk()
052 클래스 생성자 이해하기
클래스 생성자는 클래스(설계도)를 가지고 객체(제품)이 생성될 때 자동적으로 호출되는 메소드(함수)임. 이 메소드 이름은 def __init(self) 입니다.
class Coffee_Class():
def __init__(self):
print('키오스크 시스템을 시작합니다.')
문제 198. Coffee_Class로 키오스크 객체를 만들때 키오스크 그림이 출력되고 "커피 키오스크 시스템을 시작합니다."라고 출력되게 하시오.
class Coffee_Class():
def __init__(self):
self.image("c:\\data\\kioskimage.png") #수정
print('키오스크 시스템을 시작합니다.')
def image(self,name):
import PIL.Image as pilimg
import numpy as np
import matplotlib.pyplot as plt
im = pilimg.open(name) #수정
pix = np.array(im)
plt.imshow(pix)
plt.axis('off') #x,y축 없애기
plt.show() # 이미지 출력할때 넣어주면 됨
def coffee_kiosk(self):
#커피 이미지
self.image("c:\\data\\coffee.png") #수정
# 아래의 코드는 동일하므로 생략함
053 클래스 소멸자 이해하기
객체가 사라질때 자동으로 호출되는 함수를 소멸자(__del__)라고 함.
총 클래스로 gun1이라는 총을 만들고 총을 사용하다가 이제 총을 폐기하고 싶으면 del 명령어로 총을 폐기하면 되는데 이때 자동으로 작동되는 메소드(함수)가 소멸자.
class Gun():
def __init__(self):
self.bullet = 0
print('총 한 정이 생성되었습니다.')
def __del__(self):
print('총이 폐기 되었습니다.')
클래스 생성 후 gun1을 만들고 del 사용해보기
gun1 = Gun()
del gun1
문제199. 이미지를 이용해서 메뉴판을 이미지로 만드세요.
class Coffee_Class():
def __init__(self):
self.image("c:\\data\\kioskimage.png") #수정
print('키오스크 시스템을 시작합니다.')
def image(self,name):
import PIL.Image as pilimg
import numpy as np
import matplotlib.pyplot as plt
im = pilimg.open(name) #수정
pix = np.array(im)
plt.imshow(pix)
plt.axis('off') #x,y축 없애기
plt.show() # 이미지 출력할때 넣어주면 됨
def coffee_kiosk(self):
#커피 이미지
self.image("c:\\data\\coffee.png") #수정
# 커피 메뉴판
self.image("c:\\data\\menu.jpg")
import pandas as pd
c_type = ['아메리카노','카페라떼','카페모카','녹차라떼']
c_stock = [20,10,30,20] # [0]: 아메리카노 재고, [1] : 카페라떼 재고, [2] : 카페모카 재고, [3] : 녹차라떼 재고
c_price = [1500,2500,3500,3500] # [0]: 아메리카노 가격, [1] : 카페라떼 가격, [2] : 카페모카 가격, [3] : 녹차라떼 가격
coupon = 0
order_no = 1
cafe_dict = {}
cafe_dict['주문번호'] = []
cafe_dict['주문시간'] =[]
cafe_dict['커피종류'] = []
cafe_dict['수량'] = []
cafe_dict['가격'] = []
while True:
# 전체 품절
if c_stock[0] == 0 and c_stock[1] == 0 and c_stock[2] == 0 and c_stock[3] == 0:
print('\n\n\n모든 커피가 품절입니다.')
print('='*40,'\n')
break
num = int(input('\n%d번손님,주문하시겠습니까? \n메뉴를 골라주세요. 번호를 눌러주세요.'%order_no))
# 주문
if num < 5:
print('%s를 선택하셨습니다.'%c_type[num-1])
if c_stock[num-1] == 0:
print('\n%s : 품절'%c_type[num-1])
print('\n다시 입력해주세요~')
continue
cup = int(input('몇 잔 주문하시겠습니까? '))
if cup > c_stock[num-1]:
print('\n죄송합니다. 주문량에 비해 %s가 부족합니다.'%c_type[num-1])
print('현재 주문 가능한 수량은 %d잔 입니다.' %c_stock[num-1], '다시 입력해주세요.')
cup = int(input('몇 잔 주문하시겠습니까? '))
price = c_price[num-1] * cup
print('\n결제하실 금액은 %d원 입니다.'%price)
# 쿠폰x, 정상결제 시
if coupon < 20:
money = int(input('돈을 입력하시오~ '))
if c_stock[num-1] >= cup and money >= price:
print('\n[주문번호 %d]'%order_no)
print('%s가 나왔습니다. 거스름돈은 '%c_type[num-1],money - price,'원 입니다.')
print('쿠폰이 %d개 발급되었습니다.(20개 모으면 한잔 무료)'%cup)
c_stock[num-1] -= cup
coupon += cup
print('현재 보유한 쿠폰 : %d개 '%coupon)
print('='*40,'\n')
from datetime import datetime
now = str(datetime.now())
cafe_dict['주문번호'].append(order_no)
cafe_dict['주문시간'].append(now)
cafe_dict['커피종류'].append(c_type[num-1])
cafe_dict['수량'].append(cup)
cafe_dict['가격'].append(price)
order_no += 1
elif c_stock[num-1] >= cup and money < price:
print('금액이 부족합니다. 돈을 반환합니다.')
print('='*40,'\n')
continue
#쿠폰 20개 이상
elif coupon >= 20:
question1 = int(input('쿠폰을 사용하시겠습니까?(1일 1회 1잔만 가능) \n예 : 1번\n아니오 : 2번 '))
# 쿠폰사용
if question1 == 1:
print('\n쿠폰 20개가 차감됩니다.')
coupon -= 20
if cup == 1:
price -= price
print('\n[주문번호 %d]'%order_no)
print('%s가 나왔습니다. 쿠폰은 발급되지 않습니다.'%c_type[num-1])
print('현재 보유한 쿠폰 : %d개 '%coupon)
print('='*40,'\n')
else:
price -= c_price[num-1]
money2 = int(input('결제할 차액은 %s 원 입니다. 돈을 입력하세요~ '%price))
if money2 >= price:
print('\n[주문번호 %d]'%order_no)
print('%s가 나왔습니다. 거스름돈은 %s원 입니다. 쿠폰은 발급되지 않습니다.'%(c_type[num-1],money2 - price))
print('현재 보유한 쿠폰 : %d개 '%coupon)
print('='*40,'\n')
elif money2 < price:
print('금액이 부족합니다. 돈을 반환합니다.')
print('='*40,'\n')
continue
from datetime import datetime
now = str(datetime.now())
cafe_dict['주문번호'].append(order_no)
cafe_dict['주문시간'].append(now)
cafe_dict['커피종류'].append(c_type[num-1])
cafe_dict['수량'].append(cup)
cafe_dict['가격'].append(price)
order_no += 1
#쿠폰 사용 안함
elif question1 == 2:
print('\n쿠폰을 사용하지 않습니다')
money = int(input('돈을 입력하시오~ '))
if c_stock[num-1] >= cup and money >= price:
print('\n[주문번호 %d]'%order_no)
print('%s가 나왔습니다. 거스름돈은 '%c_type[num-1],money - price,'원 입니다.')
print('쿠폰이 %d개 발급되었습니다.(20개 모으면 한잔 무료)'%cup)
c_stock[num-1] -= cup
coupon += cup
print('현재 보유한 쿠폰 : %d개 '%coupon)
print('='*40,'\n')
from datetime import datetime
now = str(datetime.now())
cafe_dict['주문번호'].append(order_no)
cafe_dict['주문시간'].append(now)
cafe_dict['커피종류'].append(c_type[num-1])
cafe_dict['수량'].append(cup)
cafe_dict['가격'].append(price)
order_no += 1
elif c_stock[num-1] >= cup and money < price:
print('금액이 부족합니다. 돈을 반환합니다.')
print('='*40,'\n')
continue
else:
print('번호를 잘못 입력했습니다. 처음 화면으로 돌아갑니다.')
# 결산(관리자용)
elif num == 10:
print('\n\n------- 관리자 모드로 실행됩니다 -------')
password = int(input('비밀번호를 입력하세요~ '))
if password == 1234:
print('\n정산 내역을 출력합니다')
break
else:
print('비밀번호가 틀렸습니다. 처음 화면으로 돌아갑니다.')
continue
# 메뉴 없음
else:
print('메뉴가 없습니다. 처음 화면으로 돌아갑니다.')
print('='*40,'\n')
continue
cafe = pd.DataFrame(cafe_dict)
time = now[:10]+'일_'+now[11:13]+'시_'+now[14:16]+'분_'+now[17:19]+'초' #현재시간
cafe.to_csv("c:\\data\\coffee_report_"+ time +".csv",encoding = "ANSI") #판다스 dataframe 자동저장
print('\n 오늘 지금까지 총 수익은 ',cafe['가격'].sum(),'원 입니다.')
# 원형그래프
from matplotlib import font_manager, rc
import matplotlib.pyplot as plt
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name) #폰트설정
result = cafe.groupby('커피종류')['가격'].sum().reset_index()
result.columns=['커피종류','총매출']
result.plot.pie(y = '총매출',labels = result['커피종류'], startangle=100, autopct='%1.1f%%')
plt.legend(loc='best',bbox_to_anchor=(1, 1))
plt. title('커피종류별 총 매출액')
plt.savefig("c:\\data\\coffee_piechart_"+ time+".png") #파이차트 이미지 자동저장
return cafe
+) gift_card 최종 스크립트
class Coffee_Gift_Card():
raise_amount = 1.1 # 클래스 멤버(변수), 클래스 변수 앞에는 self가 없음
def __init__(self):
self.money = 0
#self.raise_amount = 1.1 # 인스턴스 멤버(변수)
print('카드가 발급되었습니다. %d원이 충전되어 있습니다.'%self.money)
#이미지 출력
import PIL.Image as pilimg
import numpy as np
import matplotlib.pyplot as plt
im = pilimg.open("c:\\data\\스타벅스.png")
pix = np.array(im)
plt.imshow(pix)
plt.axis('off')
plt.show()
def charge(self,num2):
print(num2,'원을 받았습니다.')
num = int(num2 * Coffee_Gift_Card.raise_amount)
self.money += num
print(num,'원이 충전되었습니다.')
print('현재 카드에 남아있는 금액은 %d원 입니다.'%self.money)
def consume(self,num):
if self.money >= num and num >= 0 :
print(num,'원이 사용되었습니다.')
self.money -= num
elif self.money == 0:
print('잔액이 없습니다.')
elif self.money < num and num >= 0 :
print('잔액이 모자릅니다. 결제가 취소되었습니다.')
else:
print('정상적인 접근이 아닙니다.')
print('남은 잔액은 %d원 입니다.'%self.money)
(참고자료)
클래스는 객체를 만들기위해 만들고, 모듈은 클래스에 메소드를 제공하기 위해 만든다.
클래스는 말그대로 객체생성을 위해 만드는거고, 모듈은 클래스에서 사용할 기능들을 제공하기 위해 만든다고 생각하면 쉽다.
클래스(객체) | 모듈(기능. 사용가능한 메서드를 제공하는 라이브러리 개념) | |
인스턴스화 | 가능 | 불가능 |
용도 | 객체생성 | 믹스인. namespace |
super class | module | object |
메소드 | 클래스 메소드 & 인스턴스 메소드 | 모듈 메소드 & 인스턴스 메소드 |
상속 | 가능 | 불가능 |
include | 불가능 | 다른 클래스나 모듈에서 include가능 |
extend | 불가능 | 가능 |