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

python的metaclass使用小結(jié)

 更新時間:2024年01月08日 08:58:50   作者:趙青青  
python中的metaclass可謂熟悉而又陌生,自己開發(fā)時很少用,閱讀源碼時卻經(jīng)常遇到,那么到底什么是metaclass呢?何時使用metaclass呢?這篇文章主要介紹了python的metaclass,需要的朋友可以參考下

python中的metaclass可謂熟悉而又陌生,自己開發(fā)時很少用,閱讀源碼時卻經(jīng)常遇到,那么到底什么是metaclass呢?何時使用metaclass呢?

動態(tài)創(chuàng)建class的方法

假設(shè)我們需要動態(tài)創(chuàng)建一個class,那么一般我們有這樣幾種方法

  • 通過一個函數(shù)動態(tài)創(chuàng)建class
  • 通過type動態(tài)創(chuàng)建class

1.函數(shù)動態(tài)創(chuàng)建class

def create_class_by_name(name):
    if name == 'dog': 
        class Dog(object):
            pass
        return Dog
    else:
        class Cat(object):
            pass
        return Cat
dy_class = create_class_by_name('hi')
print dy_class    # output: <class '__main__.Cat'>
print dy_class()  # output: <__main__.Cat object at 0x03601D10>

2.type動態(tài)創(chuàng)建class

type 除了可以獲取到一個對象的類型,還有另外一個功能:動態(tài)創(chuàng)建 class。
它的函數(shù)簽名是這樣的:_type(name, bases, dict) -> a new type_其中:

  • name: 類名
  • bases: 父類名的tuple,用于繼承,可以為空
  • dict: 字典,包含class attributes的 name 和 value
class ClassParent(object):
    first_name = 'John'
# 創(chuàng)建一個 繼承自 ClassParent 的 ClassChild,并為 ClassChild 添加一個 age = 15 的 attribute
child_class = type('ClassChild', (ClassParent,), {'age': 15})
# child_class 形如:
class ClassChild(ClassParent):
    age = 15
child_obj = child_class()
print child_obj.first_name, child_obj.age
# output: John 15

事實(shí)上,type 關(guān)鍵字,是 python 用來創(chuàng)建 class 的 metaclass??梢酝ㄟ^ __class__ 來查看一個 class 的 metaclass:

print child_class.__class__
# output <type 'type'>

使用metaclass創(chuàng)建class

metaclass,即是(class of class) class 的 class,用來描述如何創(chuàng)建一個 class 的代碼段。

python2

在 class 的定義中,可以通過 __metaclass__ 來指定當(dāng)前 class 的 metaclass:

因此,只要我們指定了__metaclass__就可以代替type()創(chuàng)建class.我們自己來寫一個最簡單的metaclass.

class DemoMeta(type):
	pass
class DemoClass(object):
	__metaclass__ = DemoMeta
print type(DemoClass) #<class '__main__.DemoMeta'>

看一個復(fù)雜些的例子

class FooMeta(type):
	def __new__(mcs, name, bases, attrs):
		"""
		定制創(chuàng)建 class 的行為
		作為示例,這里將外部傳入的 attrs 的名稱做一些處理:如果以'_'開頭,則轉(zhuǎn)為小寫
		:param name: class 名稱
		:param bases: tuple, 父類的名稱
		:param attrs: class attributes
		"""
		converted = {atr if not atr.startswith('_') else atr.lower(): v 
                     for atr, v in attrs.items()}
		cls = super(FooMeta, mcs).__new__(mcs, name, bases, converted)
		return cls
class Foo(object):
    __metaclass__ = FooMeta

python3

py3中,指定元類的語法有一點(diǎn)小小的修改:不再使用 __metaclass__,而是在定義 class 時顯式地指定 metaclass:

class Foo(object, metaclass=CustomMetaclass):
    pass

常見用途

metaclass可以控制類的創(chuàng)建過程,包括類的屬性、方法和父類等。metaclass可以用于實(shí)現(xiàn)一些高級的編程技巧,例如自動注冊子類、自動添加屬性和方法等

  • 統(tǒng)計某種類型
  • 定義一個單例
  • 自動添加屬性和方法

如何統(tǒng)計某個類的所有子類#

猜想一下,統(tǒng)計某個類的所有子類

__bases__是一個元組,包含了一個類的所有直接父類,所以不不能統(tǒng)計到某種類型

還有一種方法:

