欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python?@dataclass裝飾器舉例詳解

 更新時間:2025年08月01日 09:48:50   作者:添財小哥  
裝飾器是Python中的一種高級功能,它允許你動態(tài)地修改函數(shù)或類的行為,這篇文章主要介紹了Python?@dataclass裝飾器的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

1. 用途和主要功能

@dataclass 是 Python 3.7 引入的一個裝飾器(位于標(biāo)準(zhǔn)庫 dataclasses 模塊中),用于簡化“純數(shù)據(jù)”類的定義。它自動為類生成常用的特殊方法(如 init、repr、eq 等),避免手動編寫冗余模板代碼。這樣定義的數(shù)據(jù)類在代碼量和可讀性上都有顯著優(yōu)勢,如便于維護、減少錯誤。使用 @dataclass 后,我們“可以直接創(chuàng)建和操作對象,而無需手動編寫這些基礎(chǔ)方法”??傮w而言,@dataclass 提高了代碼的一致性和可維護性,尤其適用于以存儲數(shù)據(jù)為主的場景。

優(yōu)勢總結(jié):

  • 自動生成 init、repreq 等方法,減少樣板代碼
  • 支持字段默認(rèn)值、類型注解等特性,使類定義更簡潔清晰。
  • 內(nèi)置支持可選的排序、不可變(凍結(jié))等功能,無需額外實現(xiàn)。
  • 可與類型檢查工具兼容,且保持 Python 代碼風(fēng)格。

2.基本用法

基本用法示例如下:只需從 dataclasses 模塊導(dǎo)入裝飾器,使用 @dataclass 標(biāo)注類,類體中定義帶類型注解的字段即可。示例代碼:

from dataclasses import dataclass

@dataclass
class InventoryItem:
    """庫存項目的數(shù)據(jù)類示例"""
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

如官方文檔所示,上例自動生成了類似下面的 init() 方法

def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0):
    self.name = name
    self.unit_price = unit_price
    self.quantity_on_hand = quantity_on_hand

此外,默認(rèn)情況下還會生成符合字段順序的 repreq 方法,使得打印實例和比較相等都更方便。例如:

item = InventoryItem("widget", 3.0, 10)
print(item)            # 輸出: InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)
item2 = InventoryItem("widget", 3.0, 10)
assert item == item2   # 基于字段值進行比較

以上示例中,InventoryItem 類依然可以定義自定義方法(如 total_cost),@dataclass 只負(fù)責(zé)處理字段相關(guān)的方法生成,不會影響其它方法定義

3. 參數(shù)詳解

