클래스 안에 정의한 함수를 **메서드(method)**라고 부릅니다. 메서드는 첫 번째 매개변수 self로 메서드를 부른 객체 자신을 받아, 그 객체의 속성을 읽거나 바꿉니다.
__init__과 self에서 배운 __init__도 객체를 만들 때 자동으로 불리는 특별한 메서드입니다. 이제 스탬프를 하나씩 찍는 add(self)처럼 우리가 원할 때마다 **객체.메서드()**로 부르는 일반 메서드를 만들어 봅시다.
1메서드 정의하고 부르기
클래스 안에 def add(self):를 정의해 두면, card.add()를 부를 때마다 파이썬이 마침표 앞의 객체 card를 첫 번째 매개변수 self 자리로 넘겨 줍니다. 즉 card.add()는 StampCard.add(card)의 줄임말입니다.
class StampCard:
def __init__(self, owner):
self.owner = owner
self.stamps = 0
def add(self):
self.stamps += 1
card = StampCard('민지')
card.add()
card.add()
print(card.stamps)
2def add(self):: 정의할 때는 첫 번째 매개변수self를 반드시 적습니다.card.add(): 부를 때는 마침표 앞의card가 자동으로self에 들어가므로 괄호 안은 비워 둡니다.self.stamps += 1:self가 가리키는card객체의.stamps값을1올립니다.
그렇다면 손님 두 명(a, b)의 카드에서 a.add()를 두 번, b.add()를 한 번 부르면 두 카드의 스탬프 수는 각각 몇 개가 될까요? 먼저 맞혀 보세요.
class StampCard:
def __init__(self, owner):
self.owner = owner
self.stamps = 0
def add(self):
self.stamps += 1
a = StampCard('민지')
b = StampCard('준호')
a.add()
a.add()
b.add()
print(a.stamps, b.stamps)
실행 결과 보기
2 1예상과 다르면 그곳이 배울 곳입니다. a.add()를 부를 때는 self가 a 객체를 가리키고, b.add()를 부를 때는 self가 b 객체를 가리킵니다. 그래서 각 메서드는 자기를 부른 객체의 .stamps만 올립니다.
2추가 인자를 받고 값을 돌려주는 메서드
메서드도 일반 함수처럼 self 뒤에 추가 매개변수를 받을 수 있고, return으로 계산한 값을 돌려줄 수 있습니다(규칙 5).
class StampCard:
def __init__(self, owner):
self.owner = owner
self.stamps = 0
def add_many(self, n):
self.stamps += n
def left(self):
return 10 - self.stamps
card = StampCard('민지')
card.add_many(4)
print(card.stamps)
print(card.left())
4
6card.add_many(4)를 부르면self에는card가, 두 번째 매개변수n에는4가 들어갑니다.card.left()는 무료 음료 기준인 10개까지 남은 개수(10 - self.stamps)를 계산해6을 돌려줍니다.
자주 틀리는 곳
1. 메서드 정의에서 self를 빼먹는다
틀린 생각: card.add()처럼 괄호 안에 아무것도 안 넘기니 def add():처럼 매개변수도 비워 두면 된다.
card.add()를 부르면 파이썬은 늘 card 객체를 첫 번째 인자로 넘깁니다. 정의에 self가 없으면 인자 개수가 맞지 않아 TypeError가 납니다.
class StampCard:
def add():
print('추가')
card = StampCard()
card.add()
Traceback (most recent call last): File "main.py", line 7, in <module> card.add() ~~~~~~~~^^TypeError: StampCard.add() takes 0 positional arguments but 1 was given0개를 받는데 1개가 넘어왔다는 메시지의 1개가 바로 파이썬이 자동으로 넘긴 card 객체(self)입니다.
맞는 규칙: 클래스 안에 만드는 메서드의 첫 번째 매개변수에는 늘 self를 적습니다.
2. 메서드를 부를 때 괄호 ()를 빼먹는다
틀린 생각: card.add라고만 적어도 메서드가 실행되어 스탬프가 올라간다.
속성(card.stamps)은 값을 읽을 때 괄호를 쓰지 않지만, 메서드(card.add())는 함수이므로 괄호 ()를 붙여야 실제로 호출됩니다(규칙 5).
class StampCard:
def __init__(self):
self.stamps = 0
def add(self):
self.stamps += 1
card = StampCard()
card.add
print(card.stamps)
010번 줄 card.add는 메서드를 부르지 않고 메서드 객체만 가리켰다가 지나갔기 때문에 card.stamps는 0 그대로입니다.
맞는 규칙: 메서드를 실행할 때는 인자가 없더라도 반드시 빈 괄호를 붙여 card.add()로 부릅니다.
3. 메서드 안에서 self. 없이 속성 이름을 쓴다
틀린 생각: 같은 클래스 안이니 add(self) 안에서 self.stamps 대신 stamps라고만 적어도 객체의 속성을 찾아 준다.
파이썬은 self.이 붙지 않은 이름을 객체의 속성이 아니라 그 함수 칸의 지역 변수나 전역 변수로 찾습니다(규칙 5).
맞는 규칙: 메서드 안에서 자기 객체의 다른 속성이나 메서드를 쓸 때는 늘 앞에 self.을 붙여 self.stamps처럼 적습니다.
확인 문제
1. 다음 코드를 실행하면 무엇이 출력될까요?
class Counter:
def __init__(self):
self.n = 10
def down(self, step):
self.n -= step
c = Counter()
c.down(3)
c.down(2)
print(c.n)
힌트
처음 c.n은 10이고, c.down(3)과 c.down(2)가 차례로 c.n에서 얼마를 빼는지 보세요.
정답
510에서 3을 빼 7이 되고, 다시 2를 빼 5가 출력됩니다.
2. 직사각형의 넓이(self.w * self.h)를 돌려주는 area 메서드를 완성하려 합니다. 빈칸 (가)와 (나)를 채우세요.
class Rect:
def __init__(self, w, h):
self.w = w
self.h = h
def area(__(가)__):
return __(나)__ * self.h
r = Rect(4, 5)
print(r.area())
힌트
메서드의 첫 번째 매개변수 이름과, 메서드 안에서 자기 객체의 w 속성을 읽는 표현을 적습니다.
정답
(가):self(나):self.w
def area(self):로 정의하고 return self.w * self.h로 자기 객체의 속성을 읽어 계산합니다.
3. 아래 코드에서 p.heal()을 불렀는데 10번 줄에서 TypeError가 납니다. 5번 줄을 어떻게 고쳐야 할까요?
class Player:
def __init__(self):
self.hp = 50
def heal():
self.hp += 10
p = Player()
p.heal()
힌트
p.heal()을 부를 때 파이썬이 자동으로 첫 번째 인자로 넘기는 객체를 받을 매개변수가 5번 줄에 있는지 보세요.
정답
5번 줄의 괄호 안에 self를 넣어 def heal(self):로 고칩니다.
아래 코드에서 card.add()를 한 번 더 불러 스탬프가 3개가 되도록 해 보세요.
처음 펼 때 약 6MB를 받습니다.컴퓨터에서 해 보기
파이썬 3.14. Tab을 누르면 다음 단추나 칸으로 갑니다. 들여쓰기는 빈칸 네 개입니다. Enter는 앞줄 들여쓰기를 잇고, 콜론 뒤에서는 한 단계 더 들여 씁니다. Ctrl+Enter로 실행합니다.
'실행'을 누르면 여기에 나옵니다.
여기서 쓴 코드 · 내 예상은 저장하지도 운영자에게 보내지도 않습니다. 페이지를 새로 열면 처음 코드입니다.