Hiểu về Dataclass trong Python
Dataclass là một tính năng tiện lợi được giới thiệu trong Python 3.7, giúp lập trình viên tiết kiệm thời gian khi tạo ra các lớp đơn giản để lưu trữ dữ liệu mà không cần viết quá nhiều mã lặp lại. Trong bài viết này, chúng ta sẽ tìm hiểu cách thức hoạt động của dataclass, cách trường (fields) ảnh hưởng đến sự so sánh và băm (hashing) của các đối tượng dataclass.
Mục lục
- Dataclass là gì?
- Bát rỗng
- So sánh các bát khác nhau
- Trường so với Biến lớp
- Dataclass có thể thay đổi và không thể thay đổi
- Giá trị mặc định và Nhà máy
- Kết luận và Gọi hành động
Dataclass là gì?
Dataclass giúp cho việc tạo ra các lớp dữ liệu trở nên dễ dàng hơn. Với dataclass, Python tự động tạo ra các phương thức __init__, __eq__, và __repr__ cho bạn.
Ví dụ, thay vì viết:
python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
Bạn chỉ cần sử dụng dataclass như sau:
python
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
Bát rỗng
Hãy xem xét một bát không có các vật phẩm đánh dấu:
Khi Python đánh giá bát này, chỉ có các thuộc tính được khai báo cùng với chú thích kiểu (annotations) mới được xem là nội dung hợp lệ của bát, từ đó ảnh hưởng đến sự so sánh và băm. Nếu không có chú thích kiểu, Python sẽ không xem các trường này là nội dung hợp lệ.
Thêm chú thích kiểu sẽ biến bát này thành:
python
@dataclass
class EmptyBowl:
items: list
Giờ đây, các vật phẩm được công nhận, và việc băm phản ánh sự hiện diện của chúng. Hai bát có các trường chú thích giống hệt nhau sẽ được coi là bằng nhau, và băm của chúng sẽ tương ứng với nội dung.
So sánh các bát khác nhau
Giả sử bạn có hai bát, mỗi bát chứa cùng một loại vật phẩm:
Mặc dù các bát có thể chứa các đồng xu và nước giống nhau, nhưng chúng khác nhau về hình thức. Python sẽ so sánh cả nội dung và loại đối tượng:
Sự bằng nhau yêu cầu cả các vật phẩm và hình thức phải giống nhau. Trong khi đó, băm chỉ xem xét các trường được chú thích.
Trường so với Biến lớp
Sự phân biệt giữa các trường được chú thích và biến lớp là rất quan trọng. Chỉ có các trường được chú thích mới được coi là vật phẩm bên trong bát. Biến lớp nằm bên ngoài và không góp phần vào sự bằng nhau hay băm.
Dataclass có thể thay đổi và không thể thay đổi
Bạn có thể nhận thấy rằng chúng ta đang khai báo các lớp với frozen=True. Dataclass có thể được tạo ra là có thể thay đổi hoặc không thể thay đổi:
- Dataclass có thể thay đổi cho phép nội dung của nó thay đổi sau khi được tạo ra. Đây là mặc định.
- Dataclass không thể thay đổi làm cho nội dung không thể thay đổi, giống như việc niêm phong các vật phẩm bên trong một bát.
Tính không thể thay đổi cũng ảnh hưởng đến khả năng băm. Chỉ các dataclass không thể thay đổi mới có thể băm một cách tự động, vì các bát có thể thay đổi có thể làm thay đổi nội dung của chúng sau khi đã được đưa vào một tập hợp hoặc được sử dụng làm khóa cho từ điển.
Giá trị mặc định và Nhà máy
Giá trị mặc định giúp việc tạo bát trở nên dễ dàng hơn mà không phải chỉ định từng vật phẩm:
Đối với các trường có thể thay đổi như danh sách hoặc từ điển, cần có một nhà máy mặc định. Sử dụng một đối số mặc định với một đối tượng có thể thay đổi có thể dẫn đến trạng thái chia sẻ giữa các thể hiện:
Điều này xảy ra vì các đối số mặc định được đánh giá một lần tại thời điểm định nghĩa, không phải thời điểm thực thi.
Thay vào đó, một default_factory tạo ra một đối tượng mới cho mỗi thể hiện:
python
from dataclasses import dataclass, field
@dataclass
class Bowl:
items: list = field(default_factory=list)
Giờ đây, mỗi bát có danh sách độc lập của riêng mình. Python sẽ gọi hàm nhà máy tại thời điểm thể hiện được tạo ra, đảm bảo rằng nội dung của mỗi bát vẫn tách biệt.
Sự phân biệt này ngăn chặn các lỗi tinh vi và bảo tồn tính toàn vẹn của nội dung bên trong mỗi bát.
Kết luận và Gọi hành động
Một bát không có vật phẩm đánh dấu không thể phân biệt với một bát rỗng khác cùng loại. Hai bát có thể chứa các vật phẩm giống nhau, nhưng vẫn tách biệt nếu hình thức của chúng khác nhau. Việc băm chỉ phụ thuộc vào nội dung, trong khi sự bằng nhau xem xét cả nội dung và hình thức.
Thông qua việc chú ý đến các trường, tính có thể thay đổi, giá trị mặc định và các phương thức tự động được tạo ra, dataclass cung cấp một cấu trúc đơn giản và dễ dự đoán cho các đối tượng dữ liệu trong Python.
FAQ
Dataclass có thể thay đổi là gì?
Dataclass có thể thay đổi cho phép bạn thay đổi nội dung sau khi đối tượng được tạo ra.
Tôi có thể sử dụng dataclass trong Python 3.6 không?
Không, dataclass được giới thiệu từ Python 3.7 trở đi.
Làm thế nào để sử dụng default_factory trong dataclass?
Bạn có thể sử dụng field(default_factory=...) để chỉ định một hàm tạo giá trị mặc định mới cho mỗi thể hiện.
Hãy bắt đầu sử dụng dataclass trong dự án Python của bạn ngay hôm nay!