面向对象高级(上)
1 判斷類型和子類
判斷對象是否是屬于某個類的
isinstance(對象名, 類名)注意: 如果是它的父類, 同樣也返回True; 但是 (父類的對象, 子類) 返回的是Fale
查看父類, 注意是使用類名而不是對象
類名.__bases__判斷是否是某個類的子類
issubclass(子類名, 父類名)2 反射
反射是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力
2.1 反射參數
可以通過不同的字符串來反射不同的參數, 進而進行一定的操作; 或者反射一些函數來執行
在Python中主要是使用內置函數hasattr,?getattr, setattr, delattr三個函數
hassattr(), 判斷對象或者類是否具有摸個參數, 第一個參數是類或者對象, 第二個參數是字符串類型的名字, 返回值是True或者False
class People:def run(self):print('running..')print( hasattr(People() , 'run') ) print( hasattr(People , 'run') )getattr(), 獲取對象或者類的參數,?第一個參數是類或者對象, 第二個參數是字符串類型的名字,但是使用對象和類室友區別的
另外還可以設置第三個參數, 當該屬性不存在的時候返回那個值
whc = People() func = getattr(whc, 'run') func() func = getattr(People, 'run') func(whc) print( getattr(whc, 'running', '該屬性不存在') )setattr(), 設置屬性, 同樣可以給對象和類綁定
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__)使用反射的好處,?可插拔機制
因為可以查看類中是否含有某屬性, 在不同模塊寫程序的時候, 只需要判斷該屬性有沒有就可使程序健壯的完成, 而不必要等待相關聯的模塊完成
2.2 反射模塊
在正常使用的導入模塊是使用import或者from, 但是要反射某個模塊, 同樣是根據輸入的字符串的來反射
具體的反射有兩種操作, 一個是內置函數__import__(), 另一個是使用模塊importlib
具體模式如下
返回值 = __import__(模塊名字字符串) #或者 import importlib 返回值 = importlib.import_module(模塊名字字符串)返回值就是相當于反射回來的命名空間的名字
一般建議使用第二種方法
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__()函數之后, 類中所有的設置, 刪除屬性和方法的時候都會調用它
具體來說, 由于設置了這兩個函數, 所以在完成設置和刪除功能的時候, 不能再使用賦值語句和setattr()這個內置函數的處理了
要處理結果需要使用__dict__屬性來完成
__setattr__() 默認有三個參數, 一個是self, 第二個是鍵, 第三個是值
__deltattr__()認有兩個個參數,一個self, 另一個是需要刪除的屬性的名字
但是__getattr__()函數特殊, 它是在調用attr不存在的時候才調用, 基于這個特性有很強的使用效果
具體的實例如下
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 #應該使用它def __delattr__(self, item):print('----> from delattr')# del self.item #無限遞歸了self.__dict__.pop(item)#__setattr__添加/修改屬性會觸發它的執行 f1=Foo(10) print(f1.__dict__) # 因為你重寫了__setattr__,凡是賦值操作都會觸發它的運行,你啥都沒寫,就是根本沒賦值,除非你直接操作屬性字典,否則永遠無法賦值 f1.z=3 print(f1.__dict__)#__delattr__刪除屬性的時候會觸發 f1.__dict__['a']=3#我們可以直接修改屬性字典,來完成添加/修改屬性的操作 del f1.a print(f1.__dict__)#__getattr__只有在使用點調用屬性且屬性不存在的時候才會觸發 f1.xxxxxx4 授權
授權是__getattr__()函數的應用
具體實例是實現一個記錄日志的Open類
在__init__()函數中, 可以通過傳入的內容來獲得文件句柄, 再編寫一個write()函數, 通過文件句柄寫入日志信息即可
但是除了wirte()函數功能之外別的文件函數像close()和flush()等都不需要修改的, 但是總不能每一個都寫一遍
所以利用__getattr__()不存在屬性調用的特性, 利用__getattr__()有兩個參數一個是self另一個就是獲取的屬性名這個特性, 通過內置函數getattr()來具體取得那些相關屬性
具體代碼如下
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()方法, 來加入對添加進來的值進行類型判斷, 從而實現自定義功能
具體代碼如下
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)
轉載于:https://www.cnblogs.com/weihuchao/p/6757345.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
- 上一篇: xss专用章节
- 下一篇: PetaPoco 快速上手