CodeGym /課程 /Python SELF TW /管理序列化

管理序列化

Python SELF TW
等級 22 , 課堂 2
開放

10.1 一切都依我想!

有時候,你的物件裡面可能會有很多不想透過網路傳遞的服務器物件,或者根本不能傳遞的東西,比如檔案、資料庫等等。

為了讓序列化也能在這種情況下運作,我們讓類別自己管理自己的序列化。這就是我們要用到一些特殊的method:__reduce__()__getstate__()__setstate__()。這些method 讓你能夠指定物件該如何被序列化和還原。

主要的控制序列化的方法:

  • __reduce__():指定物件該如何被序列化。
  • __getstate__():返回用於序列化的物件狀態。
  • __setstate__(self, state):從狀態中還原物件。

下面我會詳細說明它們,以及如何一起使用。

10.2 方法 __reduce__()

方法 __reduce__() 返回一個 tuple,指示物件該如何被序列化和反序列化。這個 tuple 通常包含:

  • 用於還原物件的 function 或 class 的引用。
  • 用於該 function 或 class 的 arguments 的 tuple。
  • 物件的額外狀態(如果需要)。

範例:


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})"
            
# 創建物件
obj = CustomClass(42)
            
# 序列化物件
serialized_obj = pickle.dumps(obj)
print("序列化的物件:", serialized_obj)
            
# 反序列化物件
deserialized_obj = pickle.loads(serialized_obj)
print("反序列化的物件:", deserialized_obj)

預設情況下,function __reduce__() 的行為是這樣的:


class CustomClass:
    def __init__(self, value):
        self.value = value
        
    def __reduce__(self):
        # 定義類別
        cls = self.__class__
        # 建構子參數
        args = (self.value,)
        # 物件狀態
        state = self.__dict__
        return (cls, args, state)

它返回一個包含三個物件的 tuple:

  • 當前類別的引用
  • 建構子參數(tuple)
  • 當前物件狀態的引用

如果你滿意這種行為,可以不必重新定義 __reduce__()

10.3 讀取和寫入狀態

方法 __getstate__()__setstate__()

這些方法用來在序列化和反序列化過程中管理物件的狀態。

  • __getstate__():返回需要序列化的物件狀態。
  • __setstate__(self, state):從狀態中還原物件。

範例:

假設我們不想保存物件的所有屬性,而想排除某些屬性。為此在 __getstate__() 方法中需要:

  1. 把當前物件的狀態(由服務性字段 __dict__ 定義)拷貝到一個單獨的變量——字典 state
  2. 刪除不需要序列化的所有屬性。
  3. 將獲得的物件作為 __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']  # 排除內部狀態
        return state
            
    def __setstate__(self, state):
        self.__dict__.update(state)
        self.internal_state = "restored internal"  # 還原內部狀態
            
    def __repr__(self):
        return f"CustomClass(value={self.value}, internal_state={self.internal_state})"
            
# 創建物件
obj = CustomClass(42)
print("原始物件:", obj)
            
# 序列化物件
serialized_obj = pickle.dumps(obj)
print("序列化的物件:", serialized_obj)
            
# 反序列化物件
deserialized_obj = pickle.loads(serialized_obj)
print("反序列化的物件:", deserialized_obj)

在反序列化時,在 __setstate__() 方法中,我們做兩件事情:

  1. 使用 update() 方法更新當前物件的狀態。
  2. 對於 internal_state 等不需要序列化的屬性賦新值。
1
問卷/小測驗
處理目錄,等級 22,課堂 2
未開放
處理目錄
處理目錄
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION