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

Python中的數(shù)據(jù)類dataclass解讀

 更新時(shí)間:2024年01月25日 16:36:09   作者:be5yond  
這篇文章主要介紹了Python中的數(shù)據(jù)類dataclass使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

1. 為什么需要數(shù)據(jù)類

1.1 ??內(nèi)置數(shù)據(jù)類型的局限

假設(shè)我們現(xiàn)在遇到一個(gè)場(chǎng)景, 需要一個(gè)數(shù)據(jù)對(duì)象來(lái)保存一些運(yùn)動(dòng)員信息.

可以選擇使用基本的數(shù)據(jù)類型tuple或者dict實(shí)現(xiàn). 如:創(chuàng)建一個(gè)球員jordan, 信息包括球員姓名, 號(hào)碼,  位置, 年齡.

使用tuple

In [1]: jordan = ('Micheal Jordan', 23, 'PG', 29)
In [2]: jordan[0]
Out[2]: 'Micheal Jordan'

劣勢(shì):創(chuàng)建和取值基于位置,  需要記住坐標(biāo)對(duì)應(yīng)的信息. 

使用dict

In [3]: jordan = {'name': 'Micheal Jordan', 'number': 23, 'position': 'PG', 'age': 29}
In [4]: jordan['position']
Out[4]: 'PG'

使用字典之后, 獲取信息時(shí)會(huì)相對(duì)直觀, 但是相較于字典的括號(hào)語(yǔ)法 jordan["position"] 我們更希望可以用類似獲取屬性一樣使用 jordan.postion. 

劣勢(shì):無(wú)法對(duì)數(shù)據(jù)屬性名進(jìn)行控制,

少值或者錯(cuò)值,如, jordan = {'name': 'Micheal Jordan', 'NUMBER': 23} 一樣可以創(chuàng)建成功.

1.2 ??使用命名元組 namedtuple

為了解決這種問(wèn)題, python 中的 collections 模塊提供一個(gè)命名元組, 可以使用點(diǎn)表示法和字段名稱訪問(wèn)給定命名元組中的值. 

使用namedtuple代碼如下

In [5]: from collections import namedtuple
 
In [6]: Player = namedtuple('Player', ['name', 'number', 'position', 'age', 'grade'])
In [7]: jordan = Player('Micheal Jordan', 23, 'PG', 29, 'S+')
 
In [8]: jordan
Out[8]: Player(name='Micheal Jordan', number=23, position='PG', age=29, grade='S+')

使用namedtuple之后

① 可以使用 '.'語(yǔ)法獲取數(shù)據(jù)的屬性, 可以限制數(shù)據(jù)的屬性名稱,

② 創(chuàng)建對(duì)象時(shí)數(shù)據(jù)不匹配會(huì)報(bào)錯(cuò).

In [9]: jordan.number
Out[9]: 23
 
In [10]: bryant = Player('Kobe Bryant', 24, 'PG')
---------------------------------------------------------------------------
TypeError: __new__() missing 2 required positional arguments: 'age' and 'grade'

1.2.1 namedtuple的不足

對(duì)于一些字段比較少的數(shù)據(jù)結(jié)構(gòu), namedtuple是一個(gè)非常好的解決方案.

但面對(duì)一些復(fù)雜的數(shù)據(jù)的時(shí)候, 需要更多的功能時(shí), namedtuple就無(wú)法滿足了.

In [11]: bryant = Player('Kobe Bryant', 24, 'PG', 22, 'S')
In [12]: bryant.age=23
---------------------------------------------------------------------------
AttributeError: can't set attribute

劣勢(shì):

① 數(shù)據(jù)無(wú)法修改

② 無(wú)法自定義數(shù)據(jù)比較,  沒(méi)有默認(rèn)值, 沒(méi)有函數(shù)支持.

1.3 自定義類 Class

為了支持?jǐn)?shù)據(jù)修改, 默認(rèn)值, 比較等功能. 更加好一些的方法是, 使用自定義類來(lái)實(shí)現(xiàn)數(shù)據(jù)類.

