isinstance(obj,cls)和issubclass(sub,super)
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)
反射
反射:通過字符串映射到對象的屬性
class BlackMedium:feature='Ugly'def __init__(self,name,addr):self.name=nameself.addr=addrdef sell_house(self):print('%s 黑中介賣房子啦,傻逼才買呢,但是誰能證明自己不傻逼' %self.name)def rent_house(self):print('%s 黑中介租房子啦,傻逼才租呢' %self.name)b1=BlackMedium('萬成置地','回龍觀天露園')#檢測是否含有某屬性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))#獲取屬性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()# getattr(b1,'aaaaaaaa') #報錯
print(getattr(b1,'aaaaaaaa','不存在啊'))#設置屬性
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__)
setattr,delattr,getattr方法
用法
class Foo: #Dictdef __init__(self,name):self.name=namedef __getitem__(self, item): #item='namexxx'# print('getitem...')return self.__dict__.get(item)def __setitem__(self, key, value):# print('setitem...')# print(key,value)self.__dict__[key]=valuedef __delitem__(self, key):# print('delitem...')# print(key)del self.__dict__[key]
T = Foo('alex')
# print(T.__dict__)
#查,會觸發getitem的運行
print(T['name'])
#改,會觸發setitem的運行
T['name'] = 'Alex'
print(T['name'])
#刪除,會觸發detitem的運行
del T['name']
print(T['name'])
str,repr,format
改變對象的字符串顯示__str__,repr
自定制格式化字符串__format__
format_dict={'nat':'{obj.name}-{obj.addr}-{obj.type}',#學校名-學校地址-學校類型'tna':'{obj.type}:{obj.name}:{obj.addr}',#學校類型:學校名:學校地址'tan':'{obj.type}/{obj.addr}/{obj.name}',#學校類型/學校地址/學校名
}
class School:def __init__(self,name,addr,type):self.name=nameself.addr=addrself.type=typedef __repr__(self):return 'School(%s,%s)' %(self.name,self.addr)def __str__(self):return '(%s,%s)' %(self.name,self.addr)def __format__(self, format_spec):# if format_specif not format_spec or format_spec not in format_dict:format_spec='nat'fmt=format_dict[format_spec]return fmt.format(obj=self)s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)'''
str函數或者print函數--->obj.__str__()
repr或者交互式解釋器--->obj.__repr__()
如果__str__沒有被定義,那么就會使用__repr__來代替輸出
注意:這倆方法的返回值必須是字符串,否則拋出異常
'''
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))
自定format方法:
dic_time = {'ymd':'{0.year}:{0.month}:{0.day}','dmy':'{0.day}/{0.month}/{0.year}','myd':'{0.month}--{0.year}--{0.day}',
}class Date:def __init__(self,year,month,day):self.year = yearself.month = monthself.day = daydef __format__(self, format_spec):if not format_spec or format_spec not in dic_time:format_spec = 'ymd'fmt = dic_time[format_spec]return fmt.format(self)
d1 = Date(2018,3,22)
print(format(d1))
print('{:dmy}'.format(d1))
del方法
析構方法,當對象在內存中被釋放時,自動觸發執行
注:如果產生的對象僅僅只是python程序級別的(用戶級),那么無需定義__del__,如果產生的對象的同時還會向操作系統發起系統調用,即一個對象有用戶級與內核級兩種資源,比如(打開一個文件,創建一個數據庫鏈接),則必須在清除對象的同時回收系統資源,這就用到了__del__。
class Open:def __init__(self,filename):print('open file.......')self.filename=filenamedef __del__(self):print('回收操作系統資源:self.close()')f=Open('settings.py')
# del f #f.__del__()
print('----main------') #del f #f.__del__()
二次加工標準類型(包裝)
包裝:python為大家提供了標準數據類型,以及豐富的內置方法,其實在很多場景下我們都需要基于標準數據類型來定制我們自己的數據類型,新增/改寫方法,這就用到了我們剛學的繼承/派生知識(其他的標準類型均可以通過下面的方式進行二次加工
二次加工標準類型(基于繼承實現)
class List(list): #繼承list所有的屬性,也可以派生出自己新的,比如append和middef append(self, p_object):' 派生自己的append:加上類型檢查'if not isinstance(p_object,int):raise TypeError('must be int')super().append(p_object)@propertydef mid(self):'新增自己的屬性'index=len(self)//2return self[index]l=List([1,2,3,4])
print(l)
l.append(5)
print(l)
# l.append('1111111') #報錯,必須為int類型print(l.mid)#其余的方法都繼承list的
l.insert(0,-123)
print(l)
l.clear()
print(l)
練習(clear加權限限制)
class List(list):def __init__(self,item,tag=False):super().__init__(item)self.tag=tagdef append(self, p_object):if not isinstance(p_object,str):raise TypeErrorsuper().append(p_object)def clear(self):if not self.tag:raise PermissionErrorsuper().clear()l=List([1,2,3],False)
print(l)
print(l.tag)l.append('saf')
print(l)# l.clear() #異常l.tag=True
l.clear()
```py
授權:授權是包裝的一個特性, 包裝一個類型通常是對已存在的類型的一些定制,這種做法可以新建,修改或刪除原有產品的功能。其它的則保持原樣。授權的過程,即是所有更新的功能都是由新類的某部分來處理,但已存在的功能就授權給對象的默認屬性。
實現授權的關鍵點就是覆蓋__getattr__方法
#**授權示范一**
import time
class FileHandle: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('你好啊')
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=filenameself.mode=modeself.encoding=encodingdef 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.filenameelse: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()
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">