Python超詳細(xì)講解元類(lèi)的使用
類(lèi)的定義
對(duì)象是通過(guò)類(lèi)創(chuàng)建的,如下面的代碼:
# object 為頂層基類(lèi)
class Work(object):
a = 100
Mywork = Work() # 實(shí)例化
print(Mywork ) # Mywork 是 Work 所創(chuàng)建的一個(gè)對(duì)象 <__main__.Work object at 0x101eb4630>
print(type(Mywork)) # <class '__main__.Work'>
print(type(Work)) # 類(lèi)型為元類(lèi) <class 'type'>解析:
可以看見(jiàn)對(duì)象 Mywork 是類(lèi) Work 創(chuàng)建的實(shí)例。然但是可以看到Work的類(lèi)型時(shí)由一個(gè)叫 type 的類(lèi)創(chuàng)建的實(shí)例。即 Mywork —》 Work —》 type 創(chuàng)建
上面的例子中對(duì)象是動(dòng)態(tài)創(chuàng)建的,類(lèi)則是通過(guò)關(guān)鍵字 class 聲明定義的
那么class關(guān)鍵字背后的玄機(jī)是什么呢?
- 實(shí)際上,class Work(object) 這樣的代碼,等價(jià)于 Work = type(‘Work’, (objects, ), {“a”:100})
- 即類(lèi) type 通過(guò)實(shí)例化創(chuàng)建了它的對(duì)象 Work,而這個(gè) Work 恰恰是一個(gè)類(lèi),這樣能創(chuàng)建類(lèi)的類(lèi),就是 Python 的元類(lèi)。而在python中內(nèi)置的元類(lèi)叫:type
一、什么是元類(lèi)
- 用來(lái)創(chuàng)建類(lèi)的類(lèi),叫做元類(lèi)
- 類(lèi)是元類(lèi)創(chuàng)建出來(lái)的對(duì)象
- 函數(shù)type實(shí)際上是一個(gè)元類(lèi),type就是Python在背后用來(lái)創(chuàng)建所有類(lèi)的元類(lèi)
二、注意區(qū)分元類(lèi)和繼承的基類(lèi)
- type是元類(lèi),所有的類(lèi)都是通過(guò)type所創(chuàng)建出來(lái)的
- object頂層的基類(lèi),所有類(lèi)的繼承頂層父類(lèi)都是object
三、type 元類(lèi)的使用
可以看到type是小寫(xiě),一般情況下都會(huì)認(rèn)為它是一個(gè)函數(shù),通過(guò)查看源代碼去看下如下定義的:
class type(object):
"""
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
"""
# 實(shí)例化
def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
"""
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
# (copied from class doc)
"""
pass
# 創(chuàng)建類(lèi)
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
"""
Create and return a new object. See help(type) for accurate signature.
(創(chuàng)建并返回一個(gè)新對(duì)象)
"""
passtype的用法一:獲取數(shù)據(jù)時(shí)那種類(lèi)型 : type(object) -> the object’s type
a = 100 b = "100" c = [11,22,33] print(type(a)) # ======》 <class 'int'> print(type(b)) # ======》 <class 'str'> print(type(c)) # ======》 <class 'list'>
type的用法二:創(chuàng)建類(lèi):type(object_or_name, bases, dict)
1.在查看源碼的時(shí)候,可以看到在初始化時(shí),init__方法接受三個(gè)參數(shù),type 在實(shí)例化的過(guò)程,也會(huì)重新創(chuàng)建一個(gè)新的類(lèi),而創(chuàng)建類(lèi)的代碼來(lái)自__new 方法,它的參數(shù)與 __init__方法是一樣的。
2.當(dāng)調(diào)用 type 進(jìn)行實(shí)例化的時(shí)候,會(huì)先自動(dòng)調(diào)用 new 方法,再調(diào)用__init__方法,最終會(huì)實(shí)例化一個(gè)對(duì)象,這個(gè)對(duì)象是一個(gè)類(lèi)。
1. 元類(lèi) type 的 init 方法有3個(gè)參數(shù):
1.name:類(lèi)名(字符串類(lèi)型)
2.bases:繼承的父類(lèi)(元祖類(lèi)型)
3.dict:屬性和方法組成的字典(字典類(lèi)型)
具體例子:
# 通過(guò) class 定義類(lèi)
class Myclass(object):
a = 100
b = 200
# 通過(guò)type創(chuàng)建的類(lèi)(動(dòng)態(tài)創(chuàng)建類(lèi))
Myclass1 = type("Myclass1",(object,),{"a":"100","b":"200"})
print(Myclass)
print(Myclass1)
如果需要定義實(shí)例方法和類(lèi)屬性怎么辦呢?,將方法和屬性以字典的形式傳進(jìn)去
def work(self):
print("這是實(shí)例方法——————work————————")
# 定義類(lèi)屬性值
def init_method(self, aa, bb, cc):
self.aa = aa
self.bb = bb
self.cc = cc
# 通過(guò)type創(chuàng)建的類(lèi)(動(dòng)態(tài)創(chuàng)建類(lèi))
Myclass2 = type("Myclass2",(object,),{"a":"100","b":"200","work":work,"work_1":work_1,"__init__":init_method})
m = Myclass2(11,22,33)
m.work()
print(m.aa, m.bb, m.cc)
四、自定義元類(lèi)的使用
既然元類(lèi)可以創(chuàng)建類(lèi),那也可以自定義元類(lèi),自定義直接繼承類(lèi) type ,在自定義元類(lèi)的步驟:
1.定義一個(gè)類(lèi)繼承type
2.重寫(xiě)new方法
具體例子:
# 定義一個(gè)類(lèi)繼承type
class Mytest(type):
# 重寫(xiě)new方法
def __new__(cls, type_name, bases, atter, *args, **kwargs):
new_cls = super().__new__(cls,type_name, bases, atter)
return new_cls # 返回新的類(lèi)
M2 = Mytest("M2",(Mytest,),{"atter":100})
print(M2) # =====》 <class '__main__.M2'>使用class創(chuàng)建類(lèi)的時(shí)候指定自定義的元類(lèi)
1.不去指定時(shí),默認(rèn)創(chuàng)建都是type類(lèi)
2.指定自定義的元類(lèi)去創(chuàng)建類(lèi):metaclass = 指定的元類(lèi)
class Myclass(type):
"""自定義的元類(lèi)"""
def __new__(cls, type_name, bases, attrs, *args, **kwargs):
new_cls = super().__new__(cls, type_name, bases, attrs)
print("這個(gè)是Myclass:", type_name, bases, attrs, )
return new_cls
# 通過(guò)metaclass=xxxx 繼承自定義元類(lèi)
class Inherited_class(metaclass=Myclass):
a = 100
b = 200
print(type(Inherited_class)) # ======》 <class '__main__.Myclass'>
到此這篇關(guān)于Python超詳細(xì)講解元類(lèi)的使用的文章就介紹到這了,更多相關(guān)Python元類(lèi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python簡(jiǎn)單獲取數(shù)組元素個(gè)數(shù)的方法
這篇文章主要介紹了python簡(jiǎn)單獲取數(shù)組元素個(gè)數(shù)的方法,實(shí)例分析了Python中l(wèi)en方法的相關(guān)使用技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-07-07
PyTorch 解決Dataset和Dataloader遇到的問(wèn)題
今天小編就為大家分享一篇PyTorch 解決Dataset和Dataloader遇到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01
Python實(shí)現(xiàn)個(gè)人微信號(hào)自動(dòng)監(jiān)控告警的示例
今天小編就為大家分享一篇Python實(shí)現(xiàn)個(gè)人微信號(hào)自動(dòng)監(jiān)控告警的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
PyTorch中l(wèi)oading fbgemm.dll異常的解決辦法
PyTorch是一個(gè)深度學(xué)習(xí)框架,當(dāng)我們?cè)诒镜卣{(diào)試大模型時(shí),可能會(huì)選用并安裝它,目前已更新至2.4版本,本文給大家介紹了PyTorch中l(wèi)oading fbgemm.dll異常的解決辦法,文中通過(guò)代碼和圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08
python urllib urlopen()對(duì)象方法/代理的補(bǔ)充說(shuō)明
這篇文章主要介紹了python urllib urlopen()對(duì)象方法/代理的補(bǔ)充說(shuō)明的相關(guān)資料,需要的朋友可以參考下2017-06-06
python類(lèi)的私有屬性和公共屬性說(shuō)明
這篇文章主要介紹了python類(lèi)的私有屬性和公共屬性說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
Win10系統(tǒng)下安裝labelme及json文件批量轉(zhuǎn)化方法
這篇文章主要介紹了Win10系統(tǒng)下安裝labelme及json文件批量轉(zhuǎn)化的方法,文中較詳細(xì)的給大家介紹了安裝過(guò)程 ,需要的朋友可以參考下2019-07-07

