日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

day24 反射\元类

發(fā)布時(shí)間:2024/7/5 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 day24 反射\元类 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

反射 reflect

# 什么是反射, 其實(shí)是反省,自省的意思,反射指的是一個(gè)對(duì)象應(yīng)該具備,可以檢測(cè),修改,增加自身屬性的能力. # 反射就是通過(guò)字符串操作屬性,涉及的四個(gè)函數(shù),這四個(gè)函數(shù)就是普通的內(nèi)置函數(shù),沒(méi)有雙下劃綫,與print等等沒(méi)有區(qū)別.

案例

hasattr getattr setattr delattr p = Person("jack",18,"man")# if hasattr(p,"name"): # 1.判斷某個(gè)對(duì)象是否存在某個(gè)屬性 # print(getattr(p,"names",None)) # 2.從對(duì)象中取出屬性,第三個(gè)值位默認(rèn)值 當(dāng)屬性不存在是返回默認(rèn)值# 3.為對(duì)象添加新的屬性 setattr(p,"id","123") print(p.id)# 4.從對(duì)象中刪除屬性 delattr(p,"id") print(p.id)

?使用場(chǎng)景:

# 反射其實(shí)就是對(duì)屬性的增刪改查,但是如果直接使用內(nèi)置的__dict__來(lái)操作,語(yǔ)法繁瑣,不好理解 # 另外一個(gè)最主要的問(wèn)題是,如果對(duì)象不是我自己寫(xiě)的是另一方提供的,我就必須判斷這個(gè)對(duì)象是否滿足的要求,也就是是否我需要的屬性和方法

?

框架設(shè)計(jì)方式:

框架代碼:

# 反射被稱為框架的基石,為什么? 因?yàn)榭蚣艿脑O(shè)計(jì)者,不可能提前知道你的對(duì)象到底是怎么設(shè)計(jì)的,所以你提供給框架的對(duì)象 必須通過(guò)判斷驗(yàn)證之后才能正常使用,判斷驗(yàn)證就是反射要做的事情, 當(dāng)然通過(guò)__dict__也是可以實(shí)現(xiàn)的, 其實(shí)這些方法也就是對(duì)__dict__的操作進(jìn)行了封裝 需求:要實(shí)現(xiàn)一個(gè)用于處理用戶的終端指令的小框架,框架就是已經(jīng)實(shí)現(xiàn)了最基礎(chǔ)的構(gòu)架,就是所有項(xiàng)目都一樣的部分

?

實(shí)例

import plugins# 框架已經(jīng)實(shí)現(xiàn)的部分 def run(plugin):while True:cmd = input("請(qǐng)輸入指令:")if cmd == "exit":break# 因?yàn)闊o(wú)法確定框架使用者是否傳入正確的對(duì)象所以需要使用反射來(lái)檢測(cè)# 判斷對(duì)象是否具備處理這個(gè)指令的方法if hasattr(plugin,cmd):# 取出對(duì)應(yīng)方法方法func = getattr(plugin,cmd)func() # 執(zhí)行方法處理指令else:print("該指令不受支持...")print("see you la la!")# 創(chuàng)建一個(gè)插件對(duì)象 調(diào)用框架來(lái)使用它 # wincmd = plugins.WinCMD() # 框架之外的部分就有自定義對(duì)象來(lái)完成 linux = plugins.LinuxCMD() run(linux)

插件部分:

class WinCMD:def cd(self):print("wincmd 切換目錄....")def delete(self):print("wincmd 要不要?jiǎng)h庫(kù)跑路?")def dir(self):print("wincmd 列出所有文件....")class LinuxCMD:def cd(self):print("Linuxcmd 切換目錄....")def rm(self):print("Linuxcmd 要不要?jiǎng)h庫(kù)跑路?")def ls(self):print("Linuxcmd 列出所有文件....")

上述框架代碼中,寫(xiě)死了必須使用某個(gè)類,這是不合理的,因?yàn)闊o(wú)法提前知道對(duì)方的類在什么地方,以及類叫什么

所以我們應(yīng)該為框架的使用者提供一個(gè)配置文件,要求對(duì)方將累的信息寫(xiě)入配置文件,然后框架自己去加載需要的模塊

框架代碼:

import importlib import settings# 框架已經(jīng)實(shí)現(xiàn)的部分 def run(plugin):while True:cmd = input("請(qǐng)輸入指令:")if cmd == "exit":break# 因?yàn)闊o(wú)法確定框架使用者是否傳入正確的對(duì)象所以需要使用反射來(lái)檢測(cè)# 判斷對(duì)象是否具備處理這個(gè)指令的方法if hasattr(plugin,cmd):# 取出對(duì)應(yīng)方法方法func = getattr(plugin,cmd)func() # 執(zhí)行方法處理指令else:print("該指令不受支持...")print("see you la la!")# 創(chuàng)建一個(gè)插件對(duì)象 調(diào)用框架來(lái)使用它 # wincmd = plugins.WinCMD() # 框架之外的部分就有自定義對(duì)象來(lái)完成# 框架 得根據(jù)配置文件拿到需要的類 path = settings.CLASS_PATH # 從配置中單獨(dú)拿出來(lái) 模塊路徑和 類名稱 module_path,class_name = path.rsplit(".",1) #拿到模塊 mk = importlib.import_module(module_path) # 拿到類 cls = getattr(mk,class_name) # 實(shí)例化對(duì)象 obj = cls() #調(diào)用框架 run(obj)

如此一來(lái),框架就與實(shí)現(xiàn)代碼徹底解耦了,只剩下配置文件

