한양과학기술고등학교

에듀테크 프로젝트 대시보드

데이터클래스 (@dataclass)

dataclass field frozen __init__ 자동

__init__·__repr__·__eq__ 를 자동 생성해 주는 데코레이터. 데이터 위주 클래스에 최적.

1. 기본

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int
    label: str = "origin"           # 기본값

p = Point(1, 2)
p                                   # => Point(x=1, y=2, label='origin')
p == Point(1, 2)                    # => True  (필드 값 비교)
p.x = 99                            # 기본은 가변

2. 옵션

@dataclass(frozen=True)             # 불변 (해시 가능 → dict 키 OK)
class Config:
    host: str
    port: int = 80

@dataclass(order=True)              # __lt__ 등 자동 → 정렬 가능
class Version:
    major: int
    minor: int

@dataclass(slots=True)             # __slots__ 자동 (3.10+, 메모리 절약)
class Fast:
    a: int

3. field() — 가변 기본값

from dataclasses import dataclass, field

@dataclass
class Cart:
    items: list = field(default_factory=list)   # [] 직접 쓰면 에러
    total: float = 0.0
    _id: str = field(default="", repr=False)     # repr 에서 숨김

c = Cart()
c.items.append("사과")             # 인스턴스마다 별도 리스트

4. 후처리 · 메서드

@dataclass
class Rectangle:
    width: float
    height: float
    area: float = field(init=False)   # __init__ 인자에서 제외

    def __post_init__(self):
        self.area = self.width * self.height

    def scale(self, k):               # 일반 메서드도 자유롭게 추가
        return Rectangle(self.width * k, self.height * k)

5. 유틸리티

from dataclasses import asdict, astuple, replace, fields

p = Point(1, 2)
asdict(p)          # => {'x': 1, 'y': 2, 'label': 'origin'}
astuple(p)         # => (1, 2, 'origin')
replace(p, x=9)    # => Point(x=9, y=2, ...)  (새 객체)
[f.name for f in fields(p)]   # => ['x', 'y', 'label']

6. 대안 비교

언제 무엇을?
  • 간단한 불변 레코드 → NamedTuple 또는 @dataclass(frozen=True)
  • 검증·직렬화가 중요 → pydantic (서드파티)
  • 동작 위주 클래스 → 일반 class
  • 즉석 묶음 → dict 또는 tuple
"명시적인 것이 암시적인 것보다 낫다 (Explicit is better than implicit)"