最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解Python?@dataclass的內(nèi)部原理

 更新時(shí)間:2025年01月06日 09:53:16   作者:wang_yb  
文章介紹了Python中dataclass的實(shí)現(xiàn)原理,通過自定義裝飾器實(shí)現(xiàn)了__init__和__repr__方法,并解釋了__annotations__屬性和exec函數(shù)在其中的作用,感興趣的朋友跟隨小編一起看看吧

之前寫過一篇介紹Pythondataclass的文章:《掌握python的dataclass,讓你的代碼更簡(jiǎn)潔優(yōu)雅》。

那篇側(cè)重于介紹dataclass的使用,今天想探索一下這個(gè)有趣的特性是如何實(shí)現(xiàn)的。

表面上看,dataclass就是一個(gè)普通的裝飾器,但是它又在class上實(shí)現(xiàn)了很多神奇的功能,

為我們?cè)?code>Python中定義和使用class帶來了極大的便利。

如果你也好奇它在幕后是如何工作的,本篇我們就一同揭開Pythondataclass的神秘面紗,

深入探究一下其內(nèi)部原理。

1. dataclass簡(jiǎn)介

dataclass為我們提供了一種簡(jiǎn)潔而高效的方式來定義類,特別是那些主要用于存儲(chǔ)數(shù)據(jù)的類。

它能自動(dòng)為我們生成一些常用的方法,如__init__、__repr__等,大大減少了樣板代碼的編寫。

例如,我在量化中經(jīng)常用的一個(gè)K線數(shù)據(jù),用dataclass來定義的話,如下所示:

from dataclasses import dataclass
from datetime import datetime
@dataclass
class KLine:
    name: str = "BTC"
    open_price: float = 0.0
    close_price: float = 0.0
    high_price: float = 0.0
    low_price: float = 0.0
    begin_time: datetime = datetime.now()
if __name__ == "__main__":
    kl = KLine()
    print(kl)

這樣,我們無需手動(dòng)編寫__init__方法來初始化對(duì)象,就可以輕松創(chuàng)建KLine類的實(shí)例,

并且直接打印對(duì)象也可以得到清晰,易于閱讀的輸出。

$  python.exe .\kline.py
KLine(name='BTC', open_price=0.0, close_price=0.0, 
high_price=0.0, low_price=0.0, 
begin_time=datetime.datetime(2025, 1, 2, 17, 45, 53, 44463))

但這背后究竟發(fā)生了什么呢?

2. 核心概念

dataclassPython3.7版本開始,已經(jīng)加入到標(biāo)準(zhǔn)庫中了。

代碼就在Python安裝目錄中的Lib/dataclasses.py文件中。

實(shí)現(xiàn)這個(gè)裝飾器功能的核心有兩個(gè):__annotations__屬性和exec函數(shù)。

2.1. __annotations__屬性

__annotations__是 Python 中一個(gè)隱藏的寶藏,它以字典的形式存儲(chǔ)著變量、屬性以及函數(shù)參數(shù)或返回值的類型提示。

對(duì)于dataclass來說,它就像是一張地圖,裝飾器通過它來找到用戶定義的字段。

比如,在上面的KLine類中,__annotations__會(huì)返回字段的相關(guān)信息。

這使得dataclass裝飾器能夠清楚地知道類中包含哪些字段以及它們的類型,為后續(xù)的操作提供了關(guān)鍵信息。

if __name__ == "__main__":
    print(KLine.__annotations__)
# 運(yùn)行結(jié)果:
{'name': <class 'str'>, 'open_price': <class 'float'>, 
'close_price': <class 'float'>, 'high_price': <class 'float'>, 
'low_price': <class 'float'>, 'begin_time': <class 'datetime.datetime'>}

2.2. exec 函數(shù)

exec函數(shù)堪稱dataclass實(shí)現(xiàn)的魔法棒,它能夠?qū)⒆址问降拇a轉(zhuǎn)換為 Python 對(duì)象。

dataclass的世界里,它被用來創(chuàng)建各種必要的方法。

我們可以通過構(gòu)建函數(shù)定義的字符串,然后使用exec將其轉(zhuǎn)化為真正的函數(shù),并添加到類中。

這就是dataclass裝飾器能夠自動(dòng)生成__init__、__repr__等方法的秘密所在。

下面的代碼通過exec,將一個(gè)字符串代碼轉(zhuǎn)換成一個(gè)真正可使用的函數(shù)。

# 定義一個(gè)存儲(chǔ)代碼的字符串
code_string = """
def greet(name):
    print(f"Hello, {name}!")
"""
# 使用 exec 函數(shù)執(zhí)行代碼字符串
exec(code_string)
# 調(diào)用通過 exec 生成的函數(shù)
greet("Alice")

