面向对象高级(上)
1 判斷類型和子類
判斷對象是否是屬于某個類的
isinstance(對象名, 類名)注意: 如果是它的父類, 同樣也返回True; 但是 (父類的對象, 子類) 返回的是Fale
查看父類, 注意是使用類名而不是對象
類名.__bases__判斷是否是某個類的子類
issubclass(子類名, 父類名)2 反射
反射是指程序可以訪問、檢測和修改它本身狀態(tài)或行為的一種能力
2.1 反射參數(shù)
可以通過不同的字符串來反射不同的參數(shù), 進而進行一定的操作; 或者反射一些函數(shù)來執(zhí)行
在Python中主要是使用內(nèi)置函數(shù)hasattr,?getattr, setattr, delattr三個函數(shù)
hassattr(), 判斷對象或者類是否具有摸個參數(shù), 第一個參數(shù)是類或者對象, 第二個參數(shù)是字符串類型的名字, 返回值是True或者False
class People:def run(self):print('running..')print( hasattr(People() , 'run') ) print( hasattr(People , 'run') )getattr(), 獲取對象或者類的參數(shù),?第一個參數(shù)是類或者對象, 第二個參數(shù)是字符串類型的名字,但是使用對象和類室友區(qū)別的
另外還可以設(shè)置第三個參數(shù), 當(dāng)該屬性不存在的時候返回那個值
whc = People() func = getattr(whc, 'run') func() func = getattr(People, 'run') func(whc) print( getattr(whc, 'running', '該屬性不存在') )setattr(), 設(shè)置屬性, 同樣可以給對象和類綁定
whc = People() setattr(whc, 'name', 'weihuchao') setattr(People, 'country', 'China') print(whc.__dict__) print(People.__dict__)delattr(), 刪除屬性
delattr(whc, 'name') delattr(People,'country') print(whc.__dict__) print(People.__dict__)使用反射的好處,?可插拔機制
因為可以查看類中是否含有某屬性, 在不同模塊寫程序的時候, 只需要判斷該屬性有沒有就可使程序健壯的完成, 而不必要等待相關(guān)聯(lián)的模塊完成
2.2 反射模塊
在正常使用的導(dǎo)入模塊是使用import或者from, 但是要反射某個模塊, 同樣是根據(jù)輸入的字符串的來反射
具體的反射有兩種操作, 一個是內(nèi)置函數(shù)__import__(), 另一個是使用模塊importlib
具體模式如下
返回值 = __import__(模塊名字字符串) #或者 import importlib 返回值 = importlib.import_module(模塊名字字符串)返回值就是相當(dāng)于反射回來的命名空間的名字
一般建議使用第二種方法
name = 'time' nameSpace = __import__(name) print(nameSpace.time()) #或者 import importlib name = 'time' nameSpace = importlib.import_module(name) print(nameSpace.time())另外反射的例子
3 __getattr__等
在類中, 還可以定義__getattr__(),?__setattr__() 和?__deltattr__()
定義了__setattr__() 和?__deltattr__()函數(shù)之后, 類中所有的設(shè)置, 刪除屬性和方法的時候都會調(diào)用它
具體來說, 由于設(shè)置了這兩個函數(shù), 所以在完成設(shè)置和刪除功能的時候, 不能再使用賦值語句和setattr()這個內(nèi)置函數(shù)的處理了
要處理結(jié)果需要使用__dict__屬性來完成
__setattr__() 默認(rèn)有三個參數(shù), 一個是self, 第二個是鍵, 第三個是值
__deltattr__()認(rèn)有兩個個參數(shù),一個self, 另一個是需要刪除的屬性的名字
但是__getattr__()函數(shù)特殊, 它是在調(diào)用attr不存在的時候才調(diào)用, 基于這個特性有很強的使用效果
具體的實例如下
class Foo:x=1def __init__(self,y):self.y=ydef __getattr__(self, item):print('----> from getattr:你找的屬性不存在')def __setattr__(self, key, value):print('----> from setattr')# self.key=value #這就無限遞歸了,# self.__dict__[key]=value #應(yīng)該使用它def __delattr__(self, item):print('----> from delattr')# del self.item #無限遞歸了self.__dict__.pop(item)#__setattr__添加/修改屬性會觸發(fā)它的執(zhí)行 f1=Foo(10) print(f1.__dict__) # 因為你重寫了__setattr__,凡是賦值操作都會觸發(fā)它的運行,你啥都沒寫,就是根本沒賦值,除非你直接操作屬性字典,否則永遠無法賦值 f1.z=3 print(f1.__dict__)#__delattr__刪除屬性的時候會觸發(fā) f1.__dict__['a']=3#我們可以直接修改屬性字典,來完成添加/修改屬性的操作 del f1.a print(f1.__dict__)#__getattr__只有在使用點調(diào)用屬性且屬性不存在的時候才會觸發(fā) f1.xxxxxx4 授權(quán)
授權(quán)是__getattr__()函數(shù)的應(yīng)用
具體實例是實現(xiàn)一個記錄日志的Open類
在__init__()函數(shù)中, 可以通過傳入的內(nèi)容來獲得文件句柄, 再編寫一個write()函數(shù), 通過文件句柄寫入日志信息即可
但是除了wirte()函數(shù)功能之外別的文件函數(shù)像close()和flush()等都不需要修改的, 但是總不能每一個都寫一遍
所以利用__getattr__()不存在屬性調(diào)用的特性, 利用__getattr__()有兩個參數(shù)一個是self另一個就是獲取的屬性名這個特性, 通過內(nèi)置函數(shù)getattr()來具體取得那些相關(guān)屬性
具體代碼如下
import time class LogFile:def __init__(self,filename,mode='r',encoding='utf-8'):self.file=open(filename,mode,encoding=encoding)def write(self,line):t=time.strftime('%Y-%m-%d %T')self.file.write('%s %s' %(t,line))def __getattr__(self, item):print("aaa")return getattr(self.file,item)f1=LogFile('log', 'w+') f1.write('create logs..') f1.seek(0) print(f1.read()) f1.close()5 包裝
通過繼承基本類型list, 來獲得list的全部功能, 通過重寫append()方法, 來加入對添加進來的值進行類型判斷, 從而實現(xiàn)自定義功能
具體代碼如下
class List(list):def append(self, p_object):if not isinstance(p_object,int):raise TypeError('插入的值必須是int類型的!')super().append(p_object)myList = List([1,2,3,4]) print(myList) myList.append(5) print(myList) try:myList.append('test') except:print("輸入值類型不正確") print(myList)
轉(zhuǎn)載于:https://www.cnblogs.com/weihuchao/p/6757345.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
- 上一篇: xss专用章节
- 下一篇: Python-面向对象进阶