10.1 Mọi thứ theo cách của mình!
Đôi khi trong các đối tượng của bạn lưu trữ nhiều tham chiếu đến các đối tượng dịch vụ khác nhau mà bạn không muốn truyền qua mạng, hoặc không thể truyền qua mạng: các tham chiếu đến tệp, cơ sở dữ liệu, vv.
Để serialization hoạt động trong những trường hợp như vậy, người ta đã nghĩ ra cách cho phép lớp tự quản lý serialization của mình. Để làm điều này,
sử dụng các phương thức đặc biệt: __reduce__()
,
__getstate__()
, __setstate__()
. Các phương thức này
cho phép chỉ định cách các đối tượng cần được serialize và
khôi phục.
Các phương thức chính trong quản lý serialization:
-
__reduce__()
: Chỉ định cách một đối tượng nên được serialize. -
__getstate__()
: Trả về trạng thái của đối tượng để serialize. -
__setstate__(self, state)
: Khôi phục đối tượng từ trạng thái.
Mình sẽ nói về chúng chi tiết hơn và cách sử dụng chúng cùng nhau ở dưới.
10.2 Phương thức __reduce__()
Phương thức __reduce__()
trả về một tuple,
chỉ định cách đối tượng nên được serialize và
deserialize. Tuple thường chứa:
- Tham chiếu đến một hàm hoặc lớp nào đó sẽ được sử dụng để khôi phục đối tượng.
- Tuple các đối số cho hàm hoặc lớp đó.
- Trạng thái bổ sung của đối tượng (nếu cần).
Ví dụ:
import pickle
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
return (self.__class__, (self.value,))
def __repr__(self):
return f"CustomClass(value={self.value})"
# Tạo đối tượng
obj = CustomClass(42)
# Serialize đối tượng
serialized_obj = pickle.dumps(obj)
print("Đối tượng đã được serialize:", serialized_obj)
# Deserialize đối tượng
deserialized_obj = pickle.loads(serialized_obj)
print("Đối tượng đã được deserialize:", deserialized_obj)
Mặc định, hàm __reduce__()
có hành vi như sau:
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
# Định nghĩa lớp
cls = self.__class__
# Đối số của constructor
args = (self.value,)
# Trạng thái của đối tượng
state = self.__dict__
return (cls, args, state)
Nó trả về một tuple gồm ba đối tượng:
Tham chiếu đến lớp hiện tại
Đối số của constructor (tuple)
Tham chiếu đến trạng thái hiện tại của đối tượng
Nếu bạn thấy hành vi này thoải mái — không cần
phải ghi đè __reduce__()
.
10.3 Đọc và ghi trạng thái
Các phương thức __getstate__()
và
__setstate__()
Các phương thức này được sử dụng để quản lý trạng thái của đối tượng trong khi serialization và deserialization.
-
__getstate__()
: Trả về trạng thái của đối tượng, cần phải serialize. -
__setstate__(self, state)
: Khôi phục đối tượng từ trạng thái.
Ví dụ:
Giả sử chúng ta muốn lưu trữ không phải tất cả các trường của đối tượng, mà loại trừ
một số trong số chúng. Để làm điều này trong phương thức __getstate__()
cần:
-
Sao chép trạng thái hiện tại của đối tượng (được xác định bởi trường dịch vụ
__dict__
) vào một biến riêng biệt — từ điểnstate
. - Xóa khỏi nó tất cả các trường không cần serialize.
- Trả về đối tượng đã nhận được như kết quả của hàm
__getstate__()
.
import pickle
class CustomClass:
def __init__(self, value):
self.value = value
self.internal_state = "internal"
def __getstate__(self):
state = self.__dict__.copy()
del state['internal_state'] # Loại trừ trạng thái nội bộ
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.internal_state = "restored internal" # Khôi phục trạng thái nội bộ
def __repr__(self):
return f"CustomClass(value={self.value}, internal_state={self.internal_state})"
# Tạo đối tượng
obj = CustomClass(42)
print("Đối tượng ban đầu:", obj)
# Serialize đối tượng
serialized_obj = pickle.dumps(obj)
print("Đối tượng đã được serialize:", serialized_obj)
# Deserialize đối tượng
deserialized_obj = pickle.loads(serialized_obj)
print("Đối tượng đã được deserialize:", deserialized_obj)
Khi deserialization, trong hàm __setstate__()
, chúng ta thực hiện hai điều:
-
Cập nhật trạng thái hiện tại của đối tượng với phương thức
update()
. -
Trường
internal_state
(và các trường không serialize khác) nhận các giá trị mới.
GO TO FULL VERSION