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

Python Metaclass原理與實(shí)現(xiàn)過程詳細(xì)講解

 更新時(shí)間:2022年11月29日 09:38:36   作者:雕弓  
MetaClass元類,本質(zhì)也是一個(gè)類,但和普通類的用法不同,它可以對(duì)類內(nèi)部的定義(包括類屬性和類方法)進(jìn)行動(dòng)態(tài)的修改。可以這么說,使用元類的主要目的就是為了實(shí)現(xiàn)在創(chuàng)建類時(shí),能夠動(dòng)態(tài)地改變類中定義的屬性或者方法

前言

學(xué)習(xí)python時(shí),對(duì) meta class 并不陌生,django 的model, form定義中經(jīng)常會(huì)遇到class Meta 的代碼, 但 django中沒有介紹模型與表單中的 meta 屬性是怎么回事。 python的眾多教程,也很少有作者提到,或把meta class 講清楚,造成大家以為metaclass 很難理解。 今天我嘗試用實(shí)例代碼的方式,讓metaclass 更容易理解與使用。

class Person(models.Model):
    cname = models.CharField(max_length=30, verbose_name="姓名")
    user = models.ForeignKey(
        get_user_model(), null=True, on_delete=models.CASCADE)
    birth_date = models.DateField(verbose_name="出生日期")
    def __str__(self):
        return self.cname
    class Meta:
        verbose_name = "人員信息"
        db_table = "tbl_person"

Python與java 一樣,宣稱自己一切皆對(duì)象,且有過之而不及。python的數(shù)據(jù)類型是類對(duì)象,甚至函數(shù)本身也是對(duì)象。 Python object 是所有類型的基類,各種數(shù)據(jù)類型, 函數(shù), class 都是object 的派生類,因此,從object的概念上推理,存在某些 class ,其可以生成其它c(diǎn)lass, 這種 class 就稱為meta class., 也稱元類.

本文將討論meta class的定義,以及使用方式。 內(nèi)容共包含3個(gè)主題:

  • 用 type 定義類
  • 如何編寫 Metaclass
  • Metaclass 的實(shí)際應(yīng)用

Type 來定義類

1個(gè) class 也是1個(gè)object, 其包含若干屬性,以及一些方法。 type () 通常用來顯示 變量與函數(shù)的類型,但也可以用type 來創(chuàng)建 class. 下面我們來演示這一過程。

首先,先用標(biāo)準(zhǔn)的方式,class關(guān)鍵字來創(chuàng)建1個(gè) Food 類。

class Food(object):
    def __init__(self, food):
        self.food = food
    def get_food(self):
        return self.food
def main():
    myfood = Food(food='蛋炒飯')
    print(myfood.get_food())
main()

output

蛋炒飯

下面演示如何用 type來創(chuàng)建1個(gè)Food 類

def init(self, food):
    self.food = food
def get_food(self):
    return self.food
Food = type("Food", (object,),  {
    '__init__': init,
    'get_food': get_food,
})
myfood = Food(food="蛋炒飯")
print(myfood.get_food())

output:

蛋炒飯

要?jiǎng)?chuàng)建一個(gè)class對(duì)象,type()函數(shù)依次傳入3個(gè)參數(shù):

  • 第1個(gè)參數(shù)是string類型,class的名稱;
  • 第2個(gè)參數(shù)是1個(gè)tuple , (object, ) , 指定繼承的父類是 object,注意支持多重繼承,如果只有一個(gè)父類,后面是加個(gè) , 號(hào);
  • 第3個(gè)參數(shù)是 dictionary 類型, 指定 class的屬性與方法名稱,這里我們把函數(shù)init綁定到方法名__init__

通過type()函數(shù)創(chuàng)建的類和直接寫class是完全一樣的,因?yàn)镻ython解釋器遇到class定義時(shí),僅僅是掃描一下class定義的語法,然后調(diào)用type()函數(shù)創(chuàng)建出class

用 type來增加1個(gè)子類VegFood, 其父類為Food

def init(self, food):
    self.food = food
def get_food(self):
    return self.food
Food = type("Food", (object,),  {
    '__init__': init,
    'get_food': get_food,
})
def get_vegfood(self):
    return {'清炒菠菜', '干煸豆角'}
# 新建子類,父類為Food
VegFood = type("VegFood", (Food,), {
    "get_vegfood": get_vegfood,
})
veg = VegFood(food="蛋炒飯")
print(veg.get_food())
print(veg.get_vegfood())

