파이썬/파이썬 기초

파이썬 기초 05 - 미니프로젝트/예외처리

H-V 2021. 10. 30. 18:03

유투버 '나도코딩'님 강의 참조

 

 

01 스타크래프트 미니 프로젝트

from random import *

class Unit: #클래스 선언
    def __init__(self, name, hp, speed): #생성자
        self.name = name
        self.hp = hp
        self.speed = speed
        print("{0} is ready".format(name))
    
    def move(self, location):
        print("Unit is movig")
        print("{0} : is heading to {1} [속도 {2}]".format(self.name, location, self.speed))

    def damaged(self, damaged):
        print("{0} is under attack [{1} damaged]".format(self.name, damaged))
        self.hp -= damaged
        print("{0} : HP:{1}".format(self.name, self.hp))
        if self.hp <= 0:
            print("{0} is dead".format(self.name))

class AttackUnit(Unit):
    def __init__(self, name, hp, speed, damage): #생성자
        Unit.__init__(self, name, hp, speed) #상속받는 클래스에서 파라미터를 받음
        self.damage = damage

    def attack(self, location):
        print("{0} is attacking to {1} location. [Damege {2}]".format(self.name, location, self.damage))

class Marine(AttackUnit):
    def __init__(self):
        AttackUnit.__init__(self, "Marine", 40, 1, 5)
    
    def stimpack(self):
        if self.hp > 10:
            self.hp -= 10
            print("{0} : Stimpack! (Used 10 HP)".format(self.name))
        else:
            print("{0} : Not enough HP")

class Tank(AttackUnit):

    seize_mode = False

    def __init__(self):
        AttackUnit.__init__(self,"Tank", 150, 1, 35)
        self.seize_mode = False

    def set_seize_mode(self):
        if Tank.seize_mode == False:
            return
        
        if self.seize_mode == False:
            print("{0} : on Seize-Mode".format(self.name))
            self.damage *= 2
            self.seize_mode = True

        else:
            print("{0} : back to normal".format(self.name))
            self.damage /= 2
            self.seize_mode = False


class Flyable:
    def __init__(self, flying_speed):
        self.flying_speed = flying_speed

    def fly(self, name, location):
        print("{0} is flying to {1}. [Speed {2}]".format(name, location, self.flying_speed))

class FlyableAttackUnit(AttackUnit, Flyable):
    def __init__(self, name, hp, damage, flying_speed):
        AttackUnit.__init__(self, name, hp, 0, damage)
        Flyable.__init__(self, flying_speed)

    def move(self, location):
        print("Moving")
        self.fly(self.name, location)


class Wraith(FlyableAttackUnit):
    def __init__(self):
        FlyableAttackUnit.__init__(self, "Wraith", 80, 20, 5)
        self.clocked = False

    def clocking(self):
        if self.clocked == True:
            print("{0} : back to normal".format(self.name))
            self.clocked = False
        else:
            print("{0} : on Clocking".format(self.name))
            self.clocked = True

 

  • 메소드 써보기
def game_start():
    print("Game is starting")

def game_over():
    print("Player : GG")
    print("[Player] left the game")

game_start()

m1 = Marine()
m2 = Marine()

t1 = Tank()
t2 = Tank()

w1 = Wraith()

#유닛 일괄 관리
attack_units = []
attack_units.append(m1)
attack_units.append(m2)
attack_units.append(t1)
attack_units.append(t2)
attack_units.append(w1)

#전군 이동
for unit in attack_units:
    unit.move("South")

#시즈모드 개발
Tank.seize_mode = True
print("Seize-Mode upgraded")

#공격 모드
for unit in attack_units:
    if isinstance(unit, Marine):
        unit.stimpack()
    elif isinstance(unit, Tank):
        unit.set_seize_mode()
    elif isinstance(unit, Wraith):
        unit.clocking()

#전군 공격
for unit in attack_units:
    unit.attack("South")

#전군 피해
for unit in attack_units:
    unit.damaged(randint(5, 20))

#게임 종료
game_over()
더보기

Game is starting
Marine is ready
Marine is ready
Tank is ready
Tank is ready
Wraith is ready
Unit is movig
Marine : is heading to South [속도 1]
Unit is movig
Marine : is heading to South [속도 1]
Unit is movig
Tank : is heading to South [속도 1]
Unit is movig
Tank : is heading to South [속도 1]
Moving
Wraith is flying to South. [Speed 5]
Seize-Mode upgraded
Marine : Stimpack! (Used 10 HP)
Marine : Stimpack! (Used 10 HP)
Tank : on Seize-Mode
Tank : on Seize-Mode
Wraith : on Clocking
Marine is attacking to South location. [Damege 5]
Marine is attacking to South location. [Damege 5]
Tank is attacking to South location. [Damege 70]
Tank is attacking to South location. [Damege 70]
Wraith is attacking to South location. [Damege 20]
Marine is under attack [16 damaged]
Marine : HP:14
Marine is under attack [11 damaged]
Marine : HP:19
Tank is under attack [16 damaged]
Tank : HP:134
Tank is under attack [8 damaged]
Tank : HP:142
Wraith is under attack [18 damaged]
Wraith : HP:62
Player : GG
[Player] left the game

 

 