一個(gè)最簡(jiǎn)單的數(shù)據(jù)類代碼如下:

In [13]: class Player:
    ...:     def __init__(self, name, number, position, age, grade):
    ...:         self.name = name
    ...:         self.number = number
    ...:         self.position = position
    ...:         self.age = age
    ...:         self.grade = grade
 
In [14]: bryant = Player(name='Kobe Bryant', number=24, position='PG', age=22, grade='S')
In [15]: jordan = Player('Micheal Jordan', 23, 'PG', 29, 'S+')

可以使用位置參數(shù)或者鍵值參數(shù)創(chuàng)建對(duì)象

In [16]: bryant.position='SF'
In [17]: bryant.position
Out[17]: 'SF'

可以看到, 數(shù)據(jù)類可以支持對(duì)屬性的修改,

In [18]: bryant
Out[18]: <__main__.Player at 0x29446d401c8>

問(wèn)題①:目前的實(shí)現(xiàn) 對(duì)于對(duì)象的描述不太友好,

 
In [19]: jordan > bryant
---------------------------------------------------------------------------
TypeError: '>' not supported between instances of 'Player' and 'Player'

問(wèn)題②:數(shù)據(jù)還不支持比較. 

為了解決上面兩個(gè)問(wèn)題,可以通過(guò)實(shí)現(xiàn) __repr__ 方法來(lái)自定義描述, 實(shí)現(xiàn) __gt__ 方法來(lái)支持比較的功能.

更新代碼如下:

In [20]: class Player:
    ...:     def __init__(self, name, number, position, age, grade):
    ...:         self.name = name
    ...:         self.number = number
    ...:         self.position = position
    ...:         self.age = age
    ...:         self.grade = grade
    ...:     def __repr__(self):
    ...:         return f'Player: \n {self.name}\t #{self.number}\t @{self.position}\t <{self.grade}>'
    ...:     def __eq__(self, other):
    ...:         return self.age == other.age
    ...:     def __gt__(self, other):
    ...:         return self.age > other.age
    ...:     def swing(self, pos):
    ...:         self.position = pos
 
In [21]: jordan = Player('Micheal Jordan', 23, 'PG', 29, 'S+')
In [22]: bryant = Player('Kobe Bryant', 24, 'PG', 22, 'S')
 
In [23]: jordan
Out[23]:
Player:
 Micheal Jordan  #23     @PG     <S+>
 
In [24]: jordan > bryant
Out[24]: True
 
In [25]: jordan.swing('SF')
In [26]: jordan
Out[26]:
Player:
 Micheal Jordan  #23     @SF     <S+>

可以看到數(shù)據(jù)對(duì)象有了更直觀的描述, 支持了對(duì)比 (若要支持 >= 的對(duì)比, 還需要自定義 __ge__方法). 還可以自定義方法swing來(lái)改變球員打的位置.

劣勢(shì):

① __init__方法中重復(fù)代碼 (示例中每個(gè)屬性都需要寫3遍)

② 需要自己實(shí)現(xiàn)__repr__方法, 和比較方法__eq__, __gt__等

1.4 ??數(shù)據(jù)類 dataclass

主角出場(chǎng)了, 數(shù)據(jù)類是Python3.7 開始引入的一個(gè)新功能, 數(shù)據(jù)類提供了開箱即用的方法來(lái)創(chuàng)建自定義數(shù)據(jù), 可以直接實(shí)例化、打印和比較數(shù)據(jù)類實(shí)例.

In [1]: from dataclasses import dataclass
 
In [2]: @dataclass
   ...: class Player:
   ...:     name: str
   ...:     number: int
   ...:     position: str
   ...:     age: int
   ...:     grade: str
 
In [3]: james = Player('Lebron James', 23, 'SF', 25, 'S')
In [4]: james
Out[4]: Player(name='Lebron James', number=23, position='SF', age=25, grade='S')

