객체를 만들 때마다 card.owner = '민지', card.stamps = 0을 매번 밖에서 따로 적으면 한 줄이라도 빼먹기 쉽습니다. 클래스 안에 def __init__(self, ...): 함수를 만들어 두면, 객체를 생성할 때 파이썬이 자동으로 이 함수를 불러 새 객체(self)의 처음 속성을 채워 줍니다.
__init__은 앞뒤에 밑줄(_)이 두 개씩 붙은 특별한 이름입니다(영어 initialize, '초기화하다'에서 온 이름).
1__init__과 self가 하는 일
StampCard('민지')를 부르면 파이썬 안에서는 다음 세 걸음이 차례로 일어납니다.
- 빈
StampCard새 객체 ①을 하나 만듭니다. __init__(self, owner)함수를 부르면서, 첫 번째 매개변수self에는 방금 만든 새 객체 ①을 붙이고 두 번째 매개변수 **owner에는 인자'민지'**를 붙입니다(규칙 5).- 함수 안의
self.owner = owner와self.stamps = 0이 새 객체 ① 안에 두 속성을 채운 뒤, 완성된 객체 ①을 돌려줍니다.
class StampCard:
def __init__(self, owner):
self.owner = owner
self.stamps = 0
c1 = StampCard('민지')
c2 = StampCard('준호')
print(c1.owner, c1.stamps)
print(c2.owner, c2.stamps)
민지 0
준호 0부를 때는 StampCard('민지')처럼 self를 뺀 나머지 인자(owner)만 넘깁니다. 첫 번째 매개변수 self 자리에는 파이썬이 새 객체를 알아서 넣어 주기 때문입니다.
2왜 owner = owner가 아니라 self.owner = owner일까?
함수 안의 이름, 밖의 이름에서 함수 안에서 새로 만든 이름은 함수가 끝날 때 칸과 함께 사라진다고 배웠습니다(규칙 5). 만약 __init__ 안에서 self.을 빼먹고 stamps = 0이라고만 적으면 어떻게 될까요? 무엇이 일어날지 먼저 생각해 보세요.
class StampCard:
def __init__(self, owner):
self.owner = owner
stamps = 0
card = StampCard('민지')
print(card.owner)
민지self.owner = owner는 self가 가리키는 객체 ① 안에 .owner 속성을 만들었으므로 __init__이 끝난 뒤에도 card.owner로 읽을 수 있습니다. 반면 4번 줄 stamps = 0은 객체 ①이 아니라 __init__ 함수 칸 안에만 잠깐 생겼다가 사라지는 지역 변수일 뿐이라, 객체 ①에는 .stamps 속성이 생기지 않습니다.
예제
처음 스탬프 개수에 기본값 주기
기본값과 키워드 인자에서 배운 매개변수 기본값은 __init__에서도 그대로 쓸 수 있습니다.
class StampCard:
def __init__(self, s, n=0):
self.owner = s
self.stamps = n
a = StampCard('민지')
b = StampCard('준호', 3)
print(a.owner, a.stamps)
print(b.owner, b.stamps)
민지 0
준호 3StampCard('민지')처럼 주인 이름만 넘기면 n이 기본값 0이 되고, StampCard('준호', 3)처럼 두 번째 인자를 넘기면 처음 스탬프가 3개로 시작합니다.
자주 틀리는 곳
1. __init__ 매개변수에서 self를 빼먹는다
틀린 생각: 부를 때 StampCard('민지')처럼 인자를 하나만 넘기니 def __init__(owner):처럼 매개변수도 하나만 적으면 된다.
파이썬은 객체를 만들 때 새 객체 자신(self)을 늘 첫 번째 인자로 넘깁니다. 따라서 def __init__(owner):라고 적으면 새 객체가 owner에 들어가고 '민지'가 갈 자리가 없어 TypeError가 납니다.
class StampCard:
def __init__(owner):
owner.stamps = 0
name = '민지'
card = StampCard(name)
Traceback (most recent call last): File "main.py", line 7, in <module> card = StampCard(name)TypeError: StampCard.__init__() takes 1 positional argument but 2 were given오류 메시지가 1개를 받는데 2개가 넘어왔다고 하는 까닭이 바로 파이썬이 뒤에서 첫 번째 인자로 self(새 객체)를 함께 넘겼기 때문입니다.
맞는 규칙: __init__의 첫 번째 매개변수 자리에는 늘 self를 적고, 부를 때는 self 뒤의 매개변수 값만 넘깁니다.
2. __init__의 밑줄 개수를 틀린다(_init_)
틀린 생각: _init_처럼 밑줄을 앞뒤 하나씩만 적어도 초기화 함수로 동작한다.
파이썬이 객체를 만들 때 자동으로 찾아 부르는 이름은 밑줄이 앞뒤 두 개씩인 __init__뿐입니다. 밑줄을 하나씩만 적으면 평범한 메서드로 취급되어 객체를 만들 때 자동으로 불리지 않습니다.
class StampCard:
def _init_(self, owner):
self.owner = owner
name = '민지'
card = StampCard(name)
Traceback (most recent call last): File "main.py", line 7, in <module> card = StampCard(name)TypeError: StampCard() takes no arguments맞는 규칙: 초기화 함수 이름은 앞뒤에 밑줄을 두 개씩 붙여 def __init__(self, ...):로 적습니다.
3. self.을 빼먹고 속성을 만든다
틀린 생각: __init__ 안에 stamps = 0이라고만 적어도 객체의 .stamps 속성이 만들어진다.
self. 없이 적은 이름은 __init__ 함수 칸 안에서만 쓰이다 사라집니다(규칙 5).
class StampCard:
def __init__(self, owner):
self.owner = owner
stamps = 0
card = StampCard('민지')
print(card.stamps)
Traceback (most recent call last): File "main.py", line 8, in <module> print(card.stamps) ^^^^^^^^^^^AttributeError: 'StampCard' object has no attribute 'stamps'맞는 규칙: 객체 안에 남길 속성은 반드시 self.속성이름 = 값 꼴로 적습니다.
확인 문제
1. 다음 코드를 실행하면 무엇이 출력될까요?
class Menu:
def __init__(self, name, p):
self.name = name
self.price = p + 500
m = Menu('라테', 4000)
print(m.name, m.price)
힌트
Menu('라테', 4000)을 부를 때 name과 p에 무엇이 붙고 self.price에 얼마가 저장되는지 보세요.
정답
라테 4500self.name에는 '라테'가, self.price에는 4000 + 500인 4500이 저장되어 라테 4500이 출력됩니다.
2. 학생 이름을 받아 self.name에 저장하고 self.score는 0으로 시작하는 __init__을 완성하려 합니다. 빈칸 (가)와 (나)를 채우세요.
class Student:
def __init__(_(가)_, name):
self.name = name
____(나)____ = 0
s = Student('민지')
print(s.name, s.score)
힌트
(가)는 새 객체 자신을 받는 첫 번째 매개변수이고, (나)는 그 객체 안에 score 속성을 만드는 표현입니다.
정답
(가):self(나):self.score
첫 매개변수로 self를 받고 self.score = 0으로 적어야 객체 안에 score 속성이 생깁니다.
3. 아래 코드를 실행하면 7번 줄에서 AttributeError가 납니다. 3번 줄을 어떻게 고쳐야 100이 찍힐까요?
class Player:
def __init__(self):
hp = 100
p = Player()
print(p.hp)
힌트
3번 줄 hp = 100이 객체(self)에 속성을 붙이고 있는지 확인해 보세요.
정답
3번 줄을 self.hp = 100으로 고칩니다.
class Player:
def __init__(self):
self.hp = 100
p = Player()
print(p.hp)100self.을 붙여야 함수가 끝난 뒤에도 p 객체 안에 .hp 속성이 남습니다.
아래 코드에서 StampCard('민지')의 처음 스탬프 수가 1개로 시작하도록 __init__의 self.stamps 줄을 바꿔 돌려 보세요.
처음 펼 때 약 6MB를 받습니다.컴퓨터에서 해 보기
파이썬 3.14. Tab을 누르면 다음 단추나 칸으로 갑니다. 들여쓰기는 빈칸 네 개입니다. Enter는 앞줄 들여쓰기를 잇고, 콜론 뒤에서는 한 단계 더 들여 씁니다. Ctrl+Enter로 실행합니다.
'실행'을 누르면 여기에 나옵니다.
여기서 쓴 코드 · 내 예상은 저장하지도 운영자에게 보내지도 않습니다. 페이지를 새로 열면 처음 코드입니다.