python dataclass, dataclass, @dataclass, frozen dataclass, field
정의
@dataclass(3.7+, PEP 557)는 클래스에 __init__, __repr__, __eq__ 등 상용구 메서드를 자동 생성해주는 데코레이터다. 데이터 컨테이너 클래스를 한 줄 데코레이터 + 필드 어노테이션만으로 만들 수 있다.
기본 사용
python
from dataclasses import dataclass@dataclassclass Point: x: int y: intp = Point(3, 4)print(p)print(p == Point(3, 4))print(p.x, p.y)
결과
Point(x=3, y=4)True3 4
자동 생성: __init__(self, x, y), __repr__, __eq__. 수동 작성이라면 20줄 넘는 보일러플레이트.
옵션
@dataclass( init=True, # __init__ 생성 (기본 True) repr=True, # __repr__ 생성 eq=True, # __eq__ 생성 order=False, # __lt__/__le__/__gt__/__ge__ 생성 unsafe_hash=False, frozen=False, # 불변 (속성 변경 불가) match_args=True, # __match_args__ 생성 (3.10+, match 문 위치 매칭) kw_only=False, # 모든 필드를 키워드 전용으로 (3.10+) slots=False, # __slots__ 사용 (3.10+, 메모리 절감))class C: ...
frozen=True: 불변 dataclass
@dataclass(frozen=True)class Point: x: int y: intp = Point(1, 2)p.x = 99 # FrozenInstanceError# hashable이 됨 → dict 키, set 원소 가능points = {Point(0, 0), Point(1, 1)}
frozen=True는 __setattr__을 가로채 예외를 던진다. __hash__도 자동 생성.
field() 함수
기본값, 비교 제외, factory 등 세부 설정.
python
from dataclasses import dataclass, fieldfrom typing import List@dataclassclass User: name: str age: int = 0 tags: List[str] = field(default_factory=list) # 가변 기본값 id: int = field(init=False, default=-1) # __init__ 인수 제외 cache: dict = field(default_factory=dict, repr=False, compare=False)u = User("Alice", 30)u.tags.append("admin")print(u)
결과
User(name='Alice', age=30, tags=['admin'], id=-1)
가변 기본값(list, dict, set)은 반드시 default_factory. 직접 tags: list = []라고 쓰면 ValueError (dataclass가 검출).
post_init
__init__ 종료 직후 호출. 파생 필드 계산이나 검증.
from dataclasses import dataclass@dataclassclass Rect: width: float height: float area: float = 0.0 # 파생값 def __post_init__(self): self.area = self.width * self.height if self.width <= 0 or self.height <= 0: raise ValueError("dimensions must be positive")r = Rect(3, 4)print(r) # Rect(width=3, height=4, area=12)
3.10 이전엔 직접 __slots__ = ("x", "y") 작성 후 별도 dataclass와 결합 필요. 3.10+는 한 옵션으로 끝.
상속
@dataclassclass Base: a: int b: int = 0@dataclassclass Child(Base): c: int = 0 # d: int # ERROR: 기본값 있는 필드(b) 뒤에 기본값 없는 필드 불가
서브클래스가 부모 기본값 있는 필드 뒤에 무 기본값 필드를 추가하면 에러. 3.10+ kw_only=True로 회피 가능.
@dataclass(kw_only=True)class Child(Base): d: int # OK: 모든 필드가 키워드 전용
asdict / astuple / fields / replace
python
from dataclasses import dataclass, asdict, astuple, fields, replace@dataclassclass Point: x: int y: intp = Point(3, 4)print(asdict(p))print(astuple(p))print([f.name for f in fields(p)])# replace: 일부 필드만 바꾼 새 인스턴스 (frozen에서 특히 유용)q = replace(p, x=99)print(q)
💬 댓글