3. 自定義dataclass裝飾器

掌握了上面的核心概念,我們就可以開始嘗試實(shí)現(xiàn)自己的dataclass裝飾器。

當(dāng)然,這里只是簡(jiǎn)單實(shí)現(xiàn)個(gè)雛形,目的是為了了解Python標(biāo)準(zhǔn)庫中dataclass的原理。

下面主要實(shí)現(xiàn)兩個(gè)功能__init____repr__

通過這兩個(gè)功能來理解dataclass的實(shí)現(xiàn)原理。

3.1. 定義架構(gòu)

我們首先定義一個(gè)dataclass裝飾器,它的結(jié)構(gòu)如下:

def dataclass(cls=None, init=True, repr=True):
    def wrap(cls):
        # 這里將對(duì)類進(jìn)行修改
        return cls
    if cls is None:
        return wrap
    return wrap(cls)

接下來,我們?cè)谶@個(gè)裝飾器中實(shí)現(xiàn)__init____repr__

3.2. 初始化:init

當(dāng)init參數(shù)為True時(shí),我們?yōu)轭愄砑?code>__init__方法。

通過_init_fn函數(shù)來實(shí)現(xiàn),它會(huì)根據(jù)類的字段生成__init__方法的函數(shù)定義字符串,然后使用_create_fn函數(shù)將其轉(zhuǎn)換為真正的方法并添加到類中。

def _create_fn(cls, name, fn):
    ns = {}
    exec(fn, None, ns)
    method = ns[name]
    setattr(cls, name, method)
def _init_fn(cls, fields):
    args = ", ".join(fields)
    lines = [f"self.{field} = {field}" for field in fields]
    body = "\n".join(f"  {line}" for line in lines)
    txt = f"def __init__(self, {args}):\n{body}"
    _create_fn(cls, "__init__", txt)

3.3. 美化輸出:repr

__repr__方法讓我們能夠以一種清晰易讀的方式打印出類的實(shí)例。

為了實(shí)現(xiàn)這個(gè)功能,我們創(chuàng)建_repr_fn函數(shù),它生成__repr__方法的定義字符串。

這個(gè)方法會(huì)獲取實(shí)例的__dict__屬性中的所有變量,并使用 f-string 進(jìn)行格式化輸出。

def _repr_fn(cls, fields):
    txt = (
        "def __repr__(self):\n"
        "    fields = [f'{key}={val!r}' for key, val in self.__dict__.items()]\n"
        "    return f'{self.__class__.__name__}({\"\\n \".join(fields)})'"
    )
    _create_fn(cls, "__repr__", txt)

3.4. 合在一起

最終的代碼如下,代碼中使用的是自己的dataclass裝飾器,而不是標(biāo)準(zhǔn)庫中的dataclass

from datetime import datetime
def dataclass(cls=None, init=True, repr=True):
    def wrap(cls):
        fields = cls.__annotations__.keys()
        if init:
            _init_fn(cls, fields)
        if repr:
            _repr_fn(cls, fields)
        return cls
    if cls is None:  # 如果裝飾器帶參數(shù)
        return wrap
    return wrap(cls)
def _create_fn(cls, name, fn):
    ns = {}
    exec(fn, None, ns)
    method = ns[name]
    setattr(cls, name, method)
def _init_fn(cls, fields):
    args = ", ".join(fields)
    lines = [f"self.{field} = {field}" for field in fields]
    body = "\n".join(f"  {line}" for line in lines)
    txt = f"def __init__(self, {args}):\n{body}"
    _create_fn(cls, "__init__", txt)
def _repr_fn(cls, fields):
    txt = (
        "def __repr__(self):\n"
        "    fields = [f'{key}={val!r}' for key, val in self.__dict__.items()]\n"
        "    return f'{self.__class__.__name__}({\"\\n \".join(fields)})'"
    )
    _create_fn(cls, "__repr__", txt)
@dataclass
class KLine:
    name: str = "BTC"
    open_price: float = 0.0
    close_price: float = 0.0
    high_price: float = 0.0
    low_price: float = 0.0
    begin_time: datetime = datetime.now()
if __name__ == "__main__":
    kl = KLine(
        name="ETH",
        open_price=1000.5,
        close_price=3200.5,
        high_price=3400,
        low_price=200,
        begin_time=datetime.now(),
    )
    print(kl)

運(yùn)行的效果如下:

可以看出,我們自己實(shí)現(xiàn)的dataclass裝飾器也可以實(shí)現(xiàn)類的初始化和美化輸出,這里輸出時(shí)每個(gè)屬性占一行。

4. 總結(jié)

