ข้ามไปยังเนื้อหา

Dataclasses

Class ที่เก็บข้อมูลมักต้องการ __init__, __repr__ และ __eq__ — ทั้งหมดเขียนด้วยมือด้วย logic เหมือนกัน: copy constructor arguments ลงใน self.attr, format attributes เป็น string, เปรียบเทียบ attribute ทีละตัว @dataclass สร้างทั้งหมดนี้จาก type annotations ระดับ class

from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float

Python สร้าง:

  • __init__(self, x: float, y: float) ที่กำหนด self.x และ self.y
  • __repr__ ที่ return "Point(x=1.0, y=2.0)"
  • __eq__ ที่เปรียบเทียบทุก field

Scalar defaults ทำงานเหมือน keyword arguments:

@dataclass
class Config:
host: str = "localhost"
port: int = 8080
debug: bool = False

ไม่สามารถใช้ mutable object (list, dict) เป็น default โดยตรง — Python จะใช้ instance เดียวร่วมกันระหว่าง object ทั้งหมด ใช้ field(default_factory=...) แทน:

from dataclasses import dataclass, field
@dataclass
class Inventory:
name: str
tags: list = field(default_factory=list)
quantity: int = 0

field ยังรับ:

Parameterผล
default_factoryเรียกโดยไม่มี argument เพื่อสร้าง default ของแต่ละ instance
repr=Falseยกเว้น field จาก __repr__
compare=Falseยกเว้น field จาก __eq__ และ __lt__
init=Falseยกเว้นจาก __init__; กำหนดด้วยตนเองใน __post_init__

frozen=True ทำให้ dataclass ไม่สามารถแก้ไขได้: สร้าง __setattr__ และ __delattr__ ที่ raise FrozenInstanceError และยังสร้าง __hash__ ทำให้ใช้ frozen instances เป็น dict keys หรือใน sets ได้

@dataclass(frozen=True)
class Color:
red: int
green: int
blue: int

Dataclass ยังคงเป็น class ปกติ — เพิ่ม method ใดก็ได้ตามต้องการ:

@dataclass
class Point:
x: float
y: float
def distance_from_origin(self) -> float:
return (self.x ** 2 + self.y ** 2) ** 0.5
from dataclasses import dataclass, field
@dataclass
class Point:
x: float
y: float
def distance_from_origin(self) -> float:
return (self.x ** 2 + self.y ** 2) ** 0.5
@dataclass
class Inventory:
name: str
tags: list = field(default_factory=list)
quantity: int = 0
def add_tag(self, tag: str) -> None:
self.tags.append(tag)
@dataclass(frozen=True)
class Color:
red: int
green: int
blue: int
p = Point(3.0, 4.0)
print(p)
print(p.distance_from_origin())
item = Inventory("Widget")
item.add_tag("sale")
item.add_tag("clearance")
print(item)
red = Color(255, 0, 0)
print(red)
print(red == Color(255, 0, 0))
`@dataclass` สร้าง dunder methods ใดอัตโนมัติ?
ทำไมถึงเขียน `tags: list = []` เป็น dataclass field default ไม่ได้?
`frozen=True` เพิ่มอะไรให้ dataclass?
`field(repr=False)` ใช้สำหรับอะไร?