클래스(1)
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 # 표준 출력