[Python] 나도코딩 기본편 - (6)

Updated:

유튜브 나도코딩 무료 강의를 통해 학습한 내용을 정리해서 올리고 있습니다.

실습과정에서 필요에 따라 일부 강의 내용의 누락 및 추가, 수정사항이 있습니다.

퀴즈의 경우, 유튜브 풀이와 상이할 수 있습니다.


class 함수

# __init__: 생성자 / 
# 멤버 변수: self.변수
class Unit:
    def __init__(self, name, hp, damage):
        self.name = name
        self.hp = hp
        self.damage = damage
        print(f"{self.name} 유닛이 생성되었습니다.")
        print(f"체력 {self.hp} 공격력 {self.damage}")
        print("-"*40)

marine1 = Unit("마린", 40, 5) # 유닛 클래스의 인스턴스
marine2 = Unit("마린", 40, 5)
tank = Unit("탱크", 150, 35)

wraith1 = Unit("레이스", 80, 5)
print("유닛 이름: {0}, 공격력: {1}".format(wraith1.name,wraith1.damage))

wraith2 = Unit("빼앗긴 레이스", 80, 5)
wraith2.clocking = True

if wraith2.clocking == True:
    print("{0}는 현재 클로킹 상태입니다.".format(wraith2.name))
마린 유닛이 생성되었습니다.
체력 40 공격력 5
----------------------------------------
마린 유닛이 생성되었습니다.
체력 40 공격력 5
----------------------------------------
탱크 유닛이 생성되었습니다.
체력 150 공격력 35
----------------------------------------
레이스 유닛이 생성되었습니다.
체력 80 공격력 5
----------------------------------------
유닛 이름: 레이스, 공격력: 5
빼앗긴 레이스 유닛이 생성되었습니다.
체력 80 공격력 5
----------------------------------------
빼앗긴 레이스는 현재 클로킹 상태입니다.
  • class() 함수로 직접 특정 class를 생성 할 수 있다.

  • 파이썬의 패키지 numpy, pandas등에 배열, 데이터 프레임과 같은 클래스가 존재하고 클래스에 속성과 메소드 등이 포함되어 있다.

  • 어떠한 클래스에 대해 이해하고 있으면 파이썬을 진행하면서 직관적인 이해가 잘된다.

메소드

class AttackUnit:
    def __init__(self, name, hp, damage):
        self.name = name
        self.hp = hp
        self.damage = damage
        
    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격중입니다. [공격력 {2}]"\
            .format(self.name, location, self.damage))

    def damaged(self, damage):
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <=0:
            print("{0} : 파괴되었습니다.".format(self.name))

firebat1 = AttackUnit("파이어뱃", 50, 16)
firebat1.attack("5시")

firebat1.damaged(25)
firebat1.damaged(25)
파이어뱃 : 5시 방향으로 적군을 공격중입니다. [공격력 16]
파이어뱃 : 25 데미지를 입었습니다.
파이어뱃 : 현재 체력은 25 입니다.
파이어뱃 : 25 데미지를 입었습니다.
파이어뱃 : 현재 체력은 0 입니다.
파이어뱃 : 파괴되었습니다.
  • 단순하게 이해하기로 메소드는 클래스 내에 존재하는 함수이다.

  • name, age, damage 등은 클래스 내에 속성이다.

  • 특정 클래스의 객체는 인스턴스라고 표현한다.

class 상속

class Unit:
    def __init__(self, name, hp):
        self.name = name
        self.hp = hp


class AttackUnit(Unit): # (받을 class)
    def __init__(self, name, hp, damage):
        Unit.__init__(self, name, hp)
        self.damage = damage
        
    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격중입니다. [공격력 {2}]"\
            .format(self.name, location, self.damage))

    def damaged(self, damage):
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <=0:
            print("{0} : 파괴되었습니다.".format(self.name))
  • 상속은 클래스를 정의할 때 다른 클래스 정보를 받아 만드는 기능이다.

다중 상속

# 일반 유닛
class Unit:
    def __init__(self, name, hp):
        self.name = name
        self.hp = hp

