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

?python中的元類metaclass詳情

 更新時(shí)間:2022年05月30日 17:04:15   作者:??zidea????  
這篇文章主要介紹了python中的metaclass詳情,在python中的metaclass就是幫助developer實(shí)現(xiàn)元編程,更多詳細(xì)內(nèi)容需要的小伙伴可以參考一下

動(dòng)機(jī)

python語(yǔ)言因?yàn)楣ぷ髌蛴?AI ,所以對(duì)于這門(mén)語(yǔ)言還停留在表面,對(duì)于 python 深層并沒(méi)有接觸到。

今天來(lái)聊一聊元類(metaclass) ,想必大多數(shù)人都或多或少聽(tīng)過(guò)元編程這個(gè)詞,但是對(duì)于元編程是什么以及如何應(yīng)用元編程熟悉應(yīng)該不多,在 python 中的 metaclass 就是幫助 developer 實(shí)現(xiàn)元編程,因此產(chǎn)生一個(gè)想法

最近時(shí)間還算寬裕,所以想要文章認(rèn)真弄一弄

從一個(gè)問(wèn)題引出 MetaClass

在 python 語(yǔ)言中,并沒(méi)有函數(shù)重載,我們下面通過(guò)一個(gè)具體例子來(lái)說(shuō)明。

class A():
    def f(self, x:int):
        print('A.f int overload',self,x)
    def f(self,x:str):
        print('A.f str overload',self,x)
    def f(self,x,y):
        print('A.f two arg overload',self,x,y)
if __name__ == "__main__":
    a = A()
    a.f(1)

當(dāng)執(zhí)行上面代碼我們會(huì)得到一個(gè)錯(cuò)誤信息,實(shí)例化 A 類后,調(diào)用實(shí)例的 f 方法,因?yàn)樵?python 語(yǔ)言中沒(méi)有重裝方法,所以 def f(self,x:str) 會(huì)覆蓋之前的 def f(self, x:int), 而 def f(self,x,y) 方法會(huì)覆蓋于 def f(self,x:str) 方法,所以當(dāng)通過(guò)傳入 1 一個(gè)參數(shù),不會(huì)調(diào)用 def f(self,x:int) 而是調(diào)用 def f(self,x,y) 方法。

TypeError: f() missing 1 required positional argument: 'y'

那么什么是正確的姿勢(shì)解決這個(gè)問(wèn)題呢? 這里先不急于給出答案,當(dāng)我們介紹完 metaclass 后,答案就自然浮出水面。

Metaclass 編程

想要了解 Metaclass 也就是元類,meta 在英文中超越的意思,也就是 Metaclass 是高級(jí)于 class,用于創(chuàng)建 class 的 class。有的時(shí)候我們需要控制類創(chuàng)建過(guò)程,通常創(chuàng)建類工作是由 type 完成的,因?yàn)?type 直接設(shè)計(jì)到 c,我們希望在 type 創(chuàng)建類過(guò)程插入一些自定義的東西,所以引入了 Metaclass 讓某一個(gè)類創(chuàng)建工作不再由 type 來(lái)實(shí)現(xiàn),而是由指定 class 來(lái)實(shí)現(xiàn)

在 python 中,我們可以通過(guò) class 來(lái)實(shí)例化對(duì)象,不過(guò)這里要說(shuō)在 python 中 class 其實(shí)也是對(duì)象。既然 class 也是對(duì)象,那么 class 的類型又是什么呢

class A:
    a = 1
    b = "hello"
    def f(self):
        return 12
def main():
    print(f'{type(2)=}')
    print(f'{type("hello")=}')
    print(f'{type([])=}')
    print(f'{type(A())=}')
if __name__ == "__main__":
    main()

輸出一下 2、hello 、空數(shù)組和 A 類實(shí)例的類型,結(jié)果發(fā)現(xiàn)他們類別分別為 int、str、list 和 A 類別。其實(shí)他們也是對(duì)象,既然是對(duì)象,那么就會(huì)有一個(gè) class 用于創(chuàng)建這個(gè)類別。

type(2)=<class 'int'>
type("hello")=<class 'str'>
type([])=<class 'list'>
type(A())=<class '__main__.A'>

接下來(lái)我們就看一下這些 class(int,str,list) 那么這些對(duì)象又是什么類別呢