output:

蛋炒飯
{'干煸豆角', '清炒菠菜'}

可以看到,子類 VegFood可以繼承 父類Food的方法get_food(),也可以使用子類的方法 get_vegfood()

編寫 meta class

metaclass,直譯為元類,繼承自type. 因此,如前一節(jié)的示例 ,metaclass 也可以用來創(chuàng)建類。

用metaclass后, 關(guān)于類的編程過程: 先定義metaclass,就可以創(chuàng)建類,最后創(chuàng)建實(shí)例。

所以,metaclass允許你創(chuàng)建類或者修改類。換句話說,你可以把類看成是metaclass創(chuàng)建出來的“實(shí)例”。

metaclass的定義過程,主要是實(shí)現(xiàn) __new__ 方法,有4個(gè)傳入?yún)?shù), 與 type創(chuàng)建類的參數(shù)相似

  • metaclass 自身
  • 類名
  • 父類( tuple 類型)
  • 類的屬性與方法字典

metaclass還可以實(shí)現(xiàn)1個(gè) __call__方法,在該類被調(diào)用時(shí)執(zhí)行此方法。

metacalss 示例 :

class MetaCls(type):
    """metaclass的示例"""
    def __new__(cls, clsname, superclasses, attributedict):
        print("clsname:", clsname)
        print("superclasses:", superclasses)
        print("attrdict:", attributedict)
        return super(MetaCls, cls).__new__(cls,
                                           clsname, superclasses, attributedict)
def demo(self):
    print("Info from demo method")
# generate a class, Example 
Example = MetaCls('Example', (object, ), {"demo": demo, })
Example.clsname = "ExampleClass"  # 修改 metaclass的屬性值 
print("class type:", type(Example))
myexample = Example()             # 新建1個(gè)Example的實(shí)例對(duì)象
print(myexample.clsname)          # 打印父類屬性值
myexample.demo()                  # 打印子類方法

output

clsname: Example
superclasses: (<class 'object'>,)
attrdict: {'demo': <function demo at 0x00000169DF2CC280>}
class type: <class '__main__.MetaCls'>
ExampleClass
Info from demo method

從上例 可以看到, Example類的生成方式,就是 MetaCls類的實(shí)例 化過程,example可以添加自己的方法,可以修改從父類繼承的屬性。

metaclass應(yīng)用

實(shí)際開發(fā)中遇到的metaclass是django中定義model, form時(shí),可以定義metaclass的屬性,其實(shí)就是django的ORM使用了 metaclass的編程方式,由于其實(shí)現(xiàn)較復(fù)雜,就不深入討論。

這里我們來看1個(gè)更簡單,而且非常實(shí)用的metaclass的例子: 用metaclass實(shí)現(xiàn)單例模式。

單例模式提供了這樣一個(gè)機(jī)制,即確保類有且只有一個(gè)特定類型的對(duì)象,并提供全局 訪問點(diǎn)。因此,單例模式通常用于下列情形,例如日志記錄或數(shù)據(jù)庫操作、打印機(jī)后臺(tái)處 理程序,以及其他程序—該程序運(yùn)行過程中只能生成一個(gè)實(shí)例,以避免對(duì)同一資源產(chǎn)生 相互沖突的請求。