# 공격 유닛
class AttackUnit(Unit): # (받을 class)
    def __init__(self, name, hp, damage):
        Unit.__init__(self, name, hp)
        self.damage = damage
        
    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격중입니다. [공격력 {2}]"\
            .format(self.name, location, self.damage))

    def damaged(self, damage):
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <=0:
            print("{0} : 파괴되었습니다.".format(self.name))

# 공중 유닛
class Flyable:
    def __init__(self, flying_speed):
        self.flying_speed = flying_speed

    def fly(self, name, location):
        print("{0} : {1} 방향으로 날아갑니다. [속도 {2}]"\
            .format(name, location, self.flying_speed))

# 공중 공격 유닛
class FlyableAttackUnit(AttackUnit, Flyable):
    def __init__(self, name, hp, damage, flying_speed):
        AttackUnit.__init__(self, name, hp, damage)
        Flyable.__init__(self, flying_speed)

valkyrie = FlyableAttackUnit("발키리", 200, 6, 5)
valkyrie.fly(valkyrie.name,"3시")
valkyrie.damaged(20)
발키리 : 3시 방향으로 날아갑니다. [속도 5]
발키리 : 20 데미지를 입었습니다.
발키리 : 현재 체력은 180 입니다.
  • 클래스는 상속 받은 클래스를 상속 받을 수 있으며, 여러 클래스를 상속 받을 수 있다.

  • 여기선 AttackUnit은 Unit을 상속 받았고, FlyableAttackUnit은 AttackUnit과 Flyable을 상속 받았다.

메소드 오버라이딩

# 일반 유닛
class Unit:
    def __init__(self, name, hp, speed):
        self.name = name
        self.hp = hp
        self.speed = speed

    def move(self, location):
        print("[지상 유닛 이동]")
        print("{0} : {1} 방향으로 이동합니다. [속도 {2}]"\
            .format(self.name, location, self.speed))


# 공격 유닛
class AttackUnit(Unit): # (받을 class)
    def __init__(self, name, hp, speed, damage):
        Unit.__init__(self, name, hp, speed)
        self.damage = damage
        
    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격중입니다. [공격력 {2}]"\
            .format(self.name, location, self.damage))

    def damaged(self, damage):
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <=0:
            print("{0} : 파괴되었습니다.".format(self.name))

