상세 컨텐츠

본문 제목

[Python 파이썬 독학 7-2일차]

파이썬 스터디/파이썬-Python 기본편

by 후즈테크 2020. 9. 28. 23:58

본문

반응형

2. 매서드

  : class 내 정의된 함수

 

# 기존 생성되어 있던 일반 유닛 외 공격 유닛 class 를 생성한다.

  - class 명 : AttackUnit 

  - Unit 을 생성할 때와 동일하게 name, hp, damage 를 변수로 받는다.

  - 아래 조건의 함수들을 추가한다.

  - 공격 유닛은 attack(location) 값을 통해 특정 위치를 공격 할 수 있다.

  - damaged 함수를 통해 공격을 받을 경우, 체력(hp)가 감소하며, 0 이하 일 경우, 파괴된다.

# 일반 유닛
class Unit:
    def __init__(self, name, hp, damage):
        self.name = name
        self.hp = hp
        self.damage =damage
        print("{0} 유닛이 생성되었습니다." .format(self.name))
        print("체력 {0}, 공격력 {1}\n" .format(self.hp, self.damage))


# 공격 유닛
class AttackUnit:
    def __init__(self, name, hp, damage):  # self.* 는 자기 자신을 의미, 클래스 내에서 메소드 앞에 self를 입력 자기자신의 변수에 접근 가능
        self.name = 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))

 

# 실제 파이어뱃 생산 및 공격, 피해 시나리오

# 공격 유닛
class AttackUnit:
    def __init__(self, name, hp, damage):  # self.* 는 자기 자신을 의미, 클래스 내에서 메소드 앞에 self를 입력 자기자신의 변수에 접근 가능
        self.name = 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시")

#공격 2번 받는다고 가정
firebat1.damaged(25)
firebat1.damaged(25)

'''결과 값 :
파이어뱃 : 5시 방향으로 적군을 공격합니다.[공격력 16]
파이어뱃 : 25 데미지를 입었습니다.
파이어뱃 : 현재 체력은 25 입니다.
파이어뱃 : 25 데미지를 입었습니다.
파이어뱃 : 현재 체력은 0 입니다.
파이어뱃 : 파괴되었습니다.
'''

반응형

 

3. 상속

 : 다른 class( 부모 class 라고 부름) 에서 필요한 파라미터 들을 전달 받아(상속) 자식 class 에서 사용하게 되는 것.

  -> class 간 중복되어 사용되는 항목이 있을 경우, 사용

 

# 매딕 : 의무병 / 공격력 없음

 

매딕의 경우, 공격력이 없는 일반 유닛이므로, 일반 유닛 클래스의 damage 항목을 없애고, 공격 유닛 클래스에서 damage를 설정한다.

 

기존 공격 유닛의 경우, name, hp, damage 가 일반 유닛과 중복되므로, 위의 코딩을 아래와 같이 변경 할 수 있다.

 

  - class 자식class(부모class) 형태로 표기.

  - __init__ 함수내 상속 받는 항목에 대해 초기화를 진행해줌

    ex) Unit.__init__(self, name, hp)

# 일반 유닛
class Unit: # 대소문자 구분함
    def __init__(self, name, hp):
        self.name = name
        self.hp = hp
        

# 공격 유닛
class AttackUnit(Unit): # () 안에 상속 받고 싶은 class 입력
    def __init__(self, name, hp, damage):  # self.* 는 자기 자신을 의미, 클래스 내에서 메소드 앞에 self를 입력 자기자신의 변수에 접근 가능
        Unit.__init__(self, name, hp) # Unit 에서 공통으로 받는 값
        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시")

#공격 2번 받는다고 가정
firebat1.damaged(25)
firebat1.damaged(25)


''' 결과 값 :
파이어뱃 : 5시 방향으로 적군을 공격합니다.[공격력 16]
파이어뱃 : 25 데미지를 입었습니다.
파이어뱃 : 현재 체력은 25 입니다.
파이어뱃 : 25 데미지를 입었습니다.
파이어뱃 : 현재 체력은 0 입니다.
파이어뱃 : 파괴되었습니다.
'''

 