2. dataclass 的使用

2.1 類型提示和默認(rèn)值

dataclass 可以認(rèn)為是提供了一個(gè)簡(jiǎn)寫__init__方法的語(yǔ)法糖. 

類型注釋是必填項(xiàng) (不限制數(shù)據(jù)類型時(shí), 添加typing.Any為類型注釋), 默認(rèn)值的傳遞方式和__init__方法的參數(shù)格式一致. 

In [1]: from dataclasses import dataclass
In [2]: from typing import Any
 
In [3]: @dataclass
   ...: class Data:
   ...:     name: Any
   ...:     value: Any = 42

2.2 數(shù)據(jù)嵌套

數(shù)據(jù)類可以嵌套為其他數(shù)據(jù)類的字段,  可以簡(jiǎn)單創(chuàng)建一個(gè)有2個(gè)隊(duì)員的球隊(duì).lal包含兩名球員 james和davis

In [1]: from dataclasses import dataclass
In [2]: from typing import List
 
In [3]: @dataclass
   ...: class Player:
   ...:     name: str
   ...:     number: int
   ...:     position: str
   ...:     age: int
   ...:     grade: str
 
In [4]: @dataclass
   ...: class Team:
   ...:     name: str
   ...:     players: List[Player]
 
In [5]: james = Player('Lebron James', 23, 'SF', 25, 'S')
In [6]: davis = Player('Anthony Davis', 3, 'PF', 21, 'S-')
 
In [7]: lal = Team('Los Angeles Lakers', [james, davis])
In [8]: lal
Out[8]: Team(name='Los Angeles Lakers', players=[Player(name='Lebron James', number=23, position='SF', age=25, grade='S'), Player(name='Anthony Davis', number=3, position='PF', age=21, grade='S-')])

2.3 dataclasses中的field

當(dāng)我們嘗試使用可變的數(shù)據(jù)類型, 給數(shù)據(jù)類中做默認(rèn)值時(shí), 觸發(fā)了python中的大坑之一 使用可變默認(rèn)參數(shù), 導(dǎo)致多個(gè)實(shí)例公用一個(gè)數(shù)據(jù)從而引發(fā)bug. 

dataclass 默認(rèn)阻止使用可變數(shù)據(jù)做默認(rèn)值

In [9]: @dataclass
   ...: class Team:
   ...:     name: str
   ...:     players: List[Player] = [james]
---------------------------------------------------------------------------
ValueError: mutable default <class 'list'> for field players is not allowed: use default_factory

就像錯(cuò)誤提示中的, 處理此種場(chǎng)景時(shí), 需要使用 field 中的 default_factory .

In [10]: from dataclasses import field
 
In [11]: @dataclass
    ...: class Team:
    ...:     name: str
    ...:     players: List[Player] = field(default_factory=lambda :[james])
 
In [12]: nyk = Team('New York Knicks')
In [13]: nyk
Out[13]: Team(name='New York Knicks', players=[Player(name='Lebron James', number=23, position='SF', age=25, grade='S')])
field 支持的參數(shù)
參數(shù)描述默認(rèn)值
default字段的默認(rèn)值
default_factory返回字段初始值的函數(shù)
init是否在.__init__()方法中使用字段True
repr是否在.__repr__()方法中使用字段True
compare是否在比較對(duì)象時(shí), 包括該字段True
hash計(jì)算hash時(shí), 是否包括字段True
metadata包含字段信息的映射

2.4 不可變數(shù)據(jù)類

要使數(shù)據(jù)類不可變,需要在創(chuàng)建類時(shí)設(shè)置frozen=True。

In [1]: from dataclasses import dataclass
In [2]: from typing import Any
 
In [3]: @dataclass(frozen=True)
   ...: class Data:
   ...:     name: Any
   ...:     value: Any = 42
 
In [4]: data = Data('myname', 99)
In [4]: data.name = 'other'
---------------------------------------------------------------------------
FrozenInstanceError: cannot assign to field 'name'
 