使用gc.get_objects()函數(shù)獲取所有已經(jīng)創(chuàng)建的對象,然后使用issubclass()函數(shù)判斷一個類是否是另一個類的子類,從而統(tǒng)計所有的子類

以下是一個示例代碼:

import gc
def count_subclasses(cls):
    count = 0
    for obj in gc.get_objects():
        if isinstance(obj, type) and issubclass(obj, cls):
            count += 1
    return count

自動統(tǒng)計某種類型

下面是一個簡單的例子演示了如何使用metaclass來自動注冊子類。

假設(shè)我們有一個基類Base,我們希望所有繼承自Base的子類都能夠自動注冊到一個全局的字典中。我們可以定義一個Meta類,該類繼承自type,并重寫其__init__方法,在該方法中實(shí)現(xiàn)自動注冊的邏輯。然后,我們將Base類的metaclass設(shè)置為Meta類,這樣所有繼承自Base的子類都會使用Meta類來創(chuàng)建實(shí)例,并自動注冊到全局字典中。

class Meta(type):
    registry = {}
    def __init__(cls, name, bases, attrs):
        super(Meta, cls).__init__(name, bases, attrs)
        if name != 'Base':
            Meta.registry[name] = cls
class Base(object):
    __metaclass__ = Meta
class Subclass1(Base):
    pass
class Subclass2(Base):
    pass
print Meta.registry

輸出結(jié)果為:

{'Subclass1': <class '__main__.Subclass1'>, 'Subclass2': <class '__main__.Subclass2'>}

可以看到,Subclass1和Subclass2都被自動注冊到了Meta.registry字典中。這樣,我們就可以方便地獲取所有繼承自Base的子類了。

定義單例

class Singleton(type):
    def __init__(cls, name, bases, dict):
        super(Singleton, cls).__init__(name, bases, dict)
        cls.instance = None
    def __call__(cls, *args):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args)
        return cls.instance
class MyCard(object):
	__metaclass__ = Singleton
def testSingle():
	card1 = MyCard()
	card2= MyCard()
	print card1,card2
    #輸出結(jié)果:<__main__.MyCard object at 0x03A6FE90> <__main__.MyCard object at 0x03A6FE90>

自動添加屬性和方法

假設(shè)我們有一個基類Base,我們希望所有繼承自Base的子類都能夠自動添加一個名為name的屬性和一個名為hello的方法。我們可以定義一個Meta類,該類繼承自type,并重寫其__init__方法,在該方法中實(shí)現(xiàn)自動添加屬性和方法的邏輯。然后,我們將Base類的metaclass設(shè)置為Meta類,這樣所有繼承自Base的子類都會使用Meta類來創(chuàng)建實(shí)例,并自動添加name屬性和hello方法。

class Meta(type):
    def __init__(cls, name, bases, attrs):
        super(Meta, cls).__init__(name, bases, attrs)
        cls.name = name
        cls.hello = lambda self: 'Hello, %s!' % self.name
class Base(object):
    __metaclass__ = Meta
class Subclass1(Base):
    pass
class Subclass2(Base):
    pass
print Subclass1().hello()
print Subclass2().hello()
#Hello, Subclass1!
#Hello, Subclass2!

Python選取 metaclass 的策略

在Python中,當(dāng)我們定義一個類時,解釋器會根據(jù)以下順序來選擇metaclass:

  • 如果該類顯式指定了metaclass,則使用該metaclass。
  • 否則,如果該類的父類中有metaclass,則使用該metaclass。
  • 否則,如果該類的模塊中有metaclass,則使用該metaclass。
  • 否則,如果該類的基類中有metaclass,則使用該metaclass。
  • 否則,使用默認(rèn)的type作為metaclass。

結(jié)尾

如果看完之后你還是看不懂,沒關(guān)系,99%的情況下都不需要用到metaclass

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

