콘텐츠로 이동

6단원 과제 정답: Python 클래스 (Class)


문제 1. 클래스 메서드 호출 방식

① Hello, I'm Leo!
② Hello, I'm Mia!

해설

Greeter.greet(g)   # 클래스 메서드처럼 명시적으로 self 전달
g.greet()          # 인스턴스 메서드 방식 (파이썬이 자동으로 g를 self로 전달)
항목 호출 결과 이유
Greeter.greet(g) Hello, I'm Leo! self = g, g.name = "Leo"
g2.greet() Hello, I'm Mia! self = g2, g2.name = "Mia"

두 호출 방식은 완전히 동일합니다. g.greet()은 파이썬이 Greeter.greet(g)로 변환합니다.


문제 2. 인스턴스 변수는 독립적이다

① 0
② 0
③ 50
④ 50
⑤ False

해설

b1 = Box()    b1.width=0, b1.height=0
b2 = Box()    b2.width=0, b2.height=0
b1.width = 50    b1.width=50  (b2는 변하지 않음)
b1.resize(10)    b1.height += 10    b1.height=10 ... 아니, b1.height=0+0

잠깐, resize를 다시 봅시다:

def resize(self, amount):
    self.height += amount
b1.resize(10)b1.height = 0 + 10 = 10

항목 결과 이유
b1.width (초기) 0 __init__에서 width=0
b2.width (초기) 0 독립된 객체
b1.width (수정 후) 50 b1.width = 50 직접 수정
b1.width (resize 후) 50 resize는 height만 변경
b1.width == b2.width False 50 ≠ 0

문제 3. ⚠️ self.score += n 의 함정

① 0
② 10
③ 0
④ 10

해설 — 핵심 함정

class Player:
    score = 0          # 클래스 변수

    def add(self, n):
        self.score += n   # 이 줄이 함정!

self.score += nself.score = self.score + n으로 풀립니다.

첫 번째 호출 p1.add(10):

  1. 오른쪽 self.scorep1에 인스턴스 변수 없음 → 클래스 변수 Player.score = 0 읽음
  2. 0 + 10 = 10
  3. 왼쪽 대입 → p1.score = 10 (인스턴스 변수 생성!)
  4. Player.score는 여전히 0
항목 결과 이유
Player.score 0 클래스 변수 — add() 호출해도 바뀌지 않음
p1.score 10 p1에 인스턴스 변수 score=10이 새로 생김
p2.score 0 p2add() 호출 안 했으므로 클래스 변수 그대로
p1.score (두 번째 후) 10 p1.add(10) 재호출: 이번엔 인스턴스 변수 10에서 시작 → 20?

주의: 두 번째 p1.add(10) 이후 p1.score20이 됩니다.


문제 4. ⚠️ 클래스 변수 리스트 함정

① ['Alice']
② ['Alice', 'Bob']

해설 — 공유 가변 객체

class Team:
    members = []          # 모든 인스턴스가 공유하는 리스트!

members는 클래스 변수입니다. self.members.append(name)새 리스트를 만들지 않고 공유된 리스트를 수정합니다.

항목 결과 이유
['Alice'] t1.add("Alice") → 공유 리스트에 추가
['Alice', 'Bob'] t2.add("Bob") → 같은 리스트에 추가

올바른 방법:

def __init__(self):
    self.members = []    # 인스턴스마다 별도 리스트 생성


문제 5. __str__ 특수 메서드

① <__main__.Point object at 0x...>
② (3, 4)
③ Point(3, 4)

해설

항목 결과 이유
print(p1) <...object...> __str__ 없음 → 기본 객체 표현
print(p2) (3, 4) __str__ 정의됨 → f"({self.x}, {self.y})"
repr(p2) Point(3, 4) __repr__ 정의됨 → f"Point({self.x}, {self.y})"

__str__: print(), str() 호출 시 사용 (사람이 읽기 좋은 형식) __repr__: repr(), 디버거 출력 시 사용 (개발자용, 재현 가능한 형식)


