
make_dataclass()
創建一個新的 Dataclass。
此函數並不是嚴格必需的,提供此函數只是為了方便。你可以使用 dataclass() 來代替 make_dataclass()。
make_dataclass(cls_name,
fields, *,
bases=(),
namespace=None,
init=True,
repr=True,
eq=True,
order=False,
unsafe_hash=False,
frozen=False,
match_args=True,
kw_only=False,
slots=False,
weakref_slot=False,
module=None)cls_name
Dataclass 名稱。
fields
fields 的定義,是一個 iterable 物件。
fields 的元素可以是 name、(name, type) 或 (name, type, Field)。如果僅提供 name ,則轉變為 (name, typing.Any) (應用 typing.Any)。
bases
為正在建立的 Dataclass 指定多個 Base class。 生成的 Class 將從一個或多個 Base class 繼承。
namespace
向 Class 新增其他方法或屬性。
使用 namespace 中給定的命名空間進行初始化)。您可以提供一個 Dictionary,其中 Keys 是方法或屬性的名稱,Values 是實際的實現。
module
如果定義了module,則 Dataclass 的 __module__ 屬性將設置為該值。 預設情況下,設置為調用者的 module 名稱。
當您需要動態創建新 Classes 時,make_dataclass() 會非常有用。 對於靜態定義的 Classes,使用 @dataclass 可以更具可讀性。
bases 和 namespace 參數可以成為動態創建複雜 Dataclasses 的強大工具。 但是,它們也會使您的程式碼更難以理解和 debug。
如果您熟悉傳統的 Python Class 和繼承,在許多情況下,您最好使用 @dataclass 和傳統的 Class 來定義。
範例 – 基礎
範例 – bases, namespace (參數)
replace()
建立一個新物件實例,與 obj 類型相同,且用 changes 中的值替換 fields。
當您想要建立新的實例改變某些 fields,但希望保持原始 Dataclass 實例不變時,replace() 函數非常有用。
例如:如果您有一個 Dataclass 實例,表示特定時間點某事物的狀態 ,並且您想要表示一個新狀態。但您不想更改原始實例,而是建立一個表示新狀態的新實例。
範例 – init=False
在 Python 的 dataclasses 中,init=False field 是一個不打算作為參數傳遞給產生的 __init__ 方法的 field。相反,預計該欄位將在 __post_init__ 方法中,設定或保留為指定的預設值。
但是,當使用 dataclasses.replace() (目的在建立一個新物件作為現有物件的副本,並將某些欄位替換為新值) 時,init=False field 的行為有所不同。
它們不會從 "source" 物件複製。相反,它們將被設定為就像正在創建一個新物件一樣,這意味著它們將是:
如果提供了預設值,則保留預設值。
如果設定了它們,則在
__post_init__中進行設定。未初始化。(如果以上都不成立)
在這個例子中:
id是一個init=Falsefield。實例化後,呼叫__post_init__,它設定id。當呼叫
replace(product, name="Chair")時,會有效地建立一個新的Product實例,並將name設定為Chair。id不是從product複製的,而是再次呼叫__post_init__,根據新的name產生新的id。
如果您期望 replace() 從原始物件複製所有 fields,這種行為可能會令人驚訝。因此,在使用 init=False fields 時,您應該意識到這一點。
如果您想要不同的行為,例如明確複製 init=False 字段,您可以提供自訂替換方法。自訂 replace 方法可確保 init=False field (本例中為 id) 被轉移到新實例,除非它被明確變更。
is_dataclass()
is_dataclass(obj) 檢查給定的 obj 物件是否是 Dataclass 實例或 Dataclass 本身。 如果 obj 物件是 Dataclass 或 Dataclass 實例,則返回 True。
如果您需要知道一個 Class 是否是 Dataclass 的實例,而不是 Dataclass 本身。請進一步檢查 isinstance(obj, type),即 is_dataclass_instance(obj)。
範例:
__post_init__
此方法在調用 data class 的 __init__ 方法後立即調用,為初始化後處理提供方便的 hook。
這對於執行其他屬性初始化、驗證或建立 dataclass 的新實例時,需要進行的任何其他自訂設定非常有用。
__post_init__ 的用法:
初始化驗證: 在物件初始化後使用
__post_init__來驗證資料。在範例中,它檢查unit_price是否為負數,如果是則引發ValueError。派生屬性: 計算從傳遞給
__init__方法的屬性派生的屬性。在範例中,total_price是根據unit_price和quantity_on_hand計算得出的。類型檢查: 執行自訂類型檢查。該範例確保
serial_numbers是一個列表,如果不是,則會引發TypeError。預設可變性: 當使用可變預設值(例如: Lists, Dictionaries)時,使用
default_factory。這是因為在使用可變預設值時,預設值在 class 的所有實例之間共享,從而導致潛在的錯誤。副作用: 如果您需要在建立實例後執行一些副作用,
__post_init__是一個好地方。(例如: logging (日誌記錄)、在某些 registry (註冊表) 中註冊等)Field 初始化: 有時你需要設定不是 fields 的實例變數 (未在 class 中定義)。
__post_init__可用來設定這些特定於實例的屬性,這些屬性不需要是 fields。附加屬性: 也可以為 dataclass 實例新增未定義為 fields 的附加屬性,在範例中,為
total_price。Non-Field 預設值: 對於初始化不應作為參數傳遞給
__init__方法的屬性,您可以在__post_init__中指派它們,可以使用直接值或基於其他 fields 的計算。
透過使用 __post_init__,您可以確保 data class 實例,在應用程式的其餘部分使用之前,始終處於有效狀態,從而使其成為強大且自我驗證的資料模型的強大功能。
MISSING, KW_ONLY
MISSINGSentinel value 僅提供default和default_factory設置預設值。
我們應該避免在應用程序代碼中使用 MISSING 。MISSING 僅在 dataclasses module 幕後使用,並發揮它魔法。
KW_ONLYSentinel value 是一種用於指定 Dataclass 的某些 fields 應為 keyword-only arguments。
對於 Dataclass,這意味著在創建 Dataclass 的實例時,必須使用 keyword syntax 提供這些參數。 當您有許多參數時,這對於增強程式碼可讀性和防止錯誤非常有用。
KW_ONLY (pseudo-field) 指示 keyword-only fields 的開始,在此之後定義的任何 fields 都將被視為 keyword-only。 該 pseudo-field 的名稱將被忽略,並且按照慣例,使用 _。
參考資料
dataclasses — Data Classes — Python 3.12.0b4 documentation
Last updated
Was this helpful?