파이썬(Python)

파이썬 - 클래스(2)

BlueNoa 2023. 2. 8. 18:01
728x90
반응형

2023.01.25 - [파이썬] - 파이썬 - 클래스(1)

 

파이썬 - 클래스(1)

•클래스(Class) 클래스는 새로운 타입(Type)을 만드는 설계도라고 할 수 있다. 클래스의 작동 구성요소(멤버)로는 멤버 변수(속성), 메서드(행위)로 볼 수 있다. 클래스를 통해서 만들어진 것을 객

bluenoa.tistory.com

 

이전 게시글 내용에 이어서 작성되는 내용이므로 참고

 

•클래스(Class)

클래스는 또 다른 클래스를 불러서 사용할 수 있다.

전에 설명했듯이 다른 클래스에서 현재 클래스를 멤버로 사용할 수 있다.

즉, 클래스를 객체로 만들어서 사용할 수 있다는 것이며 이는 곧 객체지향적인 프로그램의 조립식 프로그래밍을 의미한다.

클래스의 포함 관계에 대한 예시를 보자.

반응형

(예시1) 로또 번호를 뽑는 클래스의 포함 관계

import random as r

class Ball: # 공을 생성할 것
    def __init__(self, num):
        self.num = num
        
class Machine: # 공을 뽑을 것
    def __init__(self):
        self.ball_list = [] # 전체 공을 저장할 공간
        for i in range(1, 46):
            self.ball_list.append(Ball(i)) # 다른 클래스를 불러와서 포함
        # print(self.ball_list) # 현재 ball_list는 '<__main__.Ball object at 0x000002775D227640>'
        # 의 형태로 저장되어 있다. 그렇기 때문에 Ball 클래스의 num을 안써주면 주소가 출력된다.
        # 결론은 Machine클래스의 ball_list[자릿수].num 으로 작성해야지 숫자가 출력된다.
        
    def select_ball(self):
        save = []
        for i in range(45):
            save.append(self.ball_list[i].num)
        result = r.sample(save, k=7) # sample은 중복을 허용하지 않고 랜덤하게 뽑는다.
        # print(result) # 7개의 숫자가 정상적으로 출력되는 것을 확인
        return result
    
class show_lotto:
    def __init__(self):
        self.Machine = Machine() # 공을 뽑은 클래스의 결과를 가져온다.
    
    def show(self):
        select_ball = self.Machine.select_ball()
        print('당첨 번호 + 보너스 번호')
        for i in select_ball:
            print('%d' % i, end=' ')
            
if __name__ == '__main__': # 현재 작성한 곳이 main이면 실행해라.
    lotto = show_lotto()
    lotto.show()
    # show_lotto().show() # 같은 명령어이다.

* r.seed 명령어로 난수표를 고정해주지 않았기 때문에 매 실행마다 결과는 달라질 수 있다.

당첨 번호 + 보너스 번호
12 18 25 28 37 10 32 

(예시2) 게임 인벤토리에 아이템을 저장하기(클래스의 포함 관계)

# 인벤토리에 아이템 저장하기
class inventory:
    isopen = False # 처음 인벤토리는 닫혀있어야 한다.
    item = [] # 아이템 이름 정보를 담는 변수
    
    def open(self): # 인벤토리 열기
        self.isopen = True # 열기로 인식
        print('인벤토리 열기')
        
    def close(self):
        self.isopen = False # 닫기로 인식
        print('인벤토리 닫기')
        
    def pickup_item(self, thing):
        if self.open:
            self.item.append(thing) # 아이템을 습득해서 추가
            print(thing.name, '아이템을 습득하였습니다.')
            self.item_list() # 리스트에 저장
            
        else:
            print('인벤토리를 열지 않음.')
            
    def item_list(self):
        n = 1
        for i in self.item:
            print('현재 아이템 목록{0}'.format(n), ':' , i.name, i.quantity)
            n += 1
            
class item_data:
    def __init__(self, name, quantity):
        self.name = name
        self.quantity = quantity
        # print(self.name, self.quantity) # 확인용

inven = inventory()
weapon = item_data('소방 도끼', '1') # 개수를 문자로 넣어서 리스트에 넣는다.

inven.open()
inven.pickup_item(weapon)
inven.close()
print('-'*15)
food = item_data('신선한 야생 딸기', '5')
inven.open()
inven.pickup_item(food)
inven.close()
인벤토리 열기
소방 도끼 아이템을 습득하였습니다.
현재 아이템 목록1 : 소방 도끼 1
인벤토리 닫기
---------------
인벤토리 열기
신선한 야생 딸기 아이템을 습득하였습니다.
현재 아이템 목록1 : 소방 도끼 1
현재 아이템 목록2 : 신선한 야생 딸기 5
인벤토리 닫기

