파이썬 python
06 클래스
ynzify
2023. 5. 11. 01:35
클래스
- 변수와 함수를 묶어 놓은 개념
- 클래스는 객체 (데이터와 가능을 가지고 있는)를 만들기 위한 설계도이다
- 클래스를 메모리에 객체화 하면 그걸 인스턴스 (instance)라고 한다
클래스의 구조
- 변수
- 인스턴스 변수 (클래스가 인스턴스화 되면 참조 가능한 변수)
- 클래스 변수 (클래스 정의시에도 참조 가능한 변수)
- 함수
- 메서드
클래스를 정의하는 방법
- 클래스 이름 upper camel case (pascal case)로 명명한다
- class <ClassName>:
def __init__(self): # 보통 인스턴스 변수들을 초기화할 때 정의한다.
self.a = 10
...
def <method_name>(self):
>>> class PlayerCharacter:
>>> def __init__(self,hp,exp):
>>> self.hp = hp # 체력
>>> self.exp = exp # 경험치
>>> def attack(self):
>>> print("공격하기")
>>> self.exp += 2
>>> def defend(self):
>>> print("방어하기")
>>> self.exp += 1
>>> def attacked(self,attack_size):
>>> print("공격받음")
>>> self.hp -= attack_size
>>> class PlayerCharacter:
>>> def __init__(self,hp,exp):
>>> # 인스턴스 변수를 선언
>>> self.hp = hp
>>> self.exp = exp
>>> player1 = PlayerCharacter(100, 0)
>>> player2 = PlayerCharacter(200,50)
>>> player1.hp, player2.hp
(100, 200)
self
- 클래스가 객체화 되었을 때 자기 자신의 주소를 받는 파라미터
- 인스턴스화 되었을 때 메모리 상에 어디에 위치해 있는지를 참조하여 인스턴스에 접근 후 그 안에 인스턴스 변수와 메서드를 사용할 수 있다
- 메서드를 정의할 때는 무조건 첫번째 파라미터에 self를 정의
- 클래스를 객체화 했을 때 메서드를 사용할 때는 self를 아규먼트로 저장하지 않아도 자동으로 들어간다
클래스 변수
- 클래스 정의 후에 참조 가능한 변수
>>> class PlayerCharacter:
>>> character_type = "Wizard" # 클래스 변수
>>> def __init__(self,hp=100,exp=0):
# 인스턴스 변수
>>> self.hp = hp
>>> self.exp = exp
>>> PlayerCharacter.hp
>>> PlayerCharacter.character_type
'Wizard'
>>> player1 = PlayerCharacter()
>>> player2 = PlayerCharacter(200,20)
>>> player1.character_type, player2.character_type
('Wizard', 'Wizard')
클래스 메서드
>>> class PlayerCharacter:
>>> character_type = "Wizard" # 클래스 변수
>>> @classmethod
>>> def print_character_type(cls):
>>> print(cls.character_type)
>>> PlayerCharacter.print_character_type()
Wizard
>>> class CFG:
>>> train_dataset_path = "/data/train/"
>>> test_dataset_path = "/data/test/"
>>> model_name = "deep_model"
>>> CFG.test_dataset_path
'/data/test/'
>>> def preprocessing(cfg):
>>> print(cfg.train_dataset_path)
>>> print(cfg.test_dataset_path)
>>> print(cfg.model_name)
>>> preprocessing(CFG)
/data/train/
/data/test/
deep_model
여긴 답이 없어... 맨 땅에 해딩으로 해봐야해 따흑...
Car 클래스에 차종, 색깔, 차번호를 받아 인스턴스 변수를 초기화하는 클래스를 만들어 주세요.
>>> class Car:
>>> def __init__(self,name,color,num):
>>> self.name = name
>>> self.color = color
>>> self.num = num
>>> def info(self):
>>> print(f"차종: {self.name}, 색깔: {self.color}, 차번호: {self.num}")
>>> morning = Car("모닝","Red",1004)
>>> morning.info()
Car 클래스에 차종, 색깔, 차번호를 받아 인스턴스 변수를 초기화하는 클래스를 만들어 주세요.
>>> class Car:
>>> def __init__(self,name,color,num):
>>> self.name = name
>>> self.color = color
>>> self.num = num
>>> morning = Car("모닝","Blue",1234)
>>> print(morning.name)
>>> print(morning.color)
>>> print(morning.num)
모닝
Blue
1234
Car 클래스에 차종, 색깔, 차번호를 모두 출력하는 info라는 메소드를 만들어 보세요.
>>> class Car:
>>> def __init__(self,name,color,num):
>>> self.name = name
>>> self.color = color
>>> self.num = num
>>> def info(self):
>>> print(f"차종: {self.name}, 색깔: {self.color}, 차번호: {self.num}")
>>> morning = Car("모닝","Red",1004)
>>> morning.info()
차종: 모닝, 색깔: Red, 차번호: 1004
상속
- 구현된 클래스의 기능을 가져다가 그 기능을 수정하거나 추가할 때 사용하는 개념
- 부모 클래스의 기능과 속성을 자식 클래스가 그대로 물려받음
- 부모 클래스랑 자식 클래스가 합쳐진다는 개념
>>> class PlayerCharacter:
>>> def __init__(self,hp = 100, exp = 0):
>>> self.hp = hp
>>> self.exp = exp
>>> def attack(self):
>>> print("공격하기")
>>> self.exp += 2
>>> def defend(self):
>>> print("방어하기")
>>> self.exp += 1
>>> class Wizard(PlayerCharacter):
>>> def __init__(self,mp):
>>> self.mp = mp
>>> # python 2.x 방식
>>> # super(Wizard,self).__init__()
>>> super().__init__() # 부모클래스 __init__ 실행
>>> def magic_skill(self):
>>> print("마법 공격하기")
>>> self.mp -= 2
>>> mp = 50
>>> player = Wizard(mp)
>>> player.attack()
>>> player.defend()
>>> player.magic_skill()
>>> player.hp, player.exp, player.mp
공격하기
방어하기
마법 공격하기
(100, 3, 48)
>>> class PlayerCharacter:
>>> def __init__(self,hp = 100, exp = 0):
>>> print(f"부모 객체 주소값은: {id(self)}")
>>> self.hp = hp
>>> self.exp = exp
>>> def attack(self):
>>> print("공격하기")
>>> self.exp += 2
>>> def defend(self):
>>> print("방어하기")
>>> self.exp += 1
>>> class Wizard(PlayerCharacter):
>>> def __init__(self,mp):
>>> print(f"자식 객체 주소값은: {id(self)}")
>>> self.mp = mp
# python 2.x 방식
# super(Wizard,self).__init__()
>>> super().__init__() # 부모클래스 __init__ 실행
>>> def magic_skill(self):
>>> print("마법 공격하기")
>>> self.mp -= 2
>>> player = Wizard(10)
자식 객체 주소값은: 2737076424128
부모 객체 주소값은: 2737076424128
>>> class PlayerCharacter:
>>> def __init__(self,hp,exp):
>>> self.hp = hp
>>> self.exp = exp
>>> def attack(self):
>>> print("공격하기")
>>> self.exp += 2
>>> def defend(self):
>>> print("방어하기")
>>> self.exp += 1
>>> def attacked(self,attack_size):
>>> print("공격받음")
>>> self.hp -= attack_size
>>> class Wizard(PlayerCharacter):
>>> def __init__(self,mp,hp,exp):
>>> super().__init__(hp,exp)
>>> self.mp = mp
>>> def magic_skill(self):
>>> print("마법 공격하기")
>>> self.mp -= 2
>>> self.exp += 10
>>> mp = 50
>>> hp = 150
>>> exp = 100
>>> player = Wizard(mp,hp,exp)
>>> player.magic_skill()
>>> player.hp, player.exp, player.mp
마법 공격하기
(150, 110, 48)
>>> player.attack()
공격하기
오버라이딩 (over riding)
- 부모 클래스로 부터 받은 메소드를 수정하고 싶을 때 사용
- 자식 클래스에서 부모 클래스로 부터 받은 메소드를 재정의
>>> class PlayerCharacter:
>>> def __init__(self,hp=100,exp=0):
>>> self.hp = hp
>>> self.exp = exp
>>> def attack(self):
>>> print("공격하기")
>>> self.exp += 2
>>> def defend(self):
>>> print("방어하기")
>>> self.exp += 1
>>> class Wizard(PlayerCharacter):
>>> def __init__(self,mp):
>>> super().__init__()
>>> self.mp = mp
>>> def magic_skill(self):
>>> print("마법 공격하기")
# 오버라이딩
>>> def defend(self):
>>> print("방어하기")
>>> self.exp += 3
>>> player = Wizard(50)
>>> player.defend()
>>> player.exp
방어하기
3
하나만 더 하자 길다.
>>> class Calculator: # 부모클래스 역할
>>> def __init__(self,num = 0):
>>> self.num = num
# 한개의 정수를 받아 self.num 변수에 더하기
>>> def add(self,num):
>>> pass
# 한개의 정수를 받아 self.num 변수에 빼기
>>> def sub(self,num):
>>> pass
# 한개의 정수를 받아 self.num 변수에 곱하기
>>> def mul(self,num):
>>> pass
# 한개의 정수를 받아 self.num 변수에 나누기
>>> def div(self,num):
>>> pass
>>> def result(self):
>>> return self.num
>>> def reset(self):
>>> self.num = 0
pass 코드는 아무 의미 없음 함수 밑에 뭘 꼭 써줘야하는데 써줄게 없으니까 그냥 넘어가라고 붙인 코드
>>> class MyCalculator(Calculator):
>>> def __init__(self,num):
>>> super().__init__(num)
>>> def add(self,num):
>>> if self.check_num(num):
>>> self.num += num
>>> def sub(self,num):
>>> if self.check_num(num):
>>> self.num -= num
>>> def mul(self,num):
>>> if self.check_num(num):
>>> self.num *= num
>>> def div(self,num):
>>> if self.check_num(num):
>>> self.num /= num
>>> def check_num(self,num):
>>> is_num = True
>>> if type(num) is not int:
>>> print("입력값이 정수가 아닙니다.")
>>> is_num = False
>>> return is_num
>>> my_calculator = MyCalculator(0)
>>> my_calculator.add("")
입력값이 정수가 아닙니다.
my_calculator.add(9)
my_calculator.result()
9
private 화
- 클래스의 인스턴스 변수나 메서드를 클래스 내부에서만 사용
- 맹글링 (mangling) 기법을 이용해서 외부에서 직접적으로 변수나 메서드에 접근을 막을 수 있다
>>> class Wizard:
>>> def __init__(self,hp,exp,mp):
>>> self.hp = hp
>>> self.exp = exp
>>> self.__mp = mp
>>> def __magic_skill(self):
>>> print("마법 공격하기")
>>> self.__mp -= 2
>>> def attack(self):
>>> print("공격하기")
>>> self.exp += 3
>>> self.__magic_skill()
>>> player = Wizard(100,0,50)
>>> player.attack()
공격하기
마법 공격하기
getter & setter
- 인스턴스 변수에 접근할 때 특정 로직을 거쳐서 접근시킴
- getter 또는 setter를 정의할 때는 private화 하기
>>> class Wizard:
>>> def __init__(self,hp,exp,mp):
>>> self.hp = hp
>>> self.exp = exp
>>> self.mp = mp
>>> def magic_skill(self):
>>> print("마법 공격하기")
>>> self.mp -= 2 # self.mp = self.mp - 2
>>> def attack(self):
>>> print("공격하기")
>>> self.exp += 3
>>> @property
>>> def mp(self): #getter
>>> print("getter 동작")
>>> return self.__mp
>>> @mp.setter
>>> def mp(self,mp):
>>> print("setter 동작")
>>> if mp < 0:
>>> mp = 0
>>> self.__mp = mp
>>> player = Wizard(100,0,50)
setter 동작
>>> player.mp
getter 동작
50
>>> player.magic_skill()
마법 공격하기
getter동작
setter 동작
매직 메서드
- 메서드명이 두개의 언더바로 감싼 메서드
- 파이썬의 다양한 내장함수들이 객체의 매직 메서드를 실행해 결과를 반환해줌
- __init__ 매직 메서드
>>> class MyDataset:
>>> def __init__(self,data):
>>> self.data = data
>>> def __call__(self):
>>> print("함수 실행 방법처럼 객체를 함수 호출 하듯이 만들어 주는 메서드")
>>> def __str__(self): # print 함수에 이 객체를 넣으면 이 매직메서드에서 반환된 결과를 출력해준다.
>>> return "MyDataset Class"
>>> def __len__(self): # len 함수에 이 클래스에 객체를 넣으면 이 매직 메서드를 호출한다고 생각하면 됩니다.
>>> return len(self.data)
>>> def __getitem__(self,idx): # 인덱싱과 슬라이싱을 가능하게 해주는 매직 메서드
>>> return self.data[idx]
>>> data = list(range(50,100))
>>> dt = MyDataset(data)
>>> dt()
함수 실행 방법처럼 객체를 함수 호출 하듯이 만들어 주는 메서드
>>> print(dt)
MyDataset Class
>>> len(dt)
50
>>> dt[-1]
99
>>> dt[:20}
[50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69]
클래스 데코레이터
>>> class RunTracking:
>>> def __init__(self,org_func):
>>> self.org_func = org_func
>>> def __call__(self,*args,**kwargs):
>>> print("함수의 실행 시간을 기록합니다.")
>>> result = self.org_func(*args,**kwargs)
>>> print("함수의 실행 종료시간을 기록합니다.")
>>> return result
>>> @RunTracking
>>> def preprocess_data(data):
>>> print("데이터를 전처리하는 중입니다.")
>>> result = []
>>> for item in data:
>>> result.append(item**2)
>>> return result
>>> data = list(range(10000000))
>>> result = preprocess_data(data)
데이터를 전처리하는 중입니다
뭐라 씨부엉씨부엉 모르겠따
근데! 이제 대충 읽으면 언어가 읽히긴 읽힌다 구현은 못해도