@dataclass 裝飾器支持多種可選參數(shù),用于控制生成方法的行為及類的特性。常見參數(shù)及其含義如下(括號內(nèi)為默認(rèn)值):

  • init(bool,默認(rèn) True):生成 init() 方法。如果類已顯式定義了 init,則忽略此參數(shù)
  • repr(bool,默認(rèn) True):生成 repr() 方法。生成的字符串包含類名及所有字段名和對應(yīng)值(以字段定義順序排列)??赏ㄟ^ field(repr=False) 排除個別字段。
  • eq(bool,默認(rèn) True):生成 eq() 方法,將實例按字段順序比較。只有類型相同的兩個實例才可能相等。如果已定義 eq,則忽略此參數(shù)。
  • order(bool,默認(rèn) False):生成排序比較方法 lt、le、gtge,按字段順序比較;要求 eq=True,否則拋出 ValueError。如果類中已定義任一比較方法,則拋出 TypeError。
  • unsafe_hash(bool,默認(rèn) False):控制 hash() 方法的生成。默認(rèn)情況下,如果同時 eq=True 且 frozen=False,則會將 hash 設(shè)為 None(實例不可哈希);如果同時 eq=True 且 frozen=True,則生成與字段相關(guān)的 hash。設(shè)為 True 時,會強制生成 hash(),即使實例可變,這通常只在特殊情況下使用。
  • frozen(bool,默認(rèn) False):如果為 True,則生成的類會“凍結(jié)”實例,使字段賦值變?yōu)橹蛔x(在嘗試修改字段時拋出異常),模擬不可變對象。注意這對性能有小幅影響:init 不能使用普通賦值,而是通過 object.setattr() 初始化。如果類中已定義 setattrdelattr,則拋出 TypeError。
  • match_args(bool,默認(rèn) True,自 3.10 起):控制是否生成 match_args 屬性(用于結(jié)構(gòu)化模式匹配)。為 True 時,match_args 包含所有非僅關(guān)鍵字字段名的元組(按定義順序);若字段中已有定義則不會覆蓋(3.10+)。
  • kw_only(bool,默認(rèn) False,自 3.10 起):將所有字段標(biāo)記為僅關(guān)鍵字字段,即在生成的 init() 中,這些字段只能通過關(guān)鍵字參數(shù)傳入。僅限關(guān)鍵字字段不會包含在 match_args 中。
  • slots(bool,默認(rèn) False,自 3.10 起):生成 slots 并返回一個新的類而非原始類;這樣實例會使用槽來存儲屬性(節(jié)省內(nèi)存)。如果類中已定義 slots,則拋出 TypeError。注意:使用 slots=True 時,普通的無參 super() 在 init() 中可能報錯(需要使用帶參 super());此外,如果基類定義了槽位,任何相同名稱的字段不會重復(fù)在子類槽位中。
  • weakref_slot(bool,默認(rèn) False,自 3.11 起):如果為 True(必須同時 slots=True),則在 slots 中增加 “weakref” 槽位,使實例可以被弱引用

以上參數(shù)均可通過 @dataclass(…) 形式傳入,或直接 @dataclass 使用默認(rèn)值。以官方文檔為例,以下三種寫法是等價的:

@dataclass
class C: ...
@dataclass()
class C: ...
@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, 
           frozen=False, match_args=True, kw_only=False, slots=False)
class C: ...

4. 底層設(shè)計邏輯

@dataclass 在類創(chuàng)建時動態(tài)修改類定義,以生成所需的方法和屬性。其核心實現(xiàn)機制包括:

  • 類型注解與字段識別:dataclass 通過類的 annotations 字典識別字段名稱和類型。只有帶有類型標(biāo)注的類變量才被視為字段(ClassVar 注解的字段會被忽略)。上述示例中,InventoryItem.annotations 將包含 {‘name’: str, ‘unit_price’: float, ‘quantity_on_hand’: int}
  • Field 對象:每個字段在內(nèi)部被表示為一個 dataclasses.Field 對象,記錄該字段的元信息(名稱、類型、默認(rèn)值、init/repr/hash/compare 標(biāo)志、metadata 等)。字段默認(rèn)值可直接賦值,也可通過 field(default=…) 或 field(default_factory=…) 指定;如無提供默認(rèn),則該類屬性會在裝飾后被刪除。例如調(diào)用 dataclasses.fields(cls) 可返回一個由 Field 對象組成的元組,描述該數(shù)據(jù)類的所有字段(不包括 ClassVar 和 InitVar 等偽字段)
  • 方法生成:根據(jù)收集到的字段信息,dataclass 通過動態(tài)生成代碼(通常借助 exec 執(zhí)行生成的函數(shù)定義字符串)來創(chuàng)建方法。正如博主指出,“實現(xiàn)這個裝飾器功能的核心有兩個:annotations 屬性和 exec 函數(shù)”。因此,它能夠自動生成包含所有字段賦值的 init,格式化輸出的 repr,以及基于字段的比較方法等。生成的字段順序嚴(yán)格遵循類定義中的順序
  • 繼承支持:dataclass 支持類繼承。當(dāng)子類使用 @dataclass 時,裝飾器會按逆向 MRO(從 object 開始)將所有基類的字段收集到一個有序映射中,然后再加入自身的字段。這樣生成的方法會考慮基類字段和子類字段,子類可通過重新定義字段(相同名稱)覆蓋基類字段類型或默認(rèn)值。比如:
