클래스 · 객체 · __init__ · self · 메서드 · 상속을 섞었습니다. 앞 단원의 리스트 · 함수 · 변수의 범위도 함께 묻고, 어느 레슨의 문제인지는 정답을 펼쳐야 보입니다. 출력을 쓰는 문제는 빈칸과 줄바꿈까지 종이에 끝까지 쓴 뒤 정답을 펼치세요. 막히면 정답 앞의 힌트를 먼저 펼칩니다. 점수는 매기지 않습니다.
한 번에 다 풀 필요는 없습니다. 문제 1~10은 폰으로도 풀 수 있고(약 20~25분), 끝의 만들어 보기 둘(문제 11·12)은 이 쪽의 실행 칸이나 컴퓨터에서 돌려 맞춰 보세요. 이 단원을 이미 안다면 문제 1 · 3 · 5 · 7만 힌트 없이 먼저 풀어 보세요(약 10분). 네 문제를 다 맞히면 다음 단원으로 넘어가고, 틀린 문제는 정답 끝의 레슨으로 돌아가 그 레슨만 봅니다.
객체를 다룰 때는 이름이 어느 객체(①, ②)에 붙어 있는지 이름표를 그리며 따라가세요. 실행 결과는 모두 파이썬 3.15로 돌린 것입니다.
문제 1
무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
class StampCard:
pass
a = StampCard()
b = StampCard()
a.stamps = 2
b.stamps = 5
a.stamps = a.stamps + 1
print(a.stamps)
print(b.stamps)
힌트
StampCard()를 두 번 불렀으니 객체가 몇 개 생겼는지, 9번 줄이 어느 객체의 .stamps를 바꾸는지 보세요.
정답
3
5StampCard()를 부를 때마다 서로 다른 새 객체(①, ②)가 만들어집니다(규칙 3). a.stamps를 2에서 3으로 바꿔도 b가 가리키는 객체 ②의 .stamps는 5 그대로입니다.
다시 볼 레슨: 클래스와 객체
문제 2
다음 코드를 실행하면 어떻게 될까요? 알맞은 것을 고르세요.
class Box:
pass
b = Box()
print(b.weight)
- ①
0이 찍힌다 - ②
None이 찍힌다 - ③ 6번 줄에서
AttributeError가 난다
힌트
5번 줄에서 만든 빈 객체 b 안에 .weight 속성을 넣은 적이 있는지 보세요.
정답
③ — 실행 결과는 이렇습니다.
Traceback (most recent call last): File "main.py", line 6, in <module> print(b.weight) ^^^^^^^^AttributeError: 'Box' object has no attribute 'weight'아직 만들지 않은 속성을 읽으려 하면 0이나 None이 나오는 것이 아니라 AttributeError가 납니다.
다시 볼 레슨: 클래스와 객체
문제 3
무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
class Member:
def __init__(self, s, p=10):
self.name = s
self.pt = p
m1 = Member('민지')
m2 = Member('준호', 30)
print(m1.name, m1.pt)
print(m2.name, m2.pt)
힌트
7번 줄은 두 번째 인자를 생략했으니 기본값 10을 쓰고, 8번 줄은 30을 넘겼습니다.
정답
민지 10
준호 30객체를 만들 때 파이썬이 자동으로 __init__을 부르고 첫 번째 매개변수 self에 새 객체를 넘깁니다(규칙 5). m1은 기본값 10으로, m2는 넘긴 30으로 .pt가 채워집니다.
다시 볼 레슨: __init__과 self · 기본값과 키워드 인자
문제 4
다음 코드를 실행하면 어떻게 될까요? 알맞은 것을 고르세요.
class Timer:
def __init__(self, sec):
left = sec
t = Timer(30)
print(t.left)
- ①
30이 찍힌다 - ② 3번 줄에서
NameError가 난다 - ③ 7번 줄에서
AttributeError가 난다
힌트
3번 줄 left = sec에 self.이 붙어 있는지 보세요.
정답
③ — 실행 결과는 이렇습니다.
Traceback (most recent call last): File "main.py", line 7, in <module> print(t.left) ^^^^^^AttributeError: 'Timer' object has no attribute 'left'3번 줄 left = sec는 self. 없이 적었으므로 __init__ 함수 칸 안에서만 쓰이다 사라지는 지역 변수입니다(규칙 5). 객체 t에는 .left 속성이 생기지 않아 7번 줄에서 AttributeError가 납니다.
다시 볼 레슨: __init__과 self · 함수 안의 이름, 밖의 이름
문제 5
무엇이 찍힐까요? 한 줄을 글자 그대로 쓰세요.
class Counter:
def __init__(self, start):
self.val = start
def step(self, n=1):
self.val += n
c1 = Counter(10)
c2 = Counter(0)
c1.step()
c2.step(5)
c1.step(2)
print(c1.val, c2.val)
힌트
c1.step()을 부를 때 self가 어느 객체를 가리키는지, c2.step(5)를 부를 때 self가 어느 객체를 가리키는지 차례로 따라가 보세요.
정답
13 5c1은10에서 시작해step()으로1오르고step(2)로2올라13이 됩니다.c2는0에서 시작해step(5)로5올라5가 됩니다.
다시 볼 레슨: 메서드
문제 6
빈칸 (가)와 (나)에 들어갈 파이썬 이름을 쓰세요.
- 클래스로 새 객체를 만들 때 파이썬이 자동으로 불러 처음 속성을 채우는 메서드의 이름은 앞뒤에 밑줄을 두 개씩 붙인
(가)이다. - 메서드 정의의 첫 번째 매개변수로 적어 호출한 객체 자신을 가리키는 관례 이름은
(나)이다.
힌트
def ____(____, ...):의 두 자리에 늘 적던 이름을 떠올려 보세요.
문제 7
무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
class StampCard:
def __init__(self, owner):
self.owner = owner
self.stamps = 0
def add(self):
self.stamps += 1
class VipCard(StampCard):
def add(self):
self.stamps += 2
a = StampCard('민지')
b = VipCard('준호')
a.add()
b.add()
print(a.owner, a.stamps)
print(b.owner, b.stamps)
힌트
VipCard는 __init__을 부모 StampCard에서 물려받고, add는 자기가 다시 정의한 것을 씁니다.
정답
민지 1
준호 2a는 StampCard 객체이므로 a.add()가 스탬프를 1 올리고, b는 VipCard 객체이므로 오버라이딩한 VipCard.add가 실행되어 스탬프를 2 올립니다.
다시 볼 레슨: 상속
문제 8
자식 클래스 BonusCard의 __init__에서 부모 클래스 StampCard의 __init__을 먼저 불러 self.owner와 self.stamps를 초기화하려고 합니다. 빈칸에 들어갈 한 줄을 쓰세요.
class StampCard:
def __init__(self, s):
self.owner = s
self.stamps = 0
class BonusCard(StampCard):
def __init__(self, s, b):
____________________
self.stamps += b
c = BonusCard('민지', 3)
print(c.owner, c.stamps)
힌트
부모 클래스를 가리키는 super() 뒤에 .__init__(...)을 붙입니다. self는 다시 넘기지 않습니다.
정답
super().__init__(s)입니다.
class StampCard:
def __init__(self, s):
self.owner = s
self.stamps = 0
class BonusCard(StampCard):
def __init__(self, s, b):
super().__init__(s)
self.stamps += b
c = BonusCard('민지', 3)
print(c.owner, c.stamps)민지 3다시 볼 레슨: 상속
문제 9
두 변수가 같은 객체를 가리킬 때와 서로 다른 객체를 가리킬 때를 견줍니다. 무엇이 찍힐까요? 한 줄을 글자 그대로 쓰세요.
class Bag:
def __init__(self):
self.items = []
b1 = Bag()
b2 = b1
b3 = Bag()
b2.items.append('사과')
b3.items.append('우유')
print(b1.items, b3.items)
힌트
7번 줄 b2 = b1은 새 객체를 만들지 않고 b1과 같은 객체에 이름표만 하나 더 붙입니다(규칙 3).
정답
['사과'] ['우유']b2 = b1은 b1이 가리키는 객체 ①에 b2라는 이름표를 하나 더 붙인 것이므로 b2.items.append('사과')를 하면 b1.items에서도 ['사과']가 보입니다(규칙 3). 반면 b3 = Bag()는 새로 만든 객체 ②이므로 ['우유']만 들어 있습니다.
문제 10
아래 코드는 Wallet 객체에 돈을 넣는 put 메서드를 부르려다 오류가 납니다. 잘못된 두 줄(6번 줄과 7번 줄)을 어떻게 고쳐야 3000이 찍힐까요?
class Wallet:
def __init__(self):
self.money = 1000
def put(won):
money += won
w = Wallet()
w.put(2000)
print(w.money)
힌트
메서드 정의의 첫 번째 매개변수에는 무엇이 들어가야 하는지, 그리고 객체의 .money 속성을 바꿀 때 이름 앞에 무엇을 붙여야 하는지 보세요.
정답
5번 줄을 def put(self, won):으로, 6번 줄을 self.money += won으로 고칩니다.
class Wallet:
def __init__(self):
self.money = 1000
def put(self, won):
self.money += won
w = Wallet()
w.put(2000)
print(w.money)3000메서드의 첫 번째 매개변수로 self를 받아야 호출한 객체 w가 연결되고, 메서드 안에서 속성을 읽고 바꿀 때도 self.money처럼 self.을 붙여야 합니다.
다시 볼 레슨: 메서드
문제 11 (만들어 보기)
스탬프 개수 .n을 0으로 시작해 모으고, 10개 이상인지(True/False) 알려 주는 StampCard 클래스를 완성하세요. 뼈대의 마지막 줄이 이렇게 찍어야 합니다.
10 True
끝에 c2 = StampCard() · c2.add(5) · print(c2.n, c2.free())를 더해 한 번 더 부르면 이렇게 나와야 합니다.
10 True
5 False
아래 뼈대에서 주석 자리 # 1과 # 2를 채우세요.
class StampCard:
def __init__(self):
self.n = 0
def add(self, k=1):
# 1. self.n에 k 더하기
pass
def free(self):
# 2. 10 이상인지 돌려주기
pass
c = StampCard()
c.add(7)
c.add(3)
print(c.n, c.free())
처음 펼 때 약 6MB를 받습니다.
파이썬 3.14. Tab을 누르면 다음 단추나 칸으로 갑니다. 들여쓰기는 빈칸 네 개입니다. Enter는 앞줄 들여쓰기를 잇고, 콜론 뒤에서는 한 단계 더 들여 씁니다. Ctrl+Enter로 실행합니다.
견줄 시험 값
'실행'을 누르면 여기에 나옵니다.
여기서 쓴 코드 · 내 예상은 저장하지도 운영자에게 보내지도 않습니다. 페이지를 새로 열면 처음 코드입니다.
힌트
add에서는 self.n += k를 실행하고, free에서는 return self.n >= 10을 돌려줍니다.
정답
class StampCard:
def __init__(self):
self.n = 0
def add(self, k=1):
self.n += k
def free(self):
return self.n >= 10
c = StampCard()
c.add(7)
c.add(3)
print(c.n, c.free())10 True다시 볼 레슨: __init__과 self · 메서드
문제 12 (만들어 보기)
장바구니 Cart 클래스를 상속받아, 담을 때마다 가격 p에서 500원을 깎아 더하는 SaleCart 클래스를 작성하세요.
- 부모 클래스
Cart는 이미 주어져 있습니다(self.total = 0,add(self, p)는self.total += p). - 자식 클래스
SaleCart(Cart)에서add(self, p)메서드를 오버라이딩해p - 500만큼self.total에 더하도록 만드세요.
4000원과 4500원을 담으면 이렇게 나와야 합니다.
7500
끝에 bag.add(3500)과 print(bag.total)을 더하면 이렇게 나와야 합니다.
7500
10500
class Cart:
def __init__(self):
self.total = 0
def add(self, p):
self.total += p
# 여기에 SaleCart 클래스를 작성하세요
bag = SaleCart()
bag.add(4000)
bag.add(4500)
print(bag.total)
처음 펼 때 약 6MB를 받습니다.
파이썬 3.14. Tab을 누르면 다음 단추나 칸으로 갑니다. 들여쓰기는 빈칸 네 개입니다. Enter는 앞줄 들여쓰기를 잇고, 콜론 뒤에서는 한 단계 더 들여 씁니다. Ctrl+Enter로 실행합니다.
견줄 시험 값
'실행'을 누르면 여기에 나옵니다.
여기서 쓴 코드 · 내 예상은 저장하지도 운영자에게 보내지도 않습니다. 페이지를 새로 열면 처음 코드입니다.
힌트
class SaleCart(Cart): 안에 def add(self, p):를 만들고 self.total += p - 500을 적습니다.
정답
class Cart:
def __init__(self):
self.total = 0
def add(self, p):
self.total += p
class SaleCart(Cart):
def add(self, p):
self.total += p - 500
bag = SaleCart()
bag.add(4000)
bag.add(4500)
print(bag.total)7500SaleCart는 __init__을 따로 적지 않았으므로 부모 Cart의 __init__을 물려받아 self.total = 0으로 시작하고, add만 덮어써서 할인가를 더합니다.