?

元類 metaclass?

# 元類是什么,用于創(chuàng)建類的類,萬(wàn)物皆對(duì)象,類當(dāng)然也是對(duì)象 ,對(duì)象是通過(guò)類實(shí)例化產(chǎn)生的,如果類也是對(duì)象的話,必然類對(duì)象也是有另一個(gè)類實(shí)例化產(chǎn)生的,默認(rèn)情況下所有類的元類都是type.

?

代碼

class Person:pass p = Person()print(type(p)) print(type(Person))Person類是通過(guò)type類實(shí)例化產(chǎn)生的

學(xué)習(xí)元類的目的:

# 高度的自定義一個(gè)類,例如控制類的名字必須以大駝峰的方式來(lái)書(shū)寫(xiě) 類也是對(duì)象,也有自己的類, 我們的需求是創(chuàng)建類對(duì)象做一些限制 想到了初始化方法 我們只要找到類對(duì)象的類(元類),覆蓋其中 init方法就能實(shí)現(xiàn)需求 當(dāng)然我們不能修改源代碼,所以應(yīng)該繼承type來(lái)編寫(xiě)自己的元類,同時(shí)覆蓋init來(lái)完成需求

?

運(yùn)用

""" 只要繼承了type 那么這個(gè)類就變成了一個(gè)元類 """ # 定義了一個(gè)元類 class MyType(type):def __init__(self,clss_name,bases,dict):super().__init__(clss_name,bases,dict)print(clss_name,bases,dict)if not clss_name.istitle():raise Exception("你丫的 類名不會(huì)寫(xiě)...")# 為pig類指定了元類為MyType class Pig(metaclass=MyType):passclass Duck(metaclass=MyType):pass

元類中call方法

# 當(dāng)你調(diào)用類對(duì)象時(shí)會(huì)自動(dòng)珍惜元類中的__call__方法 ,并將這個(gè)類本身作為第一個(gè)參數(shù)傳入,以及后面的一堆參數(shù) 覆蓋元類中的call之后,這個(gè)類就無(wú)法產(chǎn)生對(duì)象,必須調(diào)用super().__call__來(lái)完成對(duì)象的創(chuàng)建 并返回其返回值

使用場(chǎng)景:

當(dāng)你想要控制對(duì)象的創(chuàng)建過(guò)程時(shí),就覆蓋call方法 當(dāng)你想要控制類的創(chuàng)建過(guò)程時(shí),就覆蓋init方法

?

案例:

實(shí)現(xiàn)將對(duì)象的所有屬性名稱轉(zhuǎn)為大寫(xiě)

lass MyType(type):def __call__(self, *args, **kwargs):new_args = []for a in args:new_args.append(a.upper())print(new_args)print(kwargs)return super().__call__(*new_args,**kwargs)class Person(metaclass=MyType):def __init__(self,name,gender):self.name = nameself.gender = genderp = Person(name="jack",gender="woman") print(p.name) print(p.gender)

注意:一旦覆蓋了call必須調(diào)用父類的call方法來(lái)產(chǎn)生對(duì)象并返回這個(gè)對(duì)象?

補(bǔ)充new方法

# 當(dāng)你要?jiǎng)?chuàng)建類對(duì)象時(shí),會(huì)首先執(zhí)行元類中的__new__方法,拿到一個(gè)空對(duì)象,然后會(huì)自動(dòng)調(diào)用__init__來(lái)對(duì)這個(gè)類進(jìn)行初始化操作 注意:,如果你覆蓋了該方法則必須保證,new方法必須有返回值且必須是,對(duì)應(yīng)的類對(duì)象

?

測(cè)試

class Meta(type):def __new__(cls, *args, **kwargs):print(cls) # 元類自己print(args) # 創(chuàng)建類需要的幾個(gè)參數(shù) 類名,基類,名稱空間print(kwargs) #空的 print("new run")# return super().__new__(cls,*args,**kwargs)obj = type.__new__(cls,*args,**kwargs)return objdef __init__(self,a,b,c):super().__init__(a,b,c)print("init run") class A(metaclass=Meta):pass print(A)

?

總結(jié)new方法和init 都可以實(shí)現(xiàn)控制類的創(chuàng)建過(guò)程,init更簡(jiǎn)單

單例設(shè)計(jì)模式

```

設(shè)計(jì)模式?用于解決某種固定問(wèn)題的套路 例如:MVCMTV等 單例:指的是一個(gè)類產(chǎn)生一個(gè)對(duì)象 為什么要使用單例:單例是為了節(jié)省 資源,當(dāng)一個(gè)類的所有對(duì)象屬性全部相同時(shí),則沒(méi)有必要?jiǎng)?chuàng)建多個(gè)對(duì)象

元類實(shí)現(xiàn):

# 單例n元類 class Single(type):def __call__(self, *args, **kwargs):if hasattr(self,"obj"): #判斷是否存在已經(jīng)有的對(duì)象return getattr(self,"obj") # 有就返回 obj = super().__call__(*args,**kwargs) # 沒(méi)有則創(chuàng)建print("new 了")self.obj = obj # 并存入類中return objclass Student(metaclass=Single):def __init__(self,name):self.name = nameclass Person(metaclass=Single):pass# 只會(huì)創(chuàng)建一個(gè)對(duì)象 Person() Person()

?

?

?

aa

?

轉(zhuǎn)載于:https://www.cnblogs.com/Ryan-Yuan/p/11272612.html

總結(jié)

以上是生活随笔為你收集整理的day24 反射\元类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。