總結(jié)

dataclass 提供一個(gè)簡(jiǎn)便的方式創(chuàng)建數(shù)據(jù)類, 默認(rèn)實(shí)現(xiàn)__init__(),  __repr__(),  __eq__()方法.

dataclass支持?jǐn)?shù)據(jù)類型的嵌套

支持將數(shù)據(jù)設(shè)置為不可變

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • python實(shí)現(xiàn)截取屏幕保存文件,刪除N天前截圖的例子

    python實(shí)現(xiàn)截取屏幕保存文件,刪除N天前截圖的例子

    今天小編就為大家分享一篇python實(shí)現(xiàn)截取屏幕保存文件,刪除N天前截圖的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-08-08
  • 基于PyQT5制作英雄聯(lián)盟全皮膚下載器

    基于PyQT5制作英雄聯(lián)盟全皮膚下載器

    這篇文章主要介紹了基于PyQt5制作的簡(jiǎn)易英雄聯(lián)盟全皮膚下載器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起動(dòng)手嘗試一下
    2022-02-02
  • anaconda中更改python版本的方法步驟

    anaconda中更改python版本的方法步驟

    這篇文章主要介紹了anaconda中更改python版本的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Python使用watchfiles實(shí)現(xiàn)監(jiān)控目錄變更

    Python使用watchfiles實(shí)現(xiàn)監(jiān)控目錄變更

    在工作中難免會(huì)碰到這樣的需求,監(jiān)控指定目錄,下面小編就來(lái)和大家介紹一下如何利用watchfiles 模塊實(shí)現(xiàn)監(jiān)控目錄的變更,感興趣的可以了解下
    2023-09-09
  • 使用Python簡(jiǎn)單的實(shí)現(xiàn)樹莓派的WEB控制

    使用Python簡(jiǎn)單的實(shí)現(xiàn)樹莓派的WEB控制

    這篇文章主要介紹了使用Python簡(jiǎn)單的實(shí)現(xiàn)樹莓派的WEB控制的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • Python使用try except處理程序異常的三種常用方法分析

    Python使用try except處理程序異常的三種常用方法分析

    這篇文章主要介紹了Python使用try except處理程序異常的三種常用方法,結(jié)合實(shí)例形式分析了Python基于try except語(yǔ)句針對(duì)異常的捕獲、查看、回溯等相關(guān)操作技巧,需要的朋友可以參考下
    2018-09-09
  • 使用Python在Excel中插入、修改、提取和刪除超鏈接

    使用Python在Excel中插入、修改、提取和刪除超鏈接

    超鏈接是Excel中的常用功能,通過(guò)點(diǎn)擊超鏈接可以快速跳轉(zhuǎn)到外部網(wǎng)站、本地文件或工作表中的特定單元格,有效提升數(shù)據(jù)訪問(wèn)的效率和用戶體驗(yàn),這篇博客將詳細(xì)介紹如何使用Python在Excel中插入、修改、提取和刪除超鏈接,需要的朋友可以參考下
    2025-02-02
  • python刪除本地夾里重復(fù)文件的方法

    python刪除本地夾里重復(fù)文件的方法

    這篇文章主要為大家詳細(xì)介紹了python刪除本地夾里重復(fù)文件的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • django創(chuàng)建簡(jiǎn)單的頁(yè)面響應(yīng)實(shí)例教程

    django創(chuàng)建簡(jiǎn)單的頁(yè)面響應(yīng)實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于django如何創(chuàng)建簡(jiǎn)單的頁(yè)面響應(yīng)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用django具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • caffe的python接口deploy生成caffemodel分類新的圖片

    caffe的python接口deploy生成caffemodel分類新的圖片

    這篇文章主要為大家介紹了caffe的python接口生成deploy文件學(xué)習(xí)以及用訓(xùn)練好的模型(caffemodel)來(lái)分類新的圖片示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06

最新評(píng)論