(예시3) 코인 세탁기 작동하기

# 코인 세탁기
class coin:
    laundry_type = {1:'표준', 2:'섬세', 3:'이불'}
    def __init__(self):
        self.coin = int(input('돈을 넣어주세요.')) # 문자열 값을 인수형태로 변환
        print('세탁 종류 : 1=표준, 2=섬세, 3=이불')
        self.type = int(input('세탁 종류를 입력하세요.'))
        if self.type == 1:
            self.req = 2000
        elif self.type == 2:
            self.req = 3000
        elif self.type == 3:
            self.req = 5000
        self.change = (self.coin - self.req) # 잔돈
        self.insufficient = (int(self.req) - self.coin) # 부족한 경우의 금액
        
    def calculation(self): # 금액 정산
        if self.coin < self.req:
            insufficient = (int(self.coins.req) - int(self.coin)) # 부족한 금액
            print('돈이 부족합니다.')
            return insufficient
        else:
            change = (self.coins.coin - self.coins.req) # 잔돈
            return change
            
        
class washing_machine:
    def __init__(self):
        self.coins = coin()
    
    def show_data(self): # 마지막 출력 정보
        if self.coins.change < 0:
            print(self.coins.insufficient, '원 부족합니다.')
        else:
            print('세탁 종류 : ', self.coins.laundry_type[self.coins.type], '| 금액 : ', self.coins.req, '| 잔돈 : ', self.coins.change)
        
        
a = washing_machine()
a.show_data()

금액은 2500, 세탁 종류는 1(표준)을 입력했다.

돈을 넣어주세요.2500
세탁 종류 : 1=표준, 2=섬세, 3=이불
세탁 종류를 입력하세요.1
세탁 종류 :  표준 | 금액 :  2000 | 잔돈 :  500

•클래스(Class) 메서드와 정적(Static) 메서드

클래스 메서드는 '@classmethod'를 사용해서 선언할 수 있다. 전에 다뤘던 인스턴스 메서드가 아닌 클래스 자체가 첫 번째 매개 변수가 된다. 그 첫 번째 매개 변수를 클래스에 포함된 함수들이 self를 사용했던 것처럼 'cls'라고 관행적으로 표현한다. 클래스 메서드는 cls를 통해서 클래스 속성(attribute)에 접근하거나, 클래스 메서드를 호출할 수 있다.

하지만 인스턴스 메서드와는 다르게 인스턴스 속성에 접근하거나 다른 인스턴스 메서드를 호출하는 것은 불가능하다.

 

정적 메서드는 '@staticmethod'를 사용해서 선언할 수 있다. 정적 메서드는 인스턴스 메서드나 클래스 메서드와는 다르게 첫 번째에 매개변수가 할당되지 않는다. 그렇기 때문에 인스턴스나 클래스 속성에 대한 접근, 호출하는 것은 불가능하다.

클래스 내부에 존재하는 순수한 함수라고 볼 수 있다. 이때 비슷한 기능을 하는 함수들을 묶어두고 싶은 경우 정적 메서드로 선언하여 클래스로 결합시켜 놓는 것이다.

# 총알 장전!
class reload:
    bullet = 0
    def __init__(self):
        reload.bullet += 1 # 처음 인스턴스가 생성될 때 1발씩 넣어주게 된다.
        print('장전, {0}'.format(reload.bullet))
        if reload.bullet == 7:
            print('총알이 꽉 찼습니다.')
            return
    
    @classmethod
    def shoot(cls, ammo, target): # cls에는 class가 할당되어 있다.
        if reload.bullet != 0:
            reload.bullet -= 1
            print(target, ammo,'탄 발사! {0}발 남았습니다.'.format(cls.bullet)) # cls로 클래스 속성에 접근한다.
    
    @staticmethod
    def grenade(ammount):
        print('수류탄 '+str(ammount)+'개 투척')
    
gun = reload() # 처음 호출에 장전 1번
gun.__init__() # 임의로 호출하여 장전 2번

# 바로 클래스 명으로 호출할 수 있다.
reload.shoot('9mm', '100M') # 1발 발사, 1발 남음
reload.grenade(2)
장전, 1
장전, 2
100M 9mm 탄 발사! 1발 남았습니다.
수류탄 2개 투척

 

 

728x90
반응형