程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

一文掌握Python 最難知識點:元類

編輯:Python

前言

在學習 python 過程中想必大家都會去看源碼,看源碼的過程中會看到一些元類,但是看起來感覺很吃力看不懂,那是因為我們對元類不夠了解。

今天我們就來聊一聊 python 元類,看看元類到底是何方神聖。

必要知識儲備

● 在講元類之前我們得先搞清楚類和對象的概念以及類的創建過程,這個至關重要,這取決於我們是否能真正理解和正確使用元類。

● 類和對象概念

1、類:用來描述具有相同的屬性和方法的對象的集合(抽象)

2、對象:類的實體就是對象(具體)傳統方式創建類

傳統方式創建類

1、代碼演示
class Demo:
def __init__(self,name):
self.name = name
print("初始化self.name = ",self.name)
if __name__ == '__main__'
print("Demo類是由誰創建的:",type(Demo))
print("Demo類的父類:",Demo.__bases__)
cl = Demo("老王")
print("cl實例是由誰創建的:",type(cl))
2、輸出:
Demo類是由誰創建的:<class 'type'>
Demo類的父類:(<class 'object'>,)
初始化self.name = 老王
cl實例是由誰創建的:<class '__main__.Demo'>
3、結論:
a、類(Demo)是由type創建的
b、對象(cl)是由類(Demo)創建的
c、基於類(Demo)創建對象(cl),先執行父類(object)的__new__()方法,返回對象(cl)

type 創建類

1、通過上面的例子我們知道,類是由type創建的,那麼我們能不能直接通過type來創建類
2、type語法
type("類名",(繼承哪個類,),{"屬性名稱":"屬性值","方法名稱key":"方法名稱"})
3、代碼演示
demo = type("Demo",(object,),{"name":"老王"})
print("類名稱:",demo.__name__)
print("Demo類是由誰創建的:",type(demo))
cl = demo()
print("cl實例是由誰創建的:",type(cl))
4、輸出:
類名稱:Demo
Demo類是由誰創建的:<class 'type'>
cl實例是由誰創建的:<class '__main__.Demo'>
5、結論
a、類(Demo)是由type創建的
b、對象(cl)是由類(Demo)創建的
c、直接用type創建類和傳統方式創建類,效果一模一樣

元類

● 概念

1、什麼是元類:用來創建其他類的類叫元類
2、思考一個問題,我們能不能基於自己定義的類來創建其他的類?

自定義元類並創建類

1、代碼演示
class Demo1(type):
def __init__(self,*args, **kwargs):
super().__init__(*args, **kwargs)
class Demo2(metaclass=Demo1):
def __init__(self,name,age):
self.name = name
self.age = age
print("Demo2類的實例屬性:name={}".format(self.name))
print("Demo2類的實例屬性:age={}".format(self.age))
if __name__ == '__main__':
print("Demo2是由誰創建的:",type(Demo2))
cl = Demo2("老王","20")
2、輸出:
Demo2是由誰創建的:<class '__main__.Demo1'>
Demo2類的實例屬性:name=老王
Demo2類的實例屬性:age=20
3、結論
a、類(Demo2)是由Demo1創建的
b、可以通過自定義類來創建其他類

元類經典應用

1、通過元類實現單例模式
2、單例模式:在程序執行過程中一個類只實例化一次
3、原理:干預類實例化的過程,如果已經實例化了就不再進行實例化
class Demo1(type):
def __init__(self,name,bases, attrs):
super().__init__(name,bases, attrs)
self._instance = None
def __call__(self, *args, **kwargs):
#判斷是否創建了對象,未創建就調用__new__()方法創建對象,已創建了就不調用__new__()方法,直接返回已創建好的對象
if self._instance is None:
self._instance = self.__new__(self,*args, **kwargs)
#調用自己類(Demo2)的實例化方法
self.__init__(self._instance,*args, **kwargs)
return self._instance
class Demo2(metaclass=Demo1):
def __init__(self,name,age):
self.name = name
self.age = age
print("Demo2類的實例屬性:name={}".format(self.name))
print("Demo2類的實例屬性:age={}".format(self.age))
if __name__ == '__main__':
print("Demo2是由誰創建的:",type(Demo2))
cl1 = Demo2("老王",20)
cl2 = Demo2("老王",20)
print("cl1實例的內存地址:",id(cl1))
print("cl2實例的內存地址:",id(cl1))
print("cl1 是否是 cl2",cl1 is cl2)
4、輸出:
Demo2是由誰創建的:<class '__main__.Demo1'>
Demo2類的實例屬性:name=老王
Demo2類的實例屬性:age=20
Demo2類的實例屬性:name=老王
Demo2類的實例屬性:age=20
cl1實例的內存地址:1842280993096
cl2實例的內存地址:1842280993096
cl1 是否是 cl2 True

綿薄之力

最後感謝每一個認真閱讀我文章的人,看著粉絲一路的上漲和關注,禮尚往來總是要有的,雖然不是什麼很值錢的東西,如果你用得到的話可以直接拿走!

房子要一層一層蓋,知識要一點一點學。大家在學習過程中要好基礎,多上手實操,話不多說,這裡狠狠上一次干貨!我熬夜整理好的各階段(功能、接口、自動化、性能、測開)技能學習資料+實操講解,非常適合私下裡學習,比找資料自學高效多了,分享給你們。

領取關 w/x/g/z/h:軟件測試小dao

敲字不易,如果此文章對你有幫助的話,點個贊收個藏來個關注,給作者一個鼓勵。也方便你下次能夠快速查找。


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved