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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面向对象之反射、包装、(定制)

發布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面向对象之反射、包装、(定制) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是反射?

反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力(自省),

這一概念的提出很快引發了計算機科學領域關于應用反射的研究。它首次被程序語言的設計領域所采用。并在Lisp和面向

對象方面取得了成績。

?

一、python3中四個可以實現自省的函數,下列方法適用于類和對象

class BlackMedium:feture='Ugly'def __init__(self,name,addr):self.name=nameself.addr=addrdef sell_hourse(self):print('[%s]正在賣房子,傻逼才買呢'%self.name)def rent_hourse(self):print('[%s]正在租房子,傻逼才買呢'%self.name)b1=BlackMedium('黑中介','殯儀館')

?

1、hasattr(object,name)

判斷object中有沒有一個name字符串對應的方法或屬性

class BlackMedium:feture='Ugly'def __init__(self,name,addr):self.name=nameself.addr=addrdef sell_hourse(self):print('[%s]正在賣房子,傻逼才買呢'%self.name)def rent_hourse(self):print('[%s]正在租房子,傻逼才買呢'%self.name)b1=BlackMedium('黑中介','殯儀館') print(b1.__dict__)#{'name': '黑中介', 'addr': '殯儀館'} # b1.name------->b1.__dict__['name] print(b1.name)#黑中介 print(b1.addr)#殯儀館 #用hasattr檢測類的屬性和方法,存在返回TRUE,不存在返回FALSE print(hasattr(b1,'name'))#True print(hasattr(b1,'addr'))#True print(hasattr(b1,'namnmae'))#False hasattr(object,name)

?

2、getattr(object,name,default=None)

檢測正確時,有屬性就返回屬性值,有方法就返回方法的內存地址,加()就可以運行

檢測有錯誤時,不給default賦值會報錯,報錯時寫什么會提示什么

#檢測屬性,屬性存在就會打印值,屬性不存在會打印報錯或default print(getattr(b1,'name'))#黑中介 print(getattr(b1,'aaaaaa'))#有報錯提示 print(getattr(b1,'aaaaaa','沒有此屬性'))#有報錯提示:沒有此屬性#檢測方法,有則返回內存地址,加()就可以運行,沒有則報錯或提示default信息 print(getattr(b1,'sell_hourse','無此方法'))#返回sell_hourse方法的內存地址,-------》b1.sell_hourse #<bound method BlackMedium.sell_hourse of <__main__.BlackMedium object at 0x0000020EE5447198>> #有內存地址加()就可以運行 func=getattr(b1,'sell_hourse') func()#[黑中介]正在賣房子,傻逼才買呢print(getattr(b1,'jskdkflsd','無此方法'))#無此方法 getattr(object,name,default)

?

3、setattr(x,y,z)

可以增加修改屬性,也可以增加方法,

x傳入對象,y傳入字符串相當于字典中的key,x傳入值相當于字典中的value

print(b1.__dict__)#{'name': '黑中介', 'addr': '殯儀館'} setattr(b1,'name','SB')#修改屬性 setattr(b1,'sb',True)#增加屬性 print(b1.__dict__)#{'name': 'SB', 'addr': '殯儀館', 'sb': True} setattr(b1,'func',lambda self:self.name+'SB')#增加函數屬性 # print(b1.func(b1))#黑中介SB setattr(x,y,z)

?

4、delattr(x,y)

刪除屬性x,y同上

print(b1.__dict__)#{'name': '黑中介', 'addr': '殯儀館'} delattr(b1,'name')#刪除屬性------》del b1.name # del b1.name print(b1.__dict__)#{'addr': '殯儀館'} setattr(x,y)

?

5、動態模塊導入

1、把模塊名或文件名以字符串形式傳給__import__,如果模塊在二級文件內,__import__方法只能拿到最頂級模塊 module_t=__import__('三級菜單')#執行module_t就會執行模塊內的代碼 print(module_t)2import imaplib m=imaplib.import_module('文件.三級菜單')#直接定位到三級菜單 print(m) 3、導入有*號時,如果模塊里面的屬性有 _名字 的屬性或方法時, 帶 下劃線的屬性或方法則不能被導入 from 模塊名 import *

?補充:

一切皆對象,文件也是對象同樣可以使用自省的方法

1、情景:當你寫的代碼有上萬行時(此時已是大佬 ^_^),想不起來某個功能是否完成既可以使用下面的方法來判斷

x=111 y=222 #用sys可以導入模塊自己,用hasattr可以檢測功能是否完成 import sys obj=sys.modules[__name__] print(hasattr(obj,'x'))#True print(hasattr(obj,'xsdf'))#False 導入模塊自己

?

2、情景:做程序開發,每個人寫不同的功能,當需要用到別人的功能時不知道是否完成,因此我們可以導入同事寫的代碼文件,用hasattr判斷你需要的功能是否完成

import test as obj print(obj)print(hasattr(obj,'say_hi'))if hasattr(obj,'say_hi'):func=getattr(obj,'say_hi')func()else:print('其他的邏輯') 導入別人的模塊

?

二、下劃線開頭的三種attr方法

這三種方法是給實例用的和類沒關系

1、__getattr__(self,item)

只有使用點調用屬性且屬性不存在時才會觸發__getattr__

class Foo:def __init__(self,name,age):self.name=nameself.age=agedef __getattr__(self, item):print('執行__getattr__,item是 %s'%item)#調用不存在屬性時觸發__getattr__ f1=Foo('飛樂',18) print(f1.__dict__)#{'name': '飛樂', 'age': 18} f1.name#不會觸發__getattr__ f1.jsdlkf#執行__getattr__,item是 jsdlkf __getattr__(self,item)

?

2、__delattr__(self,item)

刪除屬性時會觸發

class Foo:def __init__(self,name,age):self.name=nameself.age=agedef __delattr__(self, item):#只要有刪除操作就會觸發__delattr__,并不一定能刪除,# 下面的內容會講到觸發__delattr__并且刪除值print('執行__delattr__,item是 %s'%item) f1=Foo('飛樂',18) print(f1.__dict__)#{'name': '飛樂', 'age': 18} del f1.age#執行__delattr__,item是 age print(f1.__dict__)#{'name': '飛樂', 'age': 18} __delattr__(self,item)

?

3、__setattr__(self,key,value)

增加或修改屬性會觸發__setattr__的執行,在實例化對象時__init__函數屬于增加屬性操作,也會觸發__setattr__的執行?

class Foo:def __init__(self,name,age):#會觸發__setattr__self.name=nameself.age=agedef __setattr__(self, key, value):#添加或修改屬性會觸發它的執行print('執行__setattr__,key: %s value: %s'%(key,value))# self.kye=value #一直觸發__setattr__無期遞歸,你好好想想self.__dict__[key]=value#應該使用它 f1=Foo('飛樂',18) #執行__setattr__,key: name value: 飛樂 #執行__setattr__,key: age value: 18 print(f1.__dict__)#{'name': '飛樂', 'age': 18} f1.sex='male'#增加屬性,執行__setattr__,key: sex value: maleprint(f1.name)#飛樂 f1.name='king'#修改屬性,執行__setattr__,key: name value: king print(f1.__dict__)#{'name': 'king', 'age': 18, 'sex': 'male'} print(f1.name)#king __setattr__(self,key,value)

?

4、利用attr方法定制屬于自己的方法

根據下方代碼可以自己擴展,好好想想

class Foo:def __init__(self,name,age):self.name=nameself.age=agedef __getattr__(self, item):print('%s 屬性不存在'%item)def __setattr__(self, key, value):print('正在設置--------》')if type(value) is str:# self.key=value 會觸發__setattr__遞歸self.__dict__[key]=valueelse:print('屬性添加必須是字符串')def __delattr__(self, item):print('不允許刪除屬性 【%s】'%item)#del self.__dict__[item]#self.__dict__.pop(item) # f1=Foo('飛樂',18)#屬性添加必須是字符串 f1=Foo('飛樂','18')#增加或修改屬性會觸發__setattr__ #正在設置--------》 #正在設置--------》 f1.name#不會觸發__getattr__ f1.king#觸發__getattr__ king 屬性不存在 print(f1.__dict__)#{'name': '飛樂', 'age': '18'} f1.name='king'#觸發了__setattr__ print(f1.__dict__)# {'name': 'king', 'age': '18'} del f1.name#不允許刪除屬性 【name】 定制

?

三、包裝

包裝標準類型,通過繼承和派生進行包裝定制屬于自己的數據類型

1、通過繼承派生包裝

class List(list):def append(self, object):if type(object) is str:super().append(object)#繼承父類的append方法else:print('類型必須是字符串')def show_mid(self):mid_index=int(len(self)/2)return self[mid_index]l1=List('helloword') print(l1,type(l1))#['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'd'] <class '__main__.List'> l1.append('king') print(l1)#['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'd', 'king'] l1.append(3245)#類型必須是字符串類型 print(l1.show_mid())#w 定制屬于自己的list方法

?

2、通過__getattr__授權(包裝)

授權也是一種包裝用__getattr__方法,不用繼承和派生的方法來實現

import time class Open:def __init__(self,filename,mode='r',encoding='utf-8'):#用類有兩種方法一種是繼承另一種是組合self.file=open(filename,mode,encoding=encoding)#組合self.mode=modeself.encoding=encodingdef write(self,line):t=time.strftime('%Y-%m-%d %X')self.file.write('%s %s'%(t,line))def __getattr__(self, item):return getattr(self.file,item)#返回item方法的內存地址, #f1的屬性找不到時會觸發__getattr__的執行 f1=Open('a.txt','w+') print(f1.write)#返回的內存地址加()就可以執行 #<built-in method write of _io.TextIOWrapper object at 0x000002138D1E8B40> f1.write('helloword')#把內容寫入到文件中 f1.seek(0) print(f1.read())#helloword#f1的write能找到時 f1.write('CPU過載過高\n') f1.write('內存不足\n') f1.write('系統被不明病毒攻擊\n') f1.seek(0) print(f1.read())#讀出了定制寫入的內容 # 2018-09-10 22:34:34 helloword2018-09-10 22:34:34 CPU過載過高 # 2018-09-10 22:34:34 內存不足 # 2018-09-10 22:34:34 系統被不明病毒攻擊 授權

?

轉載于:https://www.cnblogs.com/happyfei/p/9618996.html

總結

以上是生活随笔為你收集整理的面向对象之反射、包装、(定制)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。