4. 다중 상속

 : 2개 이상의 부모 class를 갖는 것.

 

지상 유닛 외, 비행이 가능한 유닛들에 관한 class 를 생성

 - 비행 기능만 있는 class = Flyable

 

 

# 드랍쉽  : 공중 유닛, 수송기. 마린 / 파이어뱃 / 탱크 등을 수송. 공격 X

 드랍쉽 등 비행은 가능하나, 공격 기능이 없는 유닛의 경우, Flyable class 를 통해 유닛 생성 가능.

 

# 발키리 : 공중 유닛, 한번에 14발 미사일 발사. / 비행 + 공중 공격 속성을 가짐

 

비행 + 공중 공격이 가능한 클래스를 생성(FlyableAttackUnit)

Flyable 과 AttackUnit 2개의 class 에서 상속을 받음.

class FlyableAttackUnit(AttackUnit, Flyable):

# 일반 유닛
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) # Unit 에서 공통으로 받는 값
        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))

# 드랍쉽 : 공중 유닛, 수송기. 마린 / 파이어뱃 / 탱크 등을 수송. 공격 X


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




# # 발키리 : 공중 유닛, 한번에 14발 미사일 발사.
valkyrie = FlyableAttackUnit("발키리", 200, 6, 5)
valkyrie.fly(valkyrie.name, "3시")

# 결과 값 : 발키리 : 3시 방향으로 날아갑니다. [속도 5]

 

5. 매소드 오버라이딩

 : 자식 클래스에서 정의한 매소드 사용

 

# 일반 유닛 - speed 추가

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 입력 / speed 추가
    def __init__(self, name, hp, speed, damage):  
        Unit.__init__(self, name, hp, speed) # Unit 에서 공통으로 받는 값, 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)  # 지상 speed = 0 , flying_speed 값이 있음
        Flyable.__init__(self, flying_speed)


# 벌쳐 : 지상 유닛, 기동성이 좋음

vulture = AttackUnit("벌처", 80, 10, 20)


# 배틀크루저 : 공중 유닛, 체력도 굉장히 좋음, 공격력도 좋음.
battlecruiser = FlyableAttackUnit("배틀크루저", 500, 25, 3)

vulture.move("11시")
battlecruiser.fly(battlecruiser.name, "9시")

''' 결과 값 :
[지상 유닛 이동]
벌처 : 11시 방향으로 이동합니다. [속도 : 10]
배틀크루저 : 9시 방향으로 날아갑니다. [속도 3]
'''

  - 일반 유닛에도 speed 값을 할당하고, 

  - 위와 같이 내용을 구성 할 수 있으나,

   이동이 필요할 경우, 지상유닛은 move, 공중유닛은 fly를 구분하여 사용해야 하는 번거로움이 있다.

 

# 매서드 오버라이딩(자식 클래스에서 함수 저장) 하여 해당 코딩을 move로 통일 시켜 줄 수 있다.

# FlyableAttackUnit Class 내에 move 함수 추가.

 

# 일반 유닛
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 입력 / speed 추가
    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)  # 지상 speed = 0 , flying_speed 값이 있음
        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시")


''' 결과 값 :
[지상 유닛 이동]
벌처 : 11시 방향으로 이동합니다. [속도 : 10]
[공중 유닛 이동
배틀크루저 : 9시 방향으로 날아갑니다. [속도 3]
'''

이전 코딩과 비교 시, class FlyableAttackUnit 내에 def move 를 추가하여,

공중 유닛도 move 함수로 사용할 수 있게 된다.

 

변경 전 변경 후
class 코딩 :

class
 FlyableAttackUnit(AttackUnitFlyable):

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

class 코딩 :

class
 FlyableAttackUnit(AttackUnitFlyable):

    def __init__(selfnamehpdamageflying_speed):
        AttackUnit.__init__(self, name, hp, 0, damage)  # 지상 speed = 0 , flying_speed 값이 있음
        Flyable.__init__(self, flying_speed)


    def move(selflocation):
        print("[공중 유닛 이동")
        self.fly(self.name, location)