문제 6. 상속, super(), isinstance()

① Animal created: 동물
② Dog created: 바둑이
③ 동물
④ 바둑이
⑤ 멍!
⑥ True
⑦ True
⑧ False

해설

class Animal:
    def __init__(self, name):
        print(f"Animal created: {name}")
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)         # Animal.__init__ 먼저 실행
        print(f"Dog created: {name}")
        self.breed = breed

Dog("바둑이", "진돗개") 호출 시 순서: 1. super().__init__("바둑이")Animal created: 바둑이 출력 2. 이후 Dog created: 바둑이 출력

항목 결과 이유
isinstance(d, Dog) True dDog의 인스턴스
isinstance(d, Animal) True DogAnimal을 상속 → 부모 타입도 True
isinstance(a, Dog) False aAnimal이지 Dog가 아님

문제 7. ⚠️ 이름 맹글링 (Name Mangling)

① True
② False
③ True
④ I have a secret.

해설

class Safe:
    def __init__(self, secret):
        self.__secret = secret   # → _Safe__secret 으로 저장됨

파이썬은 __attr_ClassName__attr로 자동 변환합니다.

항목 결과 이유
hasattr(s, "_Safe__secret") True 실제 저장 이름
hasattr(s, "__secret") False 이 이름으로는 접근 불가
s.reveal() 출력 후 True True 클래스 내부에서는 self.__secret 접근 가능
s.reveal() I have a secret. 메서드 내부에서 정상 접근

외부에서 s.__secret으로 접근하면 AttributeError가 발생합니다.


문제 8. 클래스 변수 카운터 (빈칸 정답)

class Counter:
    count = 0          # 클래스 변수

    def __init__(self):
        Counter.count += 1    # 클래스 이름으로 접근해야 클래스 변수 수정 가능

    @classmethod
    def get_count(cls):
        return cls.count      # cls는 클래스 자체를 가리킴

빈칸 정답

빈칸 위치 정답 이유
______ = 0 count 클래스 변수 이름
______.count += 1 Counter 클래스 이름으로 클래스 변수 수정
def get_count(______): cls classmethod의 첫 매개변수
return ______.count cls cls가 Counter 클래스를 가리킴

실행 결과: 3


문제 9. 상속 체인 (빈칸 정답)

class Vehicle:
    def __init__(self, speed):
        self.speed = speed

class Car(Vehicle):
    def __init__(self, speed, brand):
        super().__init__(speed)
        self.brand = brand

class ElectricCar(Car):
    def __init__(self, speed, brand, range_km):
        super().__init__(speed, brand)
        self.range_km = range_km

    def info(self):
        return f"{self.brand} {self.speed}km/h range:{self.range_km}km"

빈칸 정답

빈칸 위치 정답 이유
class Car(______): Vehicle Car가 Vehicle을 상속
super().__init__(______) (Car) speed Vehicle의 생성자에 speed 전달
class ElectricCar(______): Car ElectricCar가 Car를 상속
super().__init__(______, ______) (ElectricCar) speed, brand Car의 생성자에 두 인자 전달

실행 결과: Tesla 200km/h range:500km


문제 10. 은행 계좌 클래스 (빈칸 정답)

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.__balance = balance

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount

    def withdraw(self, amount):
        if amount > 0 and amount <= self.__balance:
            self.__balance -= amount
            return True
        return False

    def __str__(self):
        return f"{self.owner}: {self.__balance}원"

빈칸 정답

빈칸 위치 정답 이유
self.______ (owner) owner 인스턴스 변수
self.______balance __ (이중 언더스코어) 외부 접근 차단 (name mangling)
self.__balance ______ amount (deposit) += 잔액 증가
amount <= self.______ __balance 출금 가능 여부 확인
return f"... {self.______}원" __balance 잔액 출력

실행 결과:

Alice: 1500원
True
Alice: 1000원