class SingletonMeta(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(
                SingletonMeta, cls).__call__(*args, **kwargs)
        return cls._instances[cls]
class SingletonClass(metaclass=SingletonMeta):
    pass
s = SingletonClass()
print("Object created", s)
s1 = SingletonClass()
print("Object created", s1)

output :

Object created <__main__.SingletonClass object at 0x0000020CF1F20130>
Object created <__main__.SingletonClass object at 0x0000020CF1F20130>

可以看到,SingletonMeta用metaclass的方法定義了1個(gè)單例類, SingletonClass繼承自SingletonMeta, s 與 s1 雖然分別實(shí)例化,但內(nèi)存中的地址都指向同1個(gè)SingletonClass對(duì)象,這樣就實(shí)現(xiàn)了單例化。

而且metaclass實(shí)現(xiàn)單例模式,比 object方式實(shí)現(xiàn)的單例化有明顯的優(yōu)勢,任何類都可以通過繼承SingletonMeta實(shí)現(xiàn)單例模式, 是不是很酷.

到此這篇關(guān)于Python Metaclass原理與實(shí)現(xiàn)過程詳細(xì)講解的文章就介紹到這了,更多相關(guān)Python Metaclass內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何使用selenium和requests組合實(shí)現(xiàn)登錄頁面

    如何使用selenium和requests組合實(shí)現(xiàn)登錄頁面

    這篇文章主要介紹了如何使用selenium和requests組合實(shí)現(xiàn)登錄頁面,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 三種Matplotlib中動(dòng)態(tài)更新繪圖的方法總結(jié)

    三種Matplotlib中動(dòng)態(tài)更新繪圖的方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了如何隨著數(shù)據(jù)的變化動(dòng)態(tài)更新Matplotlib(Python的數(shù)據(jù)可視化庫)圖,文中介紹了常用的三種方法,希望對(duì)大家有所幫助
    2024-04-04
  • Python3 集合set入門基礎(chǔ)

    Python3 集合set入門基礎(chǔ)

    集合也也也也是python內(nèi)置的一種數(shù)據(jù)結(jié)構(gòu),它是一個(gè)無序且元素不重復(fù)的序列。這里有兩個(gè)關(guān)鍵詞一個(gè)是無序,這一點(diǎn)和字典是一樣的,另一個(gè)關(guān)鍵詞是元素不重復(fù),這一點(diǎn)和字典的key(鍵)是一樣的
    2020-02-02
  • Django的開發(fā)步驟原來是這樣的

    Django的開發(fā)步驟原來是這樣的

    這篇文章主要為大家詳細(xì)介紹了Django的開發(fā)步驟,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • Python封裝git命令的流程步驟

    Python封裝git命令的流程步驟

    在日常的 Android 項(xiàng)目開發(fā)中,一般只會(huì)使用到: git add, git commit, git push, git pull, git rebase, git merge, git diff等常規(guī)命令,但是使用 git 命令,還可以做一些特別的事情,下面將介紹使用 python 封裝 git 命令,需要的朋友可以參考下
    2024-01-01
  • python實(shí)現(xiàn)從本地?cái)z像頭和網(wǎng)絡(luò)攝像頭截取圖片功能

    python實(shí)現(xiàn)從本地?cái)z像頭和網(wǎng)絡(luò)攝像頭截取圖片功能

    這篇文章主要介紹了python實(shí)現(xiàn)從本地?cái)z像頭和網(wǎng)絡(luò)攝像頭截取圖片功能 ,文中給大家提到了python , opencv 打開網(wǎng)絡(luò)攝像頭讀取圖像的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2019-07-07
  • 講解Python中的遞歸函數(shù)

    講解Python中的遞歸函數(shù)

    這篇文章主要介紹了講解Python中的遞歸函數(shù),遞歸是學(xué)一門編程語言必須掌握的重要特性,需要的朋友可以參考下
    2015-04-04
  • py中的目錄與文件判別代碼

    py中的目錄與文件判別代碼

    python中的判別目錄和文件的腳本
    2008-07-07
  • pygame實(shí)現(xiàn)鍵盤的連續(xù)監(jiān)控

    pygame實(shí)現(xiàn)鍵盤的連續(xù)監(jiān)控

    這篇文章主要為大家詳細(xì)介紹了pygame實(shí)現(xiàn)鍵盤的連續(xù)監(jiān)控,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • Python實(shí)現(xiàn)希爾排序,歸并排序和桶排序的示例代碼

    Python實(shí)現(xiàn)希爾排序,歸并排序和桶排序的示例代碼

    希爾、歸并、快速排序算法可歸為同一類,它們的共同點(diǎn)都是建立在分治思想之上。把大問題分拆成小問題,解決所有小問題后,再合并每一個(gè)小問題的結(jié)果,最終得到對(duì)原始問題的解答。本文將介紹這三種算法的實(shí)現(xiàn)代碼,需要的可以參考一下
    2022-04-04

最新評(píng)論

泸水县| 阿拉善盟| 二手房| 铜山县| 资兴市| 佳木斯市| 清徐县| 绥棱县| 彭水| 阿瓦提县| 仁寿县| 黑水县| 阿拉善右旗| 梅州市| 茶陵县| 雷山县| 县级市| 通许县| 长丰县| 天峻县| 五大连池市| 玛沁县| 永定县| 澄城县| 乐昌市| 曲水县| 忻城县| 铜川市| 高雄县| 磴口县| 福贡县| 光泽县| 鹤山市| 临湘市| 龙口市| 哈巴河县| 中江县| 孟津县| 沾益县| 安仁县| 渝北区|