Chuyển đến nội dung chính
Mô-đun 9 · Bài học 2 trong tổng số 434/36 trong khóa học~12 min
Bài học theo mô-đun (2/4)

dataclass: các lớp dữ liệu không có bản soạn sẵn

Trình trang trí @dataclass (mô-đun dataclasses) tự động tạo __init__, __repr__ và __eq__ dành cho các lớp có nhiệm vụ duy nhất là giữ dữ liệu. Ít bản soạn sẵn hơn, mã rõ ràng hơn.

Không có lớp dữ liệu (bản soạn sẵn)

Python
class Punto:
    def __init__(self, x: float, y: float) -> None:
        self.x = x
        self.y = y
    def __repr__(self) -> str:
        return f"Punto(x={self.x}, y={self.y})"
    def __eq__(self, other) -> bool:
        if not isinstance(other, Punto):
            return NotImplemented
        return (self.x, self.y) == (other.x, other.y)

Với lớp dữ liệu

Python
from dataclasses import dataclass

@dataclass
class Punto:
    x: float
    y: float

p = Punto(3, 4)
p             # Punto(x=3, y=4)   ← __repr__ gratis
Punto(3, 4) == Punto(3, 4)        # True ← __eq__ gratis
p.x, p.y      # 3, 4

Mẫu: khai báo các trường dưới dạng chú thích lớp (name: type), tùy chọn với giá trị mặc định. @dataclass tạo phần còn lại.

Mặc định và default_factory

Python
from dataclasses import dataclass, field

@dataclass
class Articolo:
    nome: str
    prezzo: float = 0.0
    tag: list[str] = field(default_factory=list)

Frozen=True: bất biến

Python
@dataclass(frozen=True)
class Coordinata:
    lat: float
    lon: float

c = Coordinata(45.4, 9.2)
c.lat = 99   # FrozenInstanceError!

frozen các lớp dữ liệu cũng có thể băm: bạn có thể sử dụng chúng làm khóa chính tả hoặc thiết lập các phần tử.

order=True: so sánh tự động

Python
@dataclass(order=True)
class Voto:
    valore: int

Voto(10) < Voto(20)   # True
sorted([Voto(30), Voto(10), Voto(20)])

Tạo __lt__, __le__, __gt__, __ge__ so sánh các trường theo thứ tự họ đã được tuyên bố.

Phương pháp thông thường

Các lớp dữ liệu vẫn là các lớp thông thường: bạn có thể thêm các phương thức.

Python
import math
from dataclasses import dataclass

@dataclass
class Punto:
    x: float
    y: float
    def distanza_dall_origine(self) -> float:
        return math.hypot(self.x, self.y)

Punto(3, 4).distanza_dall_origine()   # 5.0

Các lớp dữ liệu bất biến và hiệu quả

Bạn có thể làm cho một lớp dữ liệu trở nên bất biến bằng cách chuyển đối số frozen=True cho trình trang trí: @dataclass(frozen=True). Điều này gây ra lỗi đối với bất kỳ nỗ lực nào nhằm thay đổi các thuộc tính sau khi khởi tạo, làm cho các phiên bản trở nên an toàn đối với các môi trường đồng thời hoặc để sử dụng làm khóa từ điển.

Hãy tự mình thử

tập thể dục#python.m9.l2.e1
Nỗ lực: 0Đang tải…

Tạo một dataclass `Book` với các trường `title: str` và `pages: int`. Khởi tạo nó dưới dạng `l = Book('Moby Dick', 635)`. Đánh giá `l == Book('Moby Dick', 635)`.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

@dataclass tạo __eq__ so sánh từng trường.

Giải pháp khả dụng sau 3 lần thử

Xem lại bài tập

tập thể dục#python.m9.l2.e2
Nỗ lực: 0Đang tải…

Tạo một lớp dữ liệu `Basket` ​​với trường `items: list[str]` với default_factory=list. Khởi tạo `c1 = Basket()` và `c2 = Basket()`, nối 'mela' vào c1.items. Đánh giá `(c1.items, c2.items)` để xác minh rằng chúng KHÔNG giống nhau.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

field(default_factory=list) đảm bảo một danh sách mới cho mỗi phiên bản.

Giải pháp khả dụng sau 3 lần thử

Thử thách bổ sung

tập thể dục#python.m9.l2.e3
Nỗ lực: 0Đang tải…

Import `dataclass` from `dataclasses`. Create a dataclass `Point` containing two float coordinates `x` and `y`. Instantiate a point with `x=1.5` and `y=2.5` storing it in `p`. Finally, evaluate `p`.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Sử dụng @dataclass phía trên lớp Point và khai báo x: float và y: float.

Giải pháp khả dụng sau 3 lần thử