class A:
    a = 1
    b = "hello"
    def f(self):
        return 12
if __name__ == "__main__":
    print(f'{type(int)=}')
    print(f'{type(str)=}')
    print(f'{type(list)=}')
    print(f'{type(A)=}')
type(int)=<class 'type'>
type(str)=<class 'type'>
type(list)=<class 'type'>
type(A)=<class 'type'>

不難看出多有 class 的類型都是 type ,例如數(shù)字 2 的 int 的一個(gè)實(shí)例,而 int 又是 type 的一個(gè)實(shí)例。

如果大家從類似 java 這些語(yǔ)言開(kāi)始,然后再去學(xué)習(xí) python 可能會(huì)有這樣疑問(wèn),在 python 中 type 和 class 有什么區(qū)別,他們不都是類型嗎? 其實(shí)答案就是這兩者在 python3 中并沒(méi)有區(qū)別,可以將他們看做一個(gè)東西。

def main():
    x = int()
    print(f'{x=}')
    B = type('B',(),{})
    print(f'{B=}')
if __name__  == "__main__":
    main()

不過(guò)如果進(jìn)一步深入研究,兩種 class 和 type 在字面上,是不同兩樣?xùn)|西,class 作為關(guān)鍵字來(lái)定義類型時(shí),是調(diào)用其構(gòu)造器來(lái)做了一些初始化的工作。

def main():
    x = int()
    print(f'{x=}')
    B = type('B',(),{})
    print(f'{B=}')
if __name__  == "__main__":
    main()

我們可以這樣來(lái)定義一個(gè)類型

x=0
B=<class '__main__.B'>

可以用 class 方式來(lái)定義一個(gè)類 A,然后我們?cè)谟?type 方式來(lái)創(chuàng)建一個(gè)類,type 接受 3 個(gè)參數(shù)分別是類的名稱,這里接受的字符串類型的名稱、以及該類的基類,是組元的形式,接下來(lái)是就是一個(gè)屬性,屬性是字典形式數(shù)據(jù),鍵是屬性名稱,值是屬性值。

class A:
    a = 2
    b = 'hello'

    def f(self):
        return 12

下面我們用 make_A 來(lái)創(chuàng)建一個(gè)類, 這里使用 type 來(lái)定義一個(gè)類

def make_A():
    name = 'A'
    bases = ()
    a = 2
    b = 'hello'

    def f(self):
        return 12
    namespace = {'a':a,'b':b,'f':f}
    A = type(name,bases,namespace)
    return

通過(guò) type 創(chuàng)建類時(shí)候需要傳入類名稱 A 然后 base 是一個(gè)要?jiǎng)?chuàng)建類 A 的基類,namescpace 是類屬性,是 dict 形式,鍵是屬性名稱,而值是屬性值。

def make_A_more_accurate():
    name = 'A'
    bases = ()
    namespace = type.__prepare__(name,bases)
    body = (
"""
a = 1
b = 'hello'

def f(self):
    return 12
"""
    )
    exec(body,globals(),namespace)
    A = type(name,bases,namespace)
    return A

metaclass 是繼承于 type,那么 metaclass 的工作也是用于創(chuàng)建 class,我們可以在 metaclass 中做一些自定義的事情,

這里可能比較難理解是 __prepare__ 上網(wǎng)找到關(guān)于 __prepare__ 解釋,暫時(shí)說(shuō)一下自己認(rèn)識(shí),可能有點(diǎn)淺,感覺(jué)就是為類創(chuàng)建了一個(gè)局部的作用域。

namespace = type.__prepare__(name,bases)
print(namespace)

type.__prepare__ 應(yīng)該是返回一個(gè)局部命名空間,

exec(body,globals(),namespace)

class Tut:
    ...
tut = Tut()
print(f'{type(tut)=}')
print(f'{type(Tut)=}')

上面例子定義一個(gè)類,然后實(shí)例化 Tut 類得到對(duì)象 tut,接下來(lái)分別輸出 tut 和 Tut 類型

type(tut)=<class '__main__.Tut'>
type(Tut)=<class 'type'>

不難看出 tut 是 Tut 的實(shí)例,而 Tut 是 type 的對(duì)象

class TutMetaClass(type):
    ...
class Tut(metaclass=TutMetaClass):
    ...

