面向對象進階
isinstance(obj,cls) 檢查是否obj是類cls的對象
class Foo(object):
pass
obj = Foo()
isinstance(obj,Foo)
issubclass(sub,super) 檢查sub是否是super的派生類
class Foo(object):
pass
class Bar(Foo):
pass
issubclass(Bar,Foo)
反射
python面向對象中的反射:通過字符串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)
getattr,setattr,delattr,hasattr
class BlackManger:
feature = 'ugly'
def __init__(self,name,addr):
self.name = name
self.addr = addr
def sell_house(self):
print('%s' %self.name)
def rent_house(self):
print('%s' %self.name)
b1 = BlackManger('somecompany','zgc')
檢測是否含有某種屬性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))
獲取屬性
n = getattr(b1,'name')
print(n)
func = getattr(b1,'rent_house')
func()
getattr(b1,'aaaaaa')
print(getattr(b1,'aaaaaaa','bucunzai'))
設置屬性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1))
刪除屬性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,則報錯
print(b1.__dict__)
類也是對象
class Foo(object):
staticField = 'old boy'
def __init__(self):
self.name = 'lzq'
def func(self):
return 'func'
@staticmethod
def bar():
return 'bar'
print(getattr(Foo,'staticField'))
print(getattr(Foo,'func'))
print(getattr(Foo,'bar'))
反射當前模塊成員
import sys
def s1():
print('s1')
def s2():
print('s2')
this_module = sys.modules[__name__]
hasattr(this_module,'s1')
hasattr(this_module,'s2')
導入其他模塊,利用反射查找該模塊是否存在某個方法
# -*- coding:utf-8 -*-
def test():
print('from the test')
# -*- coding:utf-8 -*-
import module_test as obj
#obj.test()
print(hasattr(obj,'test'))
getattr(obj,'test')()
使用反射的好處
class FtpClient:
'未完成'
def __init__(self,addr):
print('正在連接服務器[%s]' %addr)
self.addr = addr
#from module import FtpClient
f1 = FtpClient('192.168.0.0')
if hasattr(f1,'get'):
func_get = getattr(f1,'get')
func_get()
else:
print('不存在此方法')
print('處理其他的邏輯')
__setattr__,__delattr__,__getattr__
class Foo:
x=1
def __init__(self,y):
self.y = y
def __getattr__(self,item):
print('-----> from getattr:"你找的屬性不存在')
def __setattr__(self,key,value):
print('----> from setattr')
self.__dict__[key] = value
def __delattr__(self,item):
print('----> from delattr')
self.__dict__.pop(item)
f1 = Foo(10)
print(f1.__dict__)
f1.z = 3
print(f1.__dict__)
f1.__dict__['a']=3
del f1.a
print(f1.__dict__)
f1.xxxxxx
二次加工標準類型(包裝)
class List(list):#繼承list所有屬性,也可以派生出自己新的,比如append和mid
def append(self,p_object):
'派生自己的append:加上類型檢查'
if not isinstance(p_object,int):
rasie TypeError('must be int')
super().apppend(p_object)
@property
def mid(self):
'新增自己的屬性'
index = len(self)//2
return self[index]
l = List([1,2,3,4])
print(l)
l.append(5)
print(l)
#l.append('11212132') #報錯,必須為int類型
print(l.mid)
#其余方法都繼承list的
l.insert(0,-1233)
print(l)
l.clear()
print(l)
實現授權的關鍵點就是覆蓋__getattr__方法
import time
class FileHndle:
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):
return getattr(self.file,item)
f1 = FileHandle('b.txt','w+')
f1.write('hello')
f1.seek(0)
print(f1.read())
f1.close()
#我們來加上b模式支持
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
if 'b' in mode:
self.file = open(filename,mode)
else:
self.file = open(filename,mode,encoding = encoding)
self.filename=filename
self.mode = mode
self.encoding = encoding
def write(self,line):
if 'b' in self.mode:
if not isinstance(line,bytes):
raise TypeError('must be bytes')
self.file.write(line)
def __getattr__(self,item):
return getattr(self.file,item)
def __str__(self):
if 'b' in self.mode:
res="<_io.BufferedReader name='%s'>" %self.filename
else:
res="<_io.TextIOWrapper name='%s' mode='%s' encoding='%s'>" %(self.filename,self.mode,self.encoding)
return res
f1=FileHandle('b.txt','wb')
# f1.write('你好啊啊啊啊啊') #自定制的write,不用在進行encode轉成二進制去寫了,簡單,大氣
f1.write('你好啊'.encode('utf-8'))
print(f1)
f1.close()
?
作業:
基于授權定制自己的列表類型,要求定制的自己的__init__方法,
定制自己的append:只能向列表加入字符串類型的值
定制顯示列表中間那個值的屬性(提示:property)
其余方法都使用list默認的(提示:__getattr__加反射)
class List:
def __init__(self,seg):
self.seq = seq
def append(self,p_object):
'派生加上類型檢查'
if not isinstance(p_object,str):
raise TypeError('must be str')
self.seq.append(p_object)
@property
def mid(self):
'新增方法'
index = len(self.seq)//2
return self.seq[index]
def __getattr__(self,item):
return getattr(self.seq,item)
def __str__(self):
return str(self.seq)
l = List(['1','2','3'])
print(l)
l.append(4)
print(l)
?