python 元類 python元類深入理解

2021-10-11 05:05:11 字數 4334 閱讀 7863

1.python 中的類

在python中,類也是乙個物件,只不過這個物件擁有生成例項的能力,我們一般使用class ***來定義乙個類,在python直譯器執行到這個地方的時候會自動建立出這個物件,python也為我們提供了手動建立類的方法,type()。type()這個方法對我們來說並不陌生,我們所熟知的用法是:class = type(instance),當傳入乙個引數時,type()返回這個引數的類。而今天我們要用到的是type的另乙個功能。type("classname",(object,),)。當給type傳入三個引數時,就是乙個手動建立類的方式。

classa():def __init__(self,name):

self.name=nameprint("建立了乙個例項")

a= type("a",(a,),)print(a) #

print(a.name) #jiao

print(a("jiang")) #建立了乙個例項

#<__main__.a object at>

type接收三個引數分別是:

classname: 要建立的class 的名稱

object:要建立類的父類所組成的元組

sttr_dict: 要建立類的屬性

type返回乙個class,我們接收並賦值到乙個變數上,現在這個變數就指向我們所建立的類,我們可以通過這個變數來使用類。

2.python 中的type

在python 中,幾乎所有的東西都是物件,這包括整數、字串、函式以及類。它們全部都是物件,而且它們都是從乙個類建立而來——type

3.__metaclass__屬性

python在建立類時,會按照如下的流程進行:

foo中有__metaclass__這個屬性嗎?如果是,python會在記憶體中通過__metaclass__建立乙個名字為foo的類物件(我說的是類物件,請緊跟我的思路)。如果python沒有找到__metaclass__,它會繼續在bar(父類)中尋找__metaclass__屬性,並嘗試做和前面同樣的操作。如果python在任何父類中都找不到__metaclass__,它就會在模組層次中去尋找__metaclass__,並嘗試做同樣的操作。如果還是找不到__metaclass__,python就會用內建的type來建立這個類物件。

那麼在__metaclass__中放置什麼樣的**可以建立類呢?type,或者任何使用到type或者子類化type的東東都可以。

4.自定義元類

classupperattrmetaclass(type):def __new__(cls,class_name,class_parents,class_attr, *args, **kwargs):print("__new__")

class_attr['name'] = "jiao"

return type.__new__(cls,class_name,class_parents,class_attr)def __init__(self,*args,**kwargs):print("__init__")

super().__init__(*args, **kwargs)

self.__cache ={}def __call__(self, *args, **kwargs):print("__call__")if args in self.__cache:return self.__cache[args]else:

obj= super().__call__(*args)

self.__cache[args] =objreturnobjclass a(metaclass=upperattrmetaclass):def __init__(self,name):

self.name=nameprint("a.__init__")

5.類的建立流程

1.元類的__new__(),返回建立好的類。當我們想要改變建立方式的時候就要重寫這個方法。

2.元類的__init__(),初始化一些類的屬性

6.例項建立流程

1.元類的__call__(),建立乙個例項時,首先呼叫這個方法,返回建立好的例項,所以我們可以通過改寫這個方法來改變例項建立過程,比如實現單例模式

2.類的__init__(),初始化例項屬性

7.元類的應用

1.單例模式

classsingleton(type):def __init__(cls,*args,**kwargs):

cls.__instance =none

super().__init__(*args,**kwargs)def __call__(cls, *args, **kwargs):if cls.__instance isnone:

cls.__instance = super().__call__(*args,**kwargs)return cls.__instance

else:return cls.__instance

class spam(metaclass=singleton):def __init__(self):print("creating spam")

2.快取模式

importweakrefclasscached(type):def __init__(cls,*args,**kwargs):

super().__init__(*args,**kwargs)

cls.__cache =weakref.weakvaluedictionary()def __call__(cls, *args, **kwargs):if args in cls.__cache:return cls.__cache[args]else:

obj= super().__call__(*args)

cls.__cache[args] =objreturnobjclass spams(metaclass=cached):def __init__(self,name):print("creating spam()".format(name))

self.name= name

3.獲取屬性的定義順序

能過獲取到屬性的定義順序,我們就可以通過簡單的方法實現屬性到資料的對映,可以更加簡單的將類中的屬性資料化。

from collections importordereddictclasstyped:

_excepted_type=type(none)def __init__(self,name=none):

self._name=namedef __set__(self, instance, value):if notisinstance(value,self._excepted_type):raise typeerror("excepted"+str(self._excepted_type))

instance.__dict__[self._name] =valueclassinteger(typed):

_excepted_type=intclassfloat(typed):

_excepted_type=floatclassstring(typed):

_excepted_type=strclassorderedmeta(type):def __new__(cls, clsname,bases,clsdict):

d=dict(clsdict)

order=for name,value inclsdict.items():ifisinstance(value,typed):

value._name=name

d['_order'] =orderreturn type.__new__(cls,clsname,bases,d)

@classmethoddef __prepare__(metacls, name, bases):returnordereddict()#注:__prepare__該方法會在類定義一開始的時候呼叫,呼叫時以類名和基類名稱作為引數,它必須返回乙個對映物件,供處理類定義體時呼叫

#eg.

class structure(metaclass=orderedmeta):defas_csv(self):return ','.join(str(getattr(self,name)) for name inself._order)class stock(metaclass=orderedmeta):

name=string()

shares=integer()

price=float()def __init__(self,name,shares,price):

self.name=name

self.shares=shares

self.price=price

s= stock("haha",23,23.3)print(s.name)

s= stock(34,23,34)#print(s.as_csv())

8.小結

元類主要就是在類和例項建立的時候發揮作用,來實現一些功能。

python元類的使用 Python的元類如何使用

這次給大家帶來python的元類如何使用,使用python元類的注意事項有哪些,下面就是實戰案例,一起來看一下。今天我的任務就是徹底明白什麼是元類,一起看看。要搞懂元類,我們還是先從物件說起。python 一切皆物件,這句話你一定有聽說過 現在你就聽說了 乙個數字是物件,乙個字串是物件,乙個列表是物...

python 元類程式設計 python的元類程式設計

一 property動態屬性 給類中的乙個方法函式加上 property裝飾器,將這個方法變成屬性描述符,將獲取方法變為獲取屬性。class user def init self,name,birthday self.name name self.birthday birthday property...

python元類的使用 Python 元類使用講解

我要一大群的類都具有一種特點,我怎麼給他們加上呢?模板嘛,我從這個模板建立一群類不就ok了?那就需要元類了。定義乙個元類 就是乙個類的模板!莫多想,還要記住這是類級別的,不是物件級別的!如下 class mymeta type def init cls,name,bases,dic print cl...