然后我們定義一個(gè) TutMetaClass 繼承于 type,然后將 Tut 類的 metaclass 指向 TutMetaClass ,然后 tut 類型為 Tut,而 Tut 類型為 TutMetaClass 類型

type(tut)=<class '__main__.Tut'>
type(Tut)=<class '__main__.TutMetaClass'>

到此這篇關(guān)于 python 中的 元類metaclass詳情的文章就介紹到這了,更多相關(guān) python metaclass 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python?matplotlib.pyplot.hist()繪制直方圖的方法實(shí)例

    Python?matplotlib.pyplot.hist()繪制直方圖的方法實(shí)例

    直方圖(Histogram)又稱質(zhì)量分布圖,是一種統(tǒng)計(jì)報(bào)告圖,由一系列高度不等的縱向條紋或線段表示數(shù)據(jù)分布的情況,一般用橫軸表示數(shù)據(jù)類型,縱軸表示分布情況,下面這篇文章主要給大家介紹了關(guān)于Python?matplotlib.pyplot.hist()繪制直方圖的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • Python接口自動(dòng)化淺析如何處理接口依賴

    Python接口自動(dòng)化淺析如何處理接口依賴

    本文主要介紹如何提取token、將token作為類屬性全局調(diào)用及充值接口如何攜帶token進(jìn)行請(qǐng)求,其他接口調(diào)用的前提條件是當(dāng)前用戶必須是登錄狀態(tài),如何處理接口依賴
    2021-08-08
  • python 實(shí)現(xiàn)二維字典的鍵值合并等函數(shù)

    python 實(shí)現(xiàn)二維字典的鍵值合并等函數(shù)

    今天小編就為大家分享一篇python 實(shí)現(xiàn)二維字典的鍵值合并等函數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • Python3讀寫(xiě)ini配置文件的示例

    Python3讀寫(xiě)ini配置文件的示例

    這篇文章主要介紹了Python3讀寫(xiě)ini配置文件的示例,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-11-11
  • PyQt5每天必學(xué)之進(jìn)度條效果

    PyQt5每天必學(xué)之進(jìn)度條效果

    這篇文章主要為大家詳細(xì)介紹了PyQt5實(shí)現(xiàn)進(jìn)度條效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Python 數(shù)據(jù)化運(yùn)營(yíng)之KMeans聚類分析總結(jié)

    Python 數(shù)據(jù)化運(yùn)營(yíng)之KMeans聚類分析總結(jié)

    這篇文章主要介紹了Python 數(shù)據(jù)化運(yùn)營(yíng)KMeans聚類相關(guān)的一些總結(jié),感興趣的話一起來(lái)閱讀下文吧
    2021-08-08
  • Python Flask前后端Ajax交互的方法示例

    Python Flask前后端Ajax交互的方法示例

    這篇文章主要介紹了Python Flask前后端Ajax交互的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • 為什么入門(mén)大數(shù)據(jù)選擇Python而不是Java?

    為什么入門(mén)大數(shù)據(jù)選擇Python而不是Java?

    為什么入門(mén)大數(shù)據(jù)選擇Python而不是Java?這篇文章就來(lái)談?wù)剬W(xué)習(xí)大數(shù)據(jù)入門(mén)語(yǔ)言的選擇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Python實(shí)現(xiàn)以時(shí)間換空間的緩存替換算法

    Python實(shí)現(xiàn)以時(shí)間換空間的緩存替換算法

    緩存是指可以進(jìn)行高速數(shù)據(jù)交換的存儲(chǔ)器,它先于內(nèi)存與CPU交換數(shù)據(jù),因此速度很快。緩存就是把一些數(shù)據(jù)暫時(shí)存放于某些地方,可能是內(nèi)存,也有可能硬盤(pán)。下面給大家介紹Python實(shí)現(xiàn)以時(shí)間換空間的緩存替換算法,需要的朋友參考下
    2016-02-02
  • pycharm日志總是彈出“無(wú)法運(yùn)行Git,未安裝Git”的問(wèn)題

    pycharm日志總是彈出“無(wú)法運(yùn)行Git,未安裝Git”的問(wèn)題

    這篇文章主要介紹了pycharm日志總是彈出“無(wú)法運(yùn)行Git,未安裝Git”的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06

最新評(píng)論