@dataclass
class Base:
    x: Any = 15.0
    y: int = 0

@dataclass
class C(Base):
    z: int = 10
    x: int = 15

最終 C 的字段順序為 (‘x’, ‘y’, ‘z’),其中 x 的類型為 int(覆蓋了 Base 的定義)。

  • slotsannotations:如前所述,設(shè)置 slots=True 時,dataclass 會為類生成 slots 并返回新類,反之則保留使用 dict 存儲屬性。重要提示:不要依賴 slots 來獲取字段名,應(yīng)使用 dataclasses.fields() 獲取字段列表.
  • post_init 鉤子:如果類定義了 post_init(self, *args) 方法,生成的 init() 會在設(shè)置完所有字段后自動調(diào)用它。這對于根據(jù)其他字段計算附加字段或在初始化后執(zhí)行自定義邏輯很有用。例如,如果有依賴于其他字段值的字段 c,可以在 post_init 中計算它。需要注意的是,dataclass 生成的 init 不會自動調(diào)用父類的 init,因此在繼承時若父類需要初始化工作,應(yīng)在 post_init 中手動調(diào)用 super().init()。
    總之,@dataclass 內(nèi)部利用類的注解信息和動態(tài)代碼生成,在類對象上“就地”添加所需的特殊方法和元數(shù)據(jù),并維護字段順序等信息。它通過 annotations 與 Field 對象管理字段,通過 exec 等機制生成代碼,同時暴露如 fields()、asdict() 等輔助函數(shù)來訪問數(shù)據(jù)類結(jié)構(gòu)。

5. 使用場景

dataclass 適用于定義主要用于存儲數(shù)據(jù)且方法較少的類,常見場景包括:

  • 數(shù)據(jù)容器/記錄類:如描述庫存項、點坐標(biāo)、配置項、數(shù)據(jù)庫記錄等擁有多字段的“結(jié)構(gòu)體”類。相比手寫類,dataclass 讓定義這種純粹的數(shù)據(jù)容器更簡單。
  • 配置/參數(shù)類:在需要傳遞眾多配置參數(shù)時,可以定義一個 @dataclass 包含所有配置項,并利用默認(rèn)值和類型注解保證一致性。
  • 不可變對象:通過設(shè)置 frozen=True,可以創(chuàng)建不可變(只讀)對象,用作哈希表鍵或者保證狀態(tài)不被篡改。例如幾何點、金融數(shù)據(jù)的快照等。
  • 結(jié)構(gòu)化數(shù)據(jù)建模:在數(shù)據(jù)分析或業(yè)務(wù)模型中,用 dataclass 定義實體(如用戶、訂單、日志條目)更為直觀,并且配合 asdict()、astuple() 等函數(shù)可方便地序列化/轉(zhuǎn)換。
  • 與 typing 模塊協(xié)作:可以結(jié)合類型檢查器(如 Mypy)使用 dataclass,保證字段類型一致。與 TypedDict 對比,TypedDict 更像“動態(tài)字典”(適合外部輸入或靈活字段),而 dataclass 類似有固定列的表格;后者帶有方法和可選的不可變性、嚴(yán)格的類型檢查。
  • NamedTuple 的替代:相比 namedtuple(基于元組,不可變,使用 _replace() 修改),指出 dataclass 默認(rèn)是可變的(可以直接賦值改變屬性),但也可通過 frozen=True 獲得類似的不可變特性。一般來說,如果需要類風(fēng)格的寫法(可添加方法)和可變性,dataclass 更靈活;若需要內(nèi)存占用更小的輕量結(jié)構(gòu),可使用 namedtuple。
    總體而言,任何需要“字段+行為”的簡單數(shù)據(jù)類場景,都可以考慮使用 @dataclass 以提高開發(fā)效率和代碼可讀性。