호출 코딩 :

vulture.move(
"11시")

battlecruiser.fly(battlecruiser.name, "9시")
호출 코딩 :

vulture.move(
"11시")

battlecruiser.move("9시")
결과 값 : 

[지상 유닛 이동]
벌처 : 11시 방향으로 이동합니다. [속도 : 10]
배틀크루저 : 9시 방향으로 날아갑니다. [속도 3]
결과 값 : 

[지상 유닛 이동]
벌처 : 11시 방향으로 이동합니다. [속도 : 10]
[공중 유닛 이동] 
배틀크루저 : 9시 방향으로 날아갑니다. [속도 3]

 * def 내 print("[공중 유닛 이동]") 제거 시, 동일한 내용 출력 가능.

 

 

6. pass

 : 실제 정상적으로 코딩된 것 처럼 처리.

# 건물을 지을 경우,

# 일반 유닛
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 BuildingUnit(Unit):
    def __init__(self, name, hp, location):
        pass # 정상적으로 작성된 것 처럼 동작

# 서플라이 디폿 : 건물, 1개 건물 = 8 유닛.


supply_depot = BuildingUnit("서플라이 디폿", 500, "7시") # 정상동작


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

def game_end():
    pass

game_start()
game_end()


# 결과 값 : [알림] 새로운 게임을 시작합니다.

 

BuildingUnit 의 클래스 내부 매서드 및 gate_end 함수의 경우, 실제 코딩을 작성하지 않고, pass라고 입력하여

코딩 내용과 상관없이 정상동작하는 듯한 역할을 보여줄 수 있다.

 

 

7. super

 : 상속 받는 기능으로 사용하나, 다중 상속 시 차이가 발생한다.

   -> 첫번째 클래스만 상속 받음.

 : 대신 self를 사용하지 않아 단일 상속 시에는 간략하게 사용할 수 있다.

 

# 기존 상속 방법

#건물
class BuildingUnit(Unit):
    def __init__(self, name, hp, location):
        Unit.__init__(self, name, hp, 0) # 을 super를 사용하여 변경할 경우
        self.location = location

 

# super 사용

#건물 
class BuildingUnit(Unit):
    def __init__(self, name, hp, location):
        super().__init__(name, hp, 0) # 괄호를 붙이고 self 를 제외한다. # 다중상속 시 차이가 남
        self.location = location

 

위의 두 코딩은 같은 결과 값을 산출한다.

 

 

# 다중 상속 시 차이점을 확인하기 위해 부모 클래스를 간략히 재구성해보면

 

 case 1. class FlyableUnit(Unit, Flyable):

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

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

class FlyableUnit(Unit, Flyable):
    def __init__(self):
        super().__init__()

# 드랍쉽
dropship = FlyableUnit() #을 출력할 경우, super가 다중상속을 받으면 앞의 class만 상속받음. 다중상속시에는 Unit.__init__(self) 와 Flyable.__init__(self) 를 적용

# 결과 값 : Unit 생성자

 

 case 2. class FlyableUnit(Flyable, Unit):

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

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

class FlyableUnit(Flyable, Unit):
    def __init__(self):
        super().__init__()

# 드랍쉽
dropship = FlyableUnit() #을 출력할 경우, super가 다중상속을 받으면 앞의 class만 상속받음. 다중상속시에는 Unit.__init__(self) 와 Flyable.__init__(self) 를 적용

# 결과 값 : Flyable 생성자

 

case 1과 2 가 super로 상속 받을 경우, 앞쪽에 상속받는 클래스에 대한 값만 상속 받아 2 코딩의 결과 값이 다르게 나타난다. 다중상속시에는 사용을 피해야한다.

 

유튜버 '나도코딩' 님의 영상을 보며 공부 및 노트 작성합니다.

 

함께 공부해 나가실 분은

www.youtube.com/watch?v=kWiCuklohdY&feature=youtu.be

 

 

반응형

관련글 더보기

댓글 영역