Page cover

dataclasses 【數據 Class】

簡介


dataclasses module 用於向用戶定義的 Class 新增 special methods (特殊方法),例如:__init____repr__

使用 Dataclasses 的主要優點是在建立 Class 時減少 Boilerplate code,特別是那些主要儲存數據,但沒有太多行為 (方法) 的 Class。

Dataclasses 自動向 Class 加入 special methods,包括:__init____repr____eq__。 這些 special methods 手動編寫通常很乏味,特別是對於具有許多屬性的 Class。如果需要,也可以自定義和微調這些方法的行為。

數據類的裝飾器是 @dataclasses.dataclass。 這是一個簡單的例子:

PYTHON
import dataclasses

@dataclasses.dataclass
class Point:
    x: int
    y: int

# Create instances of Point (__init__)
p1 = Point(2, 3)
p2 = Point(2, 3)
p3 = Point(3, 4)

# Demonstrates __repr__
print(p1)        # Output: Point(x=2, y=3)

# Demonstrates __eq__
print(p1 == p2)  # Output: True
print(p1 == p3)  # Output: False

Class Point 有兩個 fields xy,這 2 個 fields 都應該是 int

@dataclass 自動加入一個以 xy 作為參數的 __init__ 方法,一個返回物件的字串表示形式的 __repr__ 方法,以及一個 __eq__ 方法,允許根據 Point 的兩個實例的 x 屬性和 y 屬性來比較它們的相等性。

Field


在 Python Dataclasses 的 context 中,field 是綁定到 Class 的變數,並且該 class 的每個實例都將具有其自己的單獨的 field 副本,來存儲特定於實例的狀態。

在傳統的物件導向術語中,這些通常被稱為 "attributes" or "properties"。Dataclasses 中的 fields 直接在 Class 中定義,並且可以指定它們的類型和預設值。

在此範例中,nameagePerson class 的 fields。

name field 應為 strage field 應為 int,預設值為 0。每個 Person 實例都有自己的 nameage fields。

@dataclass


@dataclass 用於生成的 special methods,然後新增到 Class 中。

@dataclass 應用於 Class 時,它會掃描該 Class 的 fields。 在這種情況下,fields 是包含類型註釋的 Class-level 變數。

參數
說明

init

是否將生成 __init__ 方法。 如果 Class 已經定義了 __init__,則忽略此參數。

repr

是否將生成 __repr__ 方法。 生成的 repr String 將包含 Class 名稱以及每個 field 的名稱,按照它們在 Class 中定義的順序排列。 不包括標記為從 repr 中排除的 fields 。如果 Class 已經定義了 __repr__,則忽略此參數。

eq

是否將生成 __eq__ 方法。 此方法按順序比較 Class,僅當它們對應的 fields 相等時,該 Class 的兩個實例才會被比較為相等。如果 Class 已經定義了 __eq__ ,則忽略此參數。

order

是否將生成 __lt__ (小於)、__le__ (小於或等於)、__gt__ (大於) 和 __ge__ (大於或等於) 方法。 這些使得 Class 的實例可排序且具有可比性。如果 field's type 不支援比較,這將引發 TypeError。如果 Class 已經定義了 __lt____le____gt____ge__ 中的任何一個,則會引發 TypeError。

unsafe_hash

如果為 True, 會強制生成 __hash__ 方法,但不建議這樣做,因為它違反了 Python's object model,其中 mutable 物件是 unhashable。 如果為 False,則根據 eqfrozen 的設置方式生成 __hash__ 方法。

frozen

在實例建立後,指派 fields 將會引發 Exception。 類似於其他語言中的唯讀 (凍結;frozen) 數據類型,就像 Tuple 一樣。如果 Class 中定義了 __setattr____delattr__,則會引發 TypeError。

match_args

kw_only

slots

weakref_slot

生成的方法按照 fields 在 Class 中定義的順序使用 fields。

例如: __init__ 方法中的參數順序遵循 Class 中 field 定義的順序。

以下是管理 __hash__ 方法隱式建立的規則。

