-
class
클래스는 객체의 구조와 행동을 정의, 복잡한 문제를 다루기 쉽도록 만듦
객체의 클래스는 초기화를 통해 제어
클래스와 메서드 만들기
class에 이름 지정하고 :(콜론) 붙인 뒤 다음 줄부터 def로 메서드 작성 > 반드시 들여쓰기
보통 파이썬에서 클래스 이름은 대문자로 시작
메서드의 첫 번째 매개변수는 반드시 self를 지정해야 함
>>> class Person: ... def greeting(self): ... print('hello') ... >>> james = Person() # Person 클래스로 james 인스턴스 만들기
메서드 호출
>>> james.greeting() # 인스턴스를 통해 클래스의 메서드에 접근 hello
↑ 인스턴스 메서드
파이썬에서 흔히 볼 수 있는 클래스
>>> a = int(10) # a = 10과 같음 >>> a 10 >>> b = list(range(10)) >>> b [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> c = dict(x=10, y=20) # c = {'x':10, 'y':20} >>> c {'x': 10, 'y': 20} >>> >>> >>> maria = Person() >>> >>> >>> b = list(range(10)) >>> b.append(20) >>> b [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20] >>> >>> >>> # 자료형 확인 >>> a = 10 >>> type(a) <class 'int'> >>> >>> b = [0, 1, 2] >>> type(b) <class 'list'> >>> >>> c = {'x':10, 'y':20} >>> type(c) <class 'dict'> >>> >>> maria = Person() >>> type(maria) <class '__main__.Person'>
빈 클래스 만들기
class Person: pass
메서드 안에서 메서드 호출
>>> # self.메서드() >>> >>> class Person(): ... def greeting(self): ... print('hello') ... def hello(self): ... self.greeting() ... >>> james = Person() >>> james.hello() hello
특정 클래스의 인스턴스인지 확인
>>> class Person: ... pass ... >>> james = Person() >>> isinstance(james, Person) True >>> >>> >>> def factorial(n): ... if not isinstance(n, int) or n < 0: # n이 정수가 아니거나 음수이면 함수를 끝냄 ... return None ... if n == 1: ... return 1 ... return n * factorial(n-1) ... >>> factorial(5) 120 >>> factorial(-5) >>> factorial(5.0) >>>
속성 사용
# class의 선언 # class 클래스이름: # def __init__(self): # self.속성 = 값 class Person: def __init__(self): self.hello = '안녕하세요' def greeting(self): print(self.hello) james = Person() james.greeting() # 실행 결과 안녕하세요
__init__ 메서드는 james = Person()처럼 클래스에 ()괄호를 붙여 인스턴스를 만들 때 호출되는 특별한 메서드
__init__(initialize) 이름 그대로 인스턴스(객체) 초기화
앞뒤로 __ 밑줄 두 개가 붙은 메서드는 파이썬이 자동으로 호출해 주는 메서드 > 스페셜 메서드, 매직 메서드라고 부름
self의 의미
self는 인스턴스 자기 자신
__init__의 매개변수 self에 들어가는 값은 Person() 그리고 self가 완성된 뒤 james에 할당
인스턴스를 만들 때 값 받기
# class 클래스이름: # def __init__(self, 매개변수1, 매개변수2): # self.속성1 = 매개변수1 # self.속성2 = 매개변수2 class Person: def __init__(self, name, age, addr): self.hello = '안녕하세요' self.name = name self.age = age self.addr = addr def greeting(self): print('{} 저는 {}입니다.'.format(self.hello, self.name)) maria = Person('마리아', 20, '수원시') maria.greeting() print('이름:', maria.name) print('나이:', maria.age) print('주소:', maria.addr) # 실행 결과 안녕하세요 저는 마리아입니다. 이름: 마리아 나이: 20 주소: 수원시
클래스 안에서 속성에 접근할 때는 self.속성 형식, 클래스 바깥에서 속성에 접근할 때는 인스턴스.속성 형식으로 접근
클래스의 위치 인수, 키워드 인수
# 1. 위치 인수와 리스트 언패킹 *args class Person: def __init__(self, *args): self.hello = '안녕하세요' self.name = args [0] self.age = args [1] self.addr = args [2] def greeting(self): print(self.name, self.age, self.addr) # 리스트로 묶어서 호출 maria = Person(*['마리아', 20, '수원시']) maria.greeting() # 실행 결과 마리아 20 수원시 # 2. 키워드 인수와 딕셔너리 언패킹 **kwargs class Person: def __init__(self, **kwargs): self.hello = '안녕하세요' self.name = kwargs ['name'] self.age = kwargs ['age'] self.addr = kwargs ['addr'] def greeting(self): print(self.name, self.age, self.addr) maria1 = Person(name='마리아', age=20, addr='수원시') maria2 = Person(**{'name':'마리아', 'age':21, 'addr':'서울시'}) maria1.greeting() maria2.greeting() # 실행 결과 마리아 20 수원시 마리아 21 서울시
인스턴스를 생성한 뒤에 속성 추가, 특정 속성만 허용
# 인스턴스를 생성한 뒤 속성 추가 class Person: pass maria = Person() maria.name = '마리아' print(maria.name) james = Person() print(james.name) # 실행 결과 마리아 print(james.name) ^^^^^^^^^^ AttributeError: 'Person' object has no attribute 'name'
마리아 인스턴스에만 name 속성을 추가했으므로 james 인스턴스에는 name 속성이 없음
class Person: # __init__ 속성값이 없음 def greeting(self): self.hello = '하이' maria = Person() # print(maria.hello) # 아직 hello 속성이 없음 maria.greeting() # greeting 메서드를 호출해야 print(maria.hello) # hello 속성이 생성됨 # 실행 결과 하이
인스턴스는 생성한 뒤에 속성을 추가할 수 있으므로 __init__ 메서드가 아닌 다른 메서드에서도 속성을 추가할 수 있음
단, 이때는 메서드를 호출해야 속성이 생성됨
# 특정 속성만 허용 __slots__ class Person: __slots__ = ['name', 'age'] maria = Person() maria.name = '마리아' maria.age = 20 maria.addr = '수원시' # 실행 결과 maria.addr = '수원시' ^^^^^^^^^^ AttributeError: 'Person' object has no attribute 'addr'
특정 속성만 허용하고 다른 속성은 제한하고 싶을 때 허용할 속성 이름만 slots에 리스트로 넣어 주면 됨
반드시 문자열로 지정
비공개 속성 사용
# class 클래스이름: # def __init__(self, 매개변수): # self.__속성 = 값 class Person: def __init__(self, name, age, addr, wallet): self.name = name self.age = age self.addr = addr self.__wallet = wallet # 변수 앞에 __를 붙여 비공개 속성으로 만듦 maria = Person('마리아', 20, '수원시', 10000) print(maria.name) print(maria.__wallet) # 클래스 바깥에서 비공개 속성에 접근하면 에러 발생 # 실행 결과 마리아 print(maria.__wallet) ^^^^^^^^^^^^^^ AttributeError: 'Person' object has no attribute '__wallet'
예제: 돈 내는 pay 메서드
class Person: def __init__(self, name, age, addr, wallet): self.name = name self.age = age self.addr = addr self.__wallet = wallet # 변수 앞에 __를 붙여 비공개 속성으로 만듦 def pay(self, amount): self.__wallet -= amount # 비공개 속성은 클래스 안의 메서드에서만 접근 가능 print('이제 {0}원 남았습니다.'.format(self.__wallet)) maria = Person('마리아', 20, '수원시', 10000) maria.pay(3000) # 실행 결과 이제 7000원 남았습니다. # + 지갑에 든 돈이 얼마인지 확인하고 돈이 모자라면 쓰지 못하도록 def pay(self, amount): if amount > self.__wallet: print('돈이 모자라네....') return self.__wallet -= amount print('이제 {0}원 남았습니다.'.format(self.__wallet)) maria = Person('마리아', 20, '수원시', 10000) maria.pay(13000) # 실행 결과 돈이 모자라네....
비공개 메서드 사용
class Person: def __greeting(self): print('hello') def hello(self): self.__greeting() james = Person() james.__greeting() # 오류 james.hello() # 실행 결과 james.__greeting() ^^^^^^^^^^^^^^^^ AttributeError: 'Person' object has no attribute '__greeting'
연습 문제 예제
# 34.5번 연습문제: 게임 캐릭터 클래스 만들기 # 다음 소스 코드에서 클래스를 작성하여 게임 캐릭터의 능력치와 '베기'가 출력되게 만드세요. class Knight: def __init__(self, health, mana, armor): self.health = health self.mana = mana self.armor = armor def slash(self): print('베기') x = Knight(health=542.4, mana=210.3, armor=38) print(x.health, x.mana, x.armor) x.slash() # 실행 결과 542.4 210.3 38 베기 # 34.6번 심사문제: 게임 캐릭터 클래스 만들기 # 표준 입력으로 게임 캐릭터 능력치(체력, 마나, AP)가 입력됩니다 # 다음 소스 코드에서 애니(Annie) 클래스를 작성하여 티버(tibbers) 스킬의 피해량이 출력되게 만드세요 # 티버의 피해량은 AP * 0.65 + 400이며 AP(Ability Power, 주문력)는 마법 능력치를 뜻합니다 class Annie: def __init__(self, health, mana, ability_power): self.health = health self.mana = mana self.ability_power = ability_power def tibbers(self): ap = self.ability_power * 0.65 + 400 print('티버: 피해량 {}'.format(ap)) health, mana, ability_power = map(float, input().split()) x = Annie(health=health, mana=mana, ability_power=ability_power) x.tibbers() # 실행 결과 511.68 334.0 298 # 표준 입력 티버: 피해량 593.7 # 표준 출력 1803.68 1184.0 645 # 표준 입력 티버: 피해량 819.25 # 표준 출력