퀴즈)

class House:
    def __init__(self, location, house_type, deal_type, price, completion_year):
        self.location = location
        self.house_type = house_type
        self.deal_type = deal_type
        self.price = price
        self.completion_year = completion_year

    def show_detail(self):
        print(self.location, self.house_type, self.deal_type, self.price, self.completion_year)

houses = []
house1 = House("강남", "아파트", "매매", "10억", "2010년")
house2 = House("마포", "오피스텔", "전세", "5억", "2007년")
house3 = House("송파", "빌라", "월세", "500/50", "2000년")
houses.append(house1)
houses.append(house2)
houses.append(house3)

print("총 {0}대의 매물이 있습니다.".format(len(houses)))
for house in houses:
    house.show_detail()
    
총 3대의 매물이 있습니다.
강남 아파트 매매 10억 2010년
마포 오피스텔 전세 5억 2007년
송파 빌라 월세 500/50 2000년

 

 

02 예외처리

  • 프로그래밍상에서 에러가 떳을때 처리하는 방법
print("Only to devide")
num1 = int(input("Enter first number -> "))
num2 = int(input("Enter second number -> "))
print("{0} / {1} = {2}".format(num1, num2, int(num1/num2)))

*int(input())인데 스트링을 넣으면 아래와 같은 오류가 뜬다

  • 이때 예외처리를 할 수 있다!
try:
    print("Only to devide")
    num1 = int(input("Enter first number -> "))
    num2 = int(input("Enter second number -> "))
    print("{0} / {1} = {2}".format(num1, num2, int(num1/num2)))
except ValueError:
    print("That is not a correct input")

→ 즉 오류도 종류가 많은데 오류의 종류를 'except'와 함께 선언해주면 개발자가 직접 예외처리를 해 줄 수 있다. 

  • 0을 입력하면 오류의 종류가 다르다!
try:
    print("Only to devide")
    num1 = int(input("Enter first number -> "))
    num2 = int(input("Enter second number -> "))
    print("{0} / {1} = {2}".format(num1, num2, int(num1/num2)))
except ValueError:
    print("That is not a correct input")
except ZeroDivisionError as err:
    print(err)

 

 

  • 한번에 모든 예외 처리도 가능하다
    except:
        print("an Error occured")​

 

 

03 예외 발생 시키기

  • 'raise ...' 구문을 써서 어떠한 상황이면 raise 예외종류 를 써서 except로 바로 넘길 수 있다. 
try:
    print("Only one digit devide")
    num1 = int(input("Enter first number -> "))
    num2 = int(input("Enter second number -> "))
    if num1 >= 10 or num2 >= 10:
        raise ValueError
    print("{0} / {1} = {2}".format(num1, num2, int(num1/num2)))
except ValueError:
    print("Wrong value. Only one digit")
    
Only one digit devide
Enter first number -> 10
Enter second number -> 5
Wrong value. Only one digit

 

  • 사용자 정의 예외 처리
class BigNumberError(Exception):
    def __init__(self, msg):
        self.msg = msg
    
    def __str__(self):
        return self.msg

try:
    print("Only one digit devide")
    num1 = int(input("Enter first number -> "))
    num2 = int(input("Enter second number -> "))
    if num1 >= 10 or num2 >= 10:
        raise BigNumberError("입력값 : {0}, {1}".format(num1, num2))
    print("{0} / {1} = {2}".format(num1, num2, int(num1/num2)))
except ValueError:
    print("Wrong value. Only one digit")
except BigNumberError as err:
    print("An error occured. Only one Digit")
    print(err)
    
An error occured. Only one Digit
입력값 : 10, 5
  • finally - 예외와 상관없이 무조건 실행하도록 하는 구문 (finally를 쓰면 프로그램이 강제 종료되는것을 막을 수 있음)
    finally:
        print("Thanks for using this!")​

 

퀴즈

조건1) 1보다 작거나 숫자가 아니면 ValueError로 처리
조건2) 치킨이 모두 소준되면 사용자 정의 에러'SoldOutError' 발생 시키고 프로그램 종료



class SoldOutError(Exception):
    pass

chicken = 10
waiting = 1

while(True):
    try:
        print("Left chicken : {0}".format(chicken))
        order = int(input("How many chickens do you want -> "))
        if order > chicken:
            print("No more chickens")
        elif order <= 0:
            raise ValueError
        else:
            print("Waiting number [{0}]. {1} chicken(s) ordered.".format(waiting,order))
            waiting += 1
            chicken -= order
        if chicken == 0:
            raise SoldOutError
    except ValueError:
        print("Wrong order")
    except SoldOutError:
        print("No more chickens")
        break