相關(guān)文章

  • Pandas實(shí)現(xiàn)(pivot_table函數(shù))數(shù)據(jù)透視表方式

    Pandas實(shí)現(xiàn)(pivot_table函數(shù))數(shù)據(jù)透視表方式

    pandas的pivot_table()函數(shù)非常強(qiáng)大,主要用于創(chuàng)建數(shù)據(jù)透視表,重要參數(shù)包括index、values、columns和aggfunc,index用于設(shè)置行索引,類似于SQL中的group by,values用于進(jìn)行聚合計算的數(shù)據(jù)選擇,columns參數(shù)可設(shè)置列層次,非必須
    2024-09-09
  • Python?時間操作datetime詳情

    Python?時間操作datetime詳情

    這篇文章主要介紹了?Python?時間操作datetime,datetime?模塊提供處理時間和日期的多種類,簡單方便,下面文章將詳細(xì)介紹其內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • Python使用pypdf按指定頁碼范圍批量拆分PDF

    Python使用pypdf按指定頁碼范圍批量拆分PDF

    在處理電子書,掃描書籍或技術(shù)文檔時,經(jīng)常會遇到一個需求,即按照指定頁碼范圍把一個 PDF 拆分成多個 PDF 文件,本文將介紹一種簡單、穩(wěn)定、無需外部依賴的方法,有需要的可以了解下
    2026-01-01
  • 詳解Java中一維、二維數(shù)組在內(nèi)存中的結(jié)構(gòu)

    詳解Java中一維、二維數(shù)組在內(nèi)存中的結(jié)構(gòu)

    這篇文章主要介紹了Java中一維、二維數(shù)組在內(nèi)存中的結(jié)構(gòu),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • python代碼區(qū)分大小寫嗎

    python代碼區(qū)分大小寫嗎

    在本篇文章里小編給大家整理了一篇關(guān)于python是否區(qū)分大小寫的相關(guān)內(nèi)容,對此有疑惑的新手們來學(xué)習(xí)下吧。
    2020-06-06
  • Python numpy二維數(shù)組如何刪除指定行和列

    Python numpy二維數(shù)組如何刪除指定行和列

    本文展示了如何對數(shù)組進(jìn)行行列刪除操作,包括刪除單行、單列、多行和多列的方法,通過具體的運(yùn)行結(jié)果展示,讀者可以清晰地了解到如何在不同情況下進(jìn)行數(shù)據(jù)處理,文章內(nèi)容實(shí)用,適合需要進(jìn)行數(shù)據(jù)處理的讀者參考學(xué)習(xí)
    2024-09-09
  • 一分鐘帶你上手Python調(diào)用DeepSeek的API

    一分鐘帶你上手Python調(diào)用DeepSeek的API

    最近DeepSeek非?;?作為一枚對前言技術(shù)非常關(guān)注的程序員來說,自然都想對接DeepSeek的API來體驗(yàn)一把,下面小編就來為大家介紹一下Python如何快速上手調(diào)用DeepSeek?API吧
    2025-02-02
  • Python中給字典排序的七種方法詳解

    Python中給字典排序的七種方法詳解

    我們經(jīng)常在計算機(jī)等級考試中遇到詞頻排序的問題,我們一般先通過生成字典的方法,統(tǒng)計詞的頻次,然后給字典排序,那么如何快速地給字典按照鍵值進(jìn)行排序呢?本文給大家介紹了Python中給字典排序的七種方法,需要的朋友可以參考下
    2025-07-07
  • 使用grpc實(shí)現(xiàn)golang后端和python服務(wù)間通信

    使用grpc實(shí)現(xiàn)golang后端和python服務(wù)間通信

    gRPC是Google 開發(fā)的高性能、開源的遠(yuǎn)程過程調(diào)用(RPC)框架,本文主要為大家詳細(xì)介紹了如何使用grpc實(shí)現(xiàn)golang后端和python服務(wù)間通信,感興趣的可以了解下
    2024-03-03
  • Python爬取京東的商品分類與鏈接

    Python爬取京東的商品分類與鏈接

    這篇文章主要介紹利用python爬取京東商品分類以及對應(yīng)的連接,這個功能不是很復(fù)雜,沒有爬取里面的隱藏的東西。算是給新手一個示例教程吧,有需要的可以參考借鑒。
    2016-08-08

最新評論

漠河县| 武城县| 新兴县| 泰来县| 湖南省| 云南省| 靖宇县| 宁蒗| 洪湖市| 成都市| 许昌市| 榆中县| 扎兰屯市| 南开区| 六枝特区| 东乡| 穆棱市| 青铜峡市| 登封市| 潜江市| 平遥县| 麻江县| 绥江县| 邵东县| 石景山区| 四会市| 湛江市| 上杭县| 泸水县| 新巴尔虎右旗| 金坛市| 渝中区| 高唐县| 凤冈县| 磐安县| 商水县| 扎赉特旗| 肥城市| 湘阴县| 三穗县| 扎囊县|