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)
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
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, 4Mẫ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
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
@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
@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.
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.0Cá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ạ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)`.
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ạ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.
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
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`.
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ử