파이썬의 클래스는 데이터와 동작을 묶는 기본 단위입니다. 이 치트시트는 class 정의, 상속과 super(), @property, slots, 자주 쓰는 매직 메서드를 빠르게 정리합니다.
언제 이 치트시트를 보나?
- 데이터와 관련 동작을 하나의 단위로 묶고 싶을 때
- 상속/오버라이딩 문법이 헷갈릴 때
핵심 패턴
__init__: 인스턴스 초기화 (생성자 역할)self: 인스턴스 자신을 가리킴 (첫 번째 인자로 자동 전달)- 상속:
class Child(Parent): + super().__init__(...) @property: getter/setter를 메서드처럼 정의, 속성처럼 접근__slots__: 메모리 절약 + 오타 방지
최소 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 기본 클래스 정의
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
def greet(self) -> str:
return f"Hello, I'm {self.name}"
def __repr__(self) -> str:
return f"Person(name={self.name!r}, age={self.age})"
p = Person("Alice", 30)
print(p.greet()) # Hello, I'm Alice
print(p) # Person(name='Alice', age=30)
|
1
2
3
4
5
6
7
8
9
10
11
| # 상속과 super()
class Employee(Person):
def __init__(self, name: str, age: int, emp_id: str):
super().__init__(name, age) # 부모 __init__ 호출
self.emp_id = emp_id
def greet(self) -> str: # 오버라이딩
return f"{super().greet()}, ID: {self.emp_id}"
e = Employee("Bob", 25, "E001")
print(e.greet()) # Hello, I'm Bob, ID: E001
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # @property - getter/setter
class Circle:
def __init__(self, radius: float):
self._radius = radius # 관례: _로 시작 = "내부용"
@property
def radius(self) -> float:
return self._radius
@radius.setter
def radius(self, value: float):
if value < 0:
raise ValueError("radius must be non-negative")
self._radius = value
@property
def area(self) -> float: # 읽기 전용 프로퍼티
return 3.14159 * self._radius ** 2
c = Circle(5)
print(c.radius) # 5
print(c.area) # 78.53975
c.radius = 10 # setter 호출
|
1
2
3
4
5
6
7
8
9
10
| # __slots__ - 메모리 절약 + 오타 방지
class Point:
__slots__ = ("x", "y")
def __init__(self, x: float, y: float):
self.x = x
self.y = y
p = Point(1, 2)
# p.z = 3 # AttributeError: 'Point' object has no attribute 'z'
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # classmethod vs staticmethod
class MyClass:
count = 0 # 클래스 변수
def __init__(self):
MyClass.count += 1
@classmethod
def get_count(cls) -> int: # cls = 클래스 자체
return cls.count
@staticmethod
def utility(x: int) -> int: # self/cls 없음
return x * 2
print(MyClass.get_count()) # 0
obj = MyClass()
print(MyClass.get_count()) # 1
print(MyClass.utility(5)) # 10
|
자주 쓰는 매직 메서드
| 메서드 | 용도 | 예시 |
|---|
__init__ | 초기화 | obj = MyClass() |
__repr__ | 개발자용 문자열 | repr(obj) |
__str__ | 사용자용 문자열 | str(obj), print(obj) |
__eq__ | 동등 비교 | obj1 == obj2 |
__hash__ | 해시 (set/dict 키) | hash(obj) |
__len__ | 길이 | len(obj) |
__getitem__ | 인덱싱 | obj[key] |
__iter__ | 이터레이션 | for x in obj |
__call__ | 호출 가능 | obj() |
자주 하는 실수/주의점
- 클래스 변수 vs 인스턴스 변수: 클래스 본문에 정의하면 모든 인스턴스가 공유
- 가변 기본값:
def __init__(self, items=[]) → 모든 인스턴스가 같은 리스트 공유 (함정!) __repr__ 없으면 디버깅 시 <MyClass object at 0x...>만 보임__eq__ 정의하면 __hash__도 함께 고려 (기본적으로 None이 됨)- 다중 상속은 MRO(Method Resolution Order) 이해 필요 →
MyClass.__mro__로 확인
dataclass와의 비교
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 일반 클래스
class PersonManual:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"PersonManual(name={self.name!r}, age={self.age})"
def __eq__(self, other):
return self.name == other.name and self.age == other.age
# dataclass - 위와 동일한 기능 자동 생성
from dataclasses import dataclass
@dataclass
class PersonAuto:
name: str
age: int
|
→ 단순 데이터 컨테이너는 @dataclass 권장 (17챕터 참고)
관련 링크(공식 문서)