# 공중 유닛
class Flyable:
    def __init__(self, flying_speed):
        self.flying_speed = flying_speed

    def fly(self, name, location):
        print("{0} : {1} 방향으로 날아갑니다. [속도 {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) # 지상 스피드 0
        Flyable.__init__(self, flying_speed)

    def move(self, location):
        print("[공중 유닛 이동]")
        self.fly(self.name, location)

vulture = AttackUnit("벌쳐", 80, 10, 20)
battlecruiser = FlyableAttackUnit("배틀크루저", 500, 25, 3)

vulture.move("11시")
battlecruiser.move("9시")

battlecruiser.fly(battlecruiser.name,"9시")
[지상 유닛 이동]
벌쳐 : 11시 방향으로 이동합니다. [속도 10]
[공중 유닛 이동]
배틀크루저 : 9시 방향으로 날아갑니다. [속도 3]
배틀크루저 : 9시 방향으로 날아갑니다. [속도 3]
  • FlyableAttackUnit은 Unit을 상속받은 AttackUnit을 상속받았다.

  • 여기서 Unit은 move라는 메소드를 가지고 있으며 FlyableAttackUnit 역시 move라는 메소드를 가지고 있다.

  • Unit이나 AttackUnit 클래스의 객체는 move 메소드를 사용시 Unit의 move 함수가 적용된다.

  • FlyableAttackUnit 클래스의 객체는 move 메소드를 사용시 FlyableAttackUnit의 move 함수가 적용된다(메소드 오버라이딩).

pass, super

# pass : 우선 완성된 것 처럼 마무리하고 넘어간다
class BuildingUnit(Unit):
    def __init__(self, name, hp, location):
        pass

supply_depot = BuildingUnit("서플라이 디폿", 500, "7시")

# super
class BuildingUnit(Unit):
    def __init__(self, name, hp, location):
        # Unit.__init__(self, name, hp, speed)
        super().__init__(name, hp, speed) # super는 self를 안쓰고 Unit class에서 받아온다.
        self.location = location
        
# 다중상속의 super
class Unit:
    def __init__(self):
        print("Unit 생성자")

class flyable:
    def __init__(self):
        print("Flyable 생성자")

class FlyableUnit(Unit, Flyable):
    def __init__(self):
        super().__init__() # 첫 번째 class만 상속해온다.

dropship = FlyableUnit()
Unit 생성자
  • pass는 우선 완성된 것처럼 마무리하고 넘어가는 기능으로 정의는 하였지만 기능은 없다.

  • super는 상속 받을 때 좀 더 간편한 기능이나 다중 상속의 경우 첫 번째 클래스만 상속받는다.

스타크래프트 시뮬레이션

# 일반 유닛
class Unit:
    def __init__(self, name, hp, speed):
        self.name = name
        self.hp = hp
        self.speed = speed
        print("{0} 유닛이 생성되었습니다.".format(self.name))

    def move(self, location):
        print("[지상 유닛 이동]")
        print("{0} : {1} 방향으로 이동합니다. [속도 {2}]"\
            .format(self.name, location, self.speed))

    def damaged(self, damage)        :
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <=0:
            print("{0} : 파괴되었습니다.".format(self.name))

# 공격 유닛
class AttackUnit(Unit): # (받을 class)
    def __init__(self, name, hp, speed, damage):
        Unit.__init__(self, name, hp, speed)
        self.damage = damage
        
    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격중입니다. [공격력 {2}]"\
            .format(self.name, location, self.damage))

# 공중 유닛
class Flyable:
    def __init__(self, flying_speed):
        self.flying_speed = flying_speed

    def fly(self, name, location):
        print("{0} : {1} 방향으로 날아갑니다. [속도 {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) # 지상 스피드 0
        Flyable.__init__(self, flying_speed)

    def move(self, location):
        print("[공중 유닛 이동]")
        self.fly(self.name, location)

# 마린
class Marine(AttackUnit):
    def __init__(self):
        AttackUnit.__init__(self, "마린", 40, 1, 5)

    def stimpack(self):
        if self.hp > 10:
            self.hp -=10
            print("{0} : 스팀팩을 사용합니다. (HP 10 감소).".format(self.name))
        else:
            print("{0} : 체력이 부족하여 스팀팩을 사용하지 않습니다.".format(self.name))

# 시저탱크
class Tank(AttackUnit):
    seize_developed = False

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

    def set_seize_mode(self):
        if Tank.seize_developed == False:
            return
        
        if self.seize_mode == False:
            print("{0} : 시즈모드로 전환합니다.".format(self.name))
            self.damage *= 2
            self.seize_mode = True
        else:
             print("{0} : 탱크모드로 전환합니다.".format(self.name))
             self.damage /= 2
             self.seize_mode = False

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

    def clocking(self):
        if self.clocked == True:
            print("{0} : 클로킹 모드 해제합니다.".format(self.name))
            self.clocked = False
        else:
            print("{0} : 클로킹 모드 설정합니다.".format(self.name))
            self.clocked = True

def game_start():
    print("[알림] 새로운 게임을 시작합니다.")

def game_over():
    print("Player : gg")
    print("[Player] 님이 게임에서 퇴장하셨습니다.")

# 게임 시작
game_start()

# 유닛 생성
m1 = Marine()
m2 = Marine()
m3 = Marine()

t1 = Tank()
t2 = Tank()

w1 = Wraith()

# 각 클래스를 리스트에 추가
attak_units = []
attak_units.append(m1)
attak_units.append(m2)
attak_units.append(m3)
attak_units.append(t1)
attak_units.append(t2)
attak_units.append(w1)

for unit in attak_units:
    unit.move("1시")

Tank.seize_developed = True
print("[알림] 탱크 시즈모드 개발이 완료되었습니다.")


for unit in attak_units:
    if isinstance(unit, Marine):
        unit.stimpack()
    elif isinstance(unit, Tank):
        unit.set_seize_mode()
    elif isinstance(unit, Wraith):
        unit.clocking()

# 전군 공격
for unit in attak_units:
    unit.attack("1시")

from random import *

for unit in attak_units:
    unit.damaged(randint(5,20))

game_over()
[알림] 새로운 게임을 시작합니다.
마린 유닛이 생성되었습니다.
마린 유닛이 생성되었습니다.
마린 유닛이 생성되었습니다.
탱크 유닛이 생성되었습니다.
탱크 유닛이 생성되었습니다.
레이스 유닛이 생성되었습니다.
[지상 유닛 이동]
마린 : 1시 방향으로 이동합니다. [속도 1]
[지상 유닛 이동]
마린 : 1시 방향으로 이동합니다. [속도 1]
[지상 유닛 이동]
마린 : 1시 방향으로 이동합니다. [속도 1]
[지상 유닛 이동]
탱크 : 1시 방향으로 이동합니다. [속도 1]
[지상 유닛 이동]
탱크 : 1시 방향으로 이동합니다. [속도 1]
[공중 유닛 이동]
레이스 : 1시 방향으로 날아갑니다. [속도 5]
[알림] 탱크 시즈모드 개발이 완료되었습니다.
마린 : 스팀팩을 사용합니다. (HP 10 감소).
마린 : 스팀팩을 사용합니다. (HP 10 감소).
마린 : 스팀팩을 사용합니다. (HP 10 감소).
탱크 : 시즈모드로 전환합니다.
탱크 : 시즈모드로 전환합니다.
레이스 : 클로킹 모드 설정합니다.
마린 : 1시 방향으로 적군을 공격중입니다. [공격력 5]
마린 : 1시 방향으로 적군을 공격중입니다. [공격력 5]
마린 : 1시 방향으로 적군을 공격중입니다. [공격력 5]
탱크 : 1시 방향으로 적군을 공격중입니다. [공격력 70]
탱크 : 1시 방향으로 적군을 공격중입니다. [공격력 70]
레이스 : 1시 방향으로 적군을 공격중입니다. [공격력 20]
마린 : 16 데미지를 입었습니다.
마린 : 현재 체력은 14 입니다.
마린 : 15 데미지를 입었습니다.
마린 : 현재 체력은 15 입니다.
마린 : 10 데미지를 입었습니다.
마린 : 현재 체력은 20 입니다.
탱크 : 18 데미지를 입었습니다.
탱크 : 현재 체력은 132 입니다.
탱크 : 6 데미지를 입었습니다.
탱크 : 현재 체력은 144 입니다.
레이스 : 14 데미지를 입었습니다.
레이스 : 현재 체력은 66 입니다.
Player : gg
[Player] 님이 게임에서 퇴장하셨습니다.

Quiz 8

(출력 예제)

총 3대의 매물이 있습니다.

강남 아파트 매매 10억 2010년

마포 오피스텔 전세 5억 2007년

송파 빌라 월세 500/50 2000년

[코드]

class House:
    # 매물 초기화
    def __init__(self, location, house_type, deal_type, price, completion_year):
        pass
    
    # 매물 정보 표시
    def show_detail(self):
        pass
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(f"{self.location} {self.house_type} {self.deal_type} {self.price} {self.completion_year}년")
        
h1 = House("강남", "아파트", "매매", "10억", 2010)
h2 = House("마포", "오피스텔", "전세", "5억", 2007)
h3 = House("송파", "빌라", "월세", "500/20", 2000)
        
house =[]
house.append(h1)
house.append(h2)
house.append(h3)

for i in house:
    if isinstance(i, House):
        i.show_detail()
강남 아파트 매매 10억 2010년
마포 오피스텔 전세 5억 2007년
송파 빌라 월세 500/20 2000년

Leave a comment