Tổng quat
Câu hỏi đã được giải quyết. Tuy nhiên, câu trả lời này bổ sung một số ví dụ thực tế để hỗ trợ cho sự hiểu biết cơ bản về dataclass.
Chính xác các lớp dữ liệu python là gì và khi nào là tốt nhất để sử dụng chúng?
- trình tạo mã : tạo mã soạn sẵn; bạn có thể chọn thực hiện các phương thức đặc biệt trong một lớp thông thường hoặc có một lớp dữ liệu tự động thực hiện chúng.
- bộ chứa dữ liệu : các cấu trúc chứa dữ liệu (ví dụ: tuples và dicts), thường có các truy cập thuộc tính rải rác, như các lớp
namedtuple
và các cấu trúc khác .
"tên biến đổi có thể thay đổi với [s]" mặc định
Đây là những gì cụm từ sau có nghĩa là:
- mutable : theo mặc định, các thuộc tính dataclass có thể được gán lại. Bạn có thể tùy ý biến chúng thành bất biến (xem ví dụ bên dưới).
- nametuple : bạn đã truy cập, truy cập thuộc tính như một
namedtuple
hoặc một lớp thông thường.
- mặc định : bạn có thể gán giá trị mặc định cho các thuộc tính.
So với các lớp phổ biến, bạn chủ yếu tiết kiệm khi nhập mã soạn sẵn.
Đặc trưng
Đây là tổng quan về các tính năng của bảng dữ liệu (TL; DR? Xem Bảng Tóm tắt trong phần tiếp theo).
Những gì bạn nhận được
Dưới đây là các tính năng bạn nhận được theo mặc định từ dataclass.
Các thuộc tính + Đại diện + So sánh
import dataclasses
@dataclasses.dataclass
#@dataclasses.dataclass() # alternative
class Color:
r : int = 0
g : int = 0
b : int = 0
Những mặc định này được cung cấp bằng cách tự động đặt các từ khóa sau thành True
:
@dataclasses.dataclass(init=True, repr=True, eq=True)
Những gì bạn có thể bật
Các tính năng bổ sung có sẵn nếu các từ khóa thích hợp được đặt thành True
.
Đặt hàng
@dataclasses.dataclass(order=True)
class Color:
r : int = 0
g : int = 0
b : int = 0
Các phương thức đặt hàng hiện đang được triển khai (các toán tử nạp chồng < > <= >=
:), tương tự như functools.total_ordering
với các phép thử đẳng thức mạnh hơn.
Có thể băm, có thể thay đổi
@dataclasses.dataclass(unsafe_hash=True) # override base `__hash__`
class Color:
...
Mặc dù đối tượng có khả năng biến đổi (có thể không mong muốn), một hàm băm được thực hiện.
Băm, bất biến
@dataclasses.dataclass(frozen=True) # `eq=True` (default) to be immutable
class Color:
...
Băm bây giờ được thực hiện và thay đổi đối tượng hoặc gán cho các thuộc tính không được phép.
Nhìn chung, đối tượng là hashable nếu một trong hai unsafe_hash=True
hoặc frozen=True
.
Xem thêm bảng logic băm gốc với nhiều chi tiết hơn.
Những gì bạn không nhận được
Để có được các tính năng sau, các phương pháp đặc biệt phải được thực hiện thủ công:
Giải nén
@dataclasses.dataclass
class Color:
r : int = 0
g : int = 0
b : int = 0
def __iter__(self):
yield from dataclasses.astuple(self)
Tối ưu hóa
@dataclasses.dataclass
class SlottedColor:
__slots__ = ["r", "b", "g"]
r : int
g : int
b : int
Kích thước đối tượng bây giờ đã giảm:
>>> imp sys
>>> sys.getsizeof(Color)
1056
>>> sys.getsizeof(SlottedColor)
888
Trong một số trường hợp, __slots__
cũng cải thiện tốc độ tạo phiên bản và truy cập các thuộc tính. Ngoài ra, các vị trí không cho phép bài tập mặc định; mặt khác, a ValueError
được nâng lên
Xem thêm về các vị trí trong bài viết trên blog này .
Bảng tóm tắt
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Feature | Keyword | Example | Implement in a Class |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Attributes | init | Color().r -> 0 | __init__ |
| Representation | repr | Color() -> Color(r=0, g=0, b=0) | __repr__ |
| Comparision* | eq | Color() == Color(0, 0, 0) -> True | __eq__ |
| | | | |
| Order | order | sorted([Color(0, 50, 0), Color()]) -> ... | __lt__, __le__, __gt__, __ge__ |
| Hashable | unsafe_hash/frozen | {Color(), {Color()}} -> {Color(r=0, g=0, b=0)} | __hash__ |
| Immutable | frozen + eq | Color().r = 10 -> TypeError | __setattr__, __delattr__ |
| | | | |
| Unpacking+ | - | r, g, b = Color() | __iter__ |
| Optimization+ | - | sys.getsizeof(SlottedColor) -> 888 | __slots__ |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
+ Các phương thức này không được tạo tự động và yêu cầu thực hiện thủ công trong một bảng dữ liệu.
* __ne__
là không cần thiết và do đó không được thực hiện .
Tính năng bổ sung
Hậu khởi tạo
@dataclasses.dataclass
class RGBA:
r : int = 0
g : int = 0
b : int = 0
a : float = 1.0
def __post_init__(self):
self.a : int = int(self.a * 255)
RGBA(127, 0, 255, 0.5)
# RGBA(r=127, g=0, b=255, a=127)
Di sản
@dataclasses.dataclass
class RGBA(Color):
a : int = 0
Chuyển đổi
Chuyển đổi một dataclass thành một tuple hoặc dict, đệ quy :
>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{r: 128, g: 0, b: 255}
Hạn chế
Người giới thiệu
- Cuộc trò chuyện của R. Hettinger trên Dataclass: Trình tạo mã để kết thúc tất cả các trình tạo mã
- Cuộc nói chuyện của T. Hunner về các lớp dễ dàng hơn: Các lớp Python không có tất cả các hành trình
- Tài liệu của Python về chi tiết băm
- Hướng dẫn thực sự của Python về Hướng dẫn cơ bản về các lớp dữ liệu trong Python 3.7
- Bài viết trên blog của A. Shaw về chuyến tham quan ngắn về các lớp dữ liệu Python 3.7
- Kho lưu trữ github của E. Smith trên dataclass
namedtuple
s là bất biến và không thể có giá trị mặc định cho các thuộc tính, trong khi các lớp dữ liệu có thể thay đổi và có thể có chúng.