6. 高級用法與擴展

  • field() 函數(shù):配合 dataclasses.field() 可對單個字段進行精細(xì)控制。常用參數(shù)包括 default、default_factory、repr、compare、hash、init、metadata 等。例如:
from dataclasses import dataclass, field

@dataclass
class C:
    # 默認(rèn)工廠:為每個實例生成一個新列表
    items: list = field(default_factory=list, repr=False, metadata={"info": "緩存列表"})

如上所示,default_factory=list 確保每個實例的 items 字段初始為一個獨立的空列表(避免多個實例共享同一個列表)。repr=False 則讓 items 字段不出現(xiàn)在自動生成的 repr 中。metadata 可以附加任意只讀元數(shù)據(jù)(以供框架或工具使用),Dataclasses 本身不使用它。

  • 默認(rèn)工廠:對于可變類型的默認(rèn)值(如列表、字典等),應(yīng)該使用 default_factory。官方文檔指出,如果將可變類型直接作為默認(rèn)參數(shù),dataclass 會在檢測到時拋出 TypeError 來避免錯誤。正確做法是使用 field(default_factory=…),這樣每次創(chuàng)建實例時都會調(diào)用工廠函數(shù)生成新對象,避免不同實例間的數(shù)據(jù)污染。
  • 僅初始化變量 (InitVar):dataclasses.InitVar 可用于聲明僅在 init 時使用的臨時參數(shù)。這些 InitVar 字段不會成為類的實際字段,也不會出現(xiàn)在 fields() 返回值中,而是作為參數(shù)傳遞給 post_init。這常用于在初始化時用某個值計算或設(shè)置其它字段,但不將其保留。例如:
from dataclasses import dataclass, field, InitVar

@dataclass
class C:
    x: int
    data_source: InitVar[str] = None

    def __post_init__(self, data_source):
        if self.x is None and data_source:
            self.x = load_default_from(data_source)
  • 繼承與重寫:子類可以繼承父類數(shù)據(jù)類,并在子類中添加字段或重新定義字段。dataclass 會自動管理字段順序(父類字段排在前,子類字段排在后)在子類中定義與父類同名的字段會覆蓋父類字段的類型或默認(rèn)值,如上文示例所示。
  • 比較 NamedTuple、TypedDict 等:前面提到,dataclass 與 namedtuple 最大區(qū)別在于:namedtuple 創(chuàng)建的是元組子類,不可變(需用 _replace 更新),而 dataclass 創(chuàng)建的是普通類實例,默認(rèn)可變。也可以設(shè)置 frozen=True 實現(xiàn)不可變。與 TypedDict 相比,dataclass 更像電子表格,有嚴(yán)格的列定義和可選的不變性,并自帶方法。一般建議:如果需要靈活的字典結(jié)構(gòu),使用 TypedDict;如果需要具有行為的正規(guī)類結(jié)構(gòu),則使用 dataclass。
  • 其他擴展:Python 的類型檢查插件(如 Pyright、Mypy)支持 @dataclass,可以利用類型注解進行靜態(tài)檢查。此外,也可與第三方庫結(jié)合,如 Pydantic(用于驗證模型數(shù)據(jù))或 attrs(一個更早的類似庫)。從 Python 3.10 開始,dataclass 還支持新語法(如結(jié)構(gòu)化模式匹配的 match_args、僅關(guān)鍵字字段等)。