通過自定義dataclass裝飾器的構(gòu)建過程,我們深入了解了 Python 中dataclass的內(nèi)部原理。

利用__annotations__獲取字段信息,借助exec創(chuàng)建各種方法,從而實(shí)現(xiàn)簡(jiǎn)潔高效的dataclass定義。

不過,實(shí)際的 Python標(biāo)準(zhǔn)庫中的dataclass還有更多的功能和優(yōu)化,了解了其原理之后,可以參考它的源碼再進(jìn)一步學(xué)習(xí)。

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

相關(guān)文章

  • python 如何通過執(zhí)行腳本安裝庫或卸載庫

    python 如何通過執(zhí)行腳本安裝庫或卸載庫

    通過執(zhí)行Python腳本,用戶可以輕松地安裝或卸載所需的庫,本文介紹了該過程的具體步驟,包括如何編寫用于安裝或卸載庫的腳本,無論是需要添加新功能還是清理環(huán)境,通過這種方式,開發(fā)者都能有效管理其工作環(huán)境中的庫
    2024-11-11
  • python防止程序超時(shí)的實(shí)現(xiàn)示例

    python防止程序超時(shí)的實(shí)現(xiàn)示例

    因?yàn)槟硞€(gè)需求,需要在程序運(yùn)行的時(shí)候防止超時(shí),本文主要介紹了python防止程序超時(shí)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-08-08
  • OpenCV半小時(shí)掌握基本操作之邊界填充

    OpenCV半小時(shí)掌握基本操作之邊界填充

    這篇文章主要介紹了OpenCV基本操作之邊界填充,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • Python迭代器的實(shí)現(xiàn)原理

    Python迭代器的實(shí)現(xiàn)原理

    這篇文章主要介紹了Python迭代器的實(shí)現(xiàn)原理,文章基于python的相關(guān)資料展開對(duì)Python迭代器的詳細(xì)介紹,需要的小伙伴可以參考一下
    2022-05-05
  • python docx如何修改word表格內(nèi)容

    python docx如何修改word表格內(nèi)容

    使用Python-docx庫,可以方便地修改Word文檔中的表格內(nèi)容,首先需要安裝python-docx庫,然后使用該庫打開Word文檔,遍歷文檔中的表格并修改指定單元格內(nèi)容,最后另存為新文檔
    2024-09-09
  • Python無權(quán)點(diǎn)文件轉(zhuǎn)化成鄰接矩陣方式

    Python無權(quán)點(diǎn)文件轉(zhuǎn)化成鄰接矩陣方式

    這篇文章主要介紹了Python無權(quán)點(diǎn)文件轉(zhuǎn)化成鄰接矩陣方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • python3.7實(shí)現(xiàn)云之訊、聚合短信平臺(tái)的短信發(fā)送功能

    python3.7實(shí)現(xiàn)云之訊、聚合短信平臺(tái)的短信發(fā)送功能

    這篇文章主要介紹了python3.7實(shí)現(xiàn)云之訊、聚合短信平臺(tái)的短信發(fā)送功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • python多線程socket編程之多客戶端接入

    python多線程socket編程之多客戶端接入

    這篇文章主要為大家詳細(xì)介紹了python多線程socket編程之多客戶端接入,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • python 利用文件鎖單例執(zhí)行腳本的方法

    python 利用文件鎖單例執(zhí)行腳本的方法

    今天小編就為大家分享一篇python 利用文件鎖單例執(zhí)行腳本的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-02-02
  • 使用Python進(jìn)行接口測(cè)試的代碼演示

    使用Python進(jìn)行接口測(cè)試的代碼演示

    在軟件開發(fā)過程中,接口測(cè)試是一個(gè)至關(guān)重要的環(huán)節(jié),Python作為一種簡(jiǎn)潔、靈活且易于學(xué)習(xí)的編程語言,為接口測(cè)試提供了強(qiáng)大的支持,本文將介紹如何使用Python進(jìn)行接口測(cè)試,并通過代碼實(shí)例演示,需要的朋友可以參考下
    2025-05-05

最新評(píng)論

仲巴县| 昆山市| 平顺县| 沙坪坝区| 钟祥市| 昭苏县| 扬州市| 岳阳市| 渝北区| 河西区| 康保县| 霍城县| 石渠县| 德州市| 敦化市| 诸暨市| 肇源县| 贡山| 炉霍县| 长沙市| 高青县| 张家界市| 重庆市| 建宁县| 托克托县| 乃东县| 余干县| 珲春市| 宁强县| 汉川市| 子洲县| 如东县| 都江堰市| 巴彦县| 临夏市| 永丰县| 成安县| 九台市| 东兴市| 堆龙德庆县| 武强县|