如果 frozen=True, eq=True,則將生成 __hash__ 方法。

如果 frozen=False, eq=True,則 __hash__ 方法將被設置為 None,將其標記為 unhashable。

如果 frozen=False, eq=False,則 __hash__ 將保持不變,這意味著將使用 Superclass 的 __hash__ 方法 (如果 Superclass 是 object,將回退到 id-based hashing)。

默認情況下,dataclass() 不會隱式生成 __hash__ 方法 (無法對實例使用 hash())。 它也不會更改現有的顯式定義的 __hash__ 方法。

範例 – unsafe_hash (參數)


field()


該函數用於自定義 Data class 中的各個 fields。就像指定了預設值本身一樣。

參數
說明

default

Field 的預設值。

default_factory

為 field 提供預設值的零參數函數,當該 field 需要預設值時將調用。 如果同時指定了 defaultdefault_factory,則會引發 TypeError

init

Field 將作為參數包含在生成的 __init__ 方法中。

repr

Field 將包含在生成的 __repr__ 方法,返回的 String 中。

hash

如果為 True,則該 field 包含在生成的 __hash__ 方法中。 如果為 None (預設值),則使用 compare

compare

Field 將包含在生成的 __eq__, __gt__... 方法中。

metadata

將值包裝在 MappingProxyType() 中,以使其唯讀,並在 field 物件上公開。 它主要用於第三方擴展,Data Classes 本身不使用。

kw_only

MISSING 是一個 Sentinel value 物件,用於檢測使用者是否提供了某些參數。

使用此標記是因為 None 對於某些具有不同含義的參數來說是有效值。 任何程式碼都不應直接使用 MISSING

範例 – 基礎


Data class Employee 有兩個 fields nameage,這兩個 fields 都具有使用 dataclasses.field() 指定的預設值。

default_factory 參數: 當您想要生成每次都應該是新物件的預設值時,default_factory 非常有用。(例如:空 List 或當前時間戳)

repr 參數: color field 從 __init__, __repr__ 方法中排除。因此在建立 Point 實例時不需要提供它,在打印 Point 物件時不包括它。

範例 – Mutable 物件


如果 field 是 mutable (例如: List, Dictionary),並且您為其提供預設值,則應該使用 default_factory 來提供一個函數,該函數在每次創建新實例時生成新值。 這避免了在多個實例之間共享相同的可變的值。

fields()


fields(class_or_instance) 獲取為特定 Dataclasses 或 Dataclass 實例定義的每個 Field 物件的 metadata。

透過使用 fields(),我們可以對程式碼中的 Dataclasses 進行更詳細的控制和理解。 這對於大量使用 Dataclasses 的複雜程序或 libraries 特別有用。

雖然 fields() 函數提供有關 Dataclass 的有用訊息,但您應該謹慎使用它們,因為訪問 metadata 可能會減慢您的程序速度。 大多數時候,您只需要直接訪問 fields 的值。

執行結果:

範例 – 基礎


執行結果:

asdict()


asdict(obj, *, dict_factory=dict) 每個 Dataclass fields 都轉換為 Dictionary,作為 name: value pairs。

透過 dict_factory,將 Dataclass obj 轉換為 dict。(deep copy)

範例 – 具有複雜 field 類型的 Dataclass


執行結果:

collections.OrderedDict 保證 fields 的顯示順序與 Dataclass 中定義的順序相同。

執行結果:

範例 – shallow_copy(obj)


asdict() 方法創建一個 deep copy,它比 shallow copy 的計算量更大,特別是對於大型 Dataclasses。

如果您知道不需要修改 Dataclass 中的任何物件,並且只需要它的簡單 dictionary 表示形式,則 shallow_copy(obj) 可能會更有效。

或者,如果您想要維護 dataclass 實例,您可能需要使用 shallow_copy(obj)

astuple()


astuple(obj, *, tuple_factory=tuple) 每個 Dataclass fields 都轉換為 Tuple。透過 dict_factory,將 Dataclass obj 轉換為 tuple

Last updated

Was this helpful?