7. 注意事項與局限性

  • 可變默認(rèn)值:正如前述,避免將可變對象(list、dict、set 等)直接作為字段默認(rèn)值。官方文檔明確,當(dāng)裝飾器檢測到這樣的可變默認(rèn)時會拋出 TypeError。正確做法是使用 default_factory;例如 x: list = field(default_factory=list) 確保每個實例擁有獨立的列表。
  • hash 與 eq/frozen:默認(rèn)情況下,如果 eq=True 且 frozen=False,dataclass 會將 hash 置為 None,使得對象不可哈希(因為可變對象不安全作為哈希鍵)。如果需要可哈希的可變對象,可設(shè)置 unsafe_hash=True 強制生成哈希方法。
  • 基類 init:如前所述,dataclass 生成的 init() 不會自動調(diào)用父類的 init()。因此,如果基類的數(shù)據(jù)類或普通類 init 有初始化邏輯,需要在子類的 post_init 中手動調(diào)用 super().init()。
  • slots=True 的陷阱:啟用 slots 后,實例不再有 dict,會節(jié)省內(nèi)存,但要注意:無參數(shù)的 super() 在 init 中可能失??;此外避免通過 slots 來訪問字段名,使用 fields()。
  • 性能影響:創(chuàng)建凍結(jié)實例 (frozen=True) 會略微降低初始化速度,因為字段賦值使用底層機制。此外,盡管 dataclass 簡化了代碼,它生成的方法開銷與手寫的并無本質(zhì)差別。
  • Python 版本兼容性:dataclasses 是 Python 3.7+ 的特性。若需要在 Python 3.6 中使用類似功能,可以安裝第三方 dataclasses 包(部分 backport 功能)。3.10 和更高版本引入了如 kw_only、slots、match_args 等新選項;3.11 增加了 weakref_slot。在低于 3.7 的環(huán)境中或需兼顧新特性時,應(yīng)注意相應(yīng)版本的支持情況。

總結(jié) 

到此這篇關(guān)于Python @dataclass裝飾器的文章就介紹到這了,更多相關(guān)Python @dataclass裝飾器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python外星人入侵游戲編程完整版

    Python外星人入侵游戲編程完整版

    這篇文章主要為大家詳細(xì)介紹了Python外星人入侵游戲編程完整的實現(xiàn)思路,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Pycharm學(xué)習(xí)教程(1) 定制外觀

    Pycharm學(xué)習(xí)教程(1) 定制外觀

    這篇文章主要介紹了最全的Pycharm學(xué)習(xí)教程第一篇如何定制外觀,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • python中的yield使用方法

    python中的yield使用方法

    這篇文章主要介紹了python中的yield使用方法,需要的朋友可以參考下
    2014-02-02
  • python中常用的九個語法技巧

    python中常用的九個語法技巧

    大家好,本篇文章主要講的是python中常用的九個語法技巧,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • Python實現(xiàn)給PDF添加水印的方法

    Python實現(xiàn)給PDF添加水印的方法

    這篇文章主要介紹了Python實現(xiàn)給PDF添加水印的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Python可視化單詞統(tǒng)計詞頻統(tǒng)計中文分詞的實現(xiàn)步驟

    Python可視化單詞統(tǒng)計詞頻統(tǒng)計中文分詞的實現(xiàn)步驟

    這篇文章主要介紹了Python可視化單詞統(tǒng)計詞頻統(tǒng)計中文分詞,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-11-11
  • DataFrame:通過SparkSql將scala類轉(zhuǎn)為DataFrame的方法

    DataFrame:通過SparkSql將scala類轉(zhuǎn)為DataFrame的方法

    今天小編就為大家分享一篇DataFrame:通過SparkSql將scala類轉(zhuǎn)為DataFrame的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • Python進程間通信Queue實例解析

    Python進程間通信Queue實例解析

    這篇文章主要介紹了Python進程間通信Queue實例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Python利用字典破解WIFI密碼的方法

    Python利用字典破解WIFI密碼的方法

    今天小編就為大家分享一篇關(guān)于Python利用字典破解WIFI密碼的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Tensorflow 如何從checkpoint文件中加載變量名和變量值

    Tensorflow 如何從checkpoint文件中加載變量名和變量值

    這篇文章主要介紹了Tensorflow 如何從checkpoint文件中加載變量名和變量值的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-05-05

最新評論