包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工
#基于继承加派生来实现二次加工标准类型 # 派生原有的list类 class List(list): def append(self, p_object): #自定义一个父类中本来就有的append if type(p_object) is str: #规定只能附加一个字符串 # self.append(p_object) #self自己调用自己的方法,陷入递归死循环当中 super().append(p_object) #用super()更好,等价于list.append(p_object) #调用父类中的append()只要不调用自己的就不会递归死循环 else: print(‘只能添加字符串类型‘) def show_midlle(self): #取列表中的中间的那个值 mid_index=int(len(self)/2) return self[mid_index] l2=list(‘helloworld‘) #原来系统内置的list print(l2,type(l2)) #[‘h‘,‘e‘,‘l‘,‘l‘,‘o‘,‘w‘,‘o‘,‘r‘,‘l‘,‘d‘] <class ‘list‘> l1=List(‘helloworld‘) #用从list继承过来的自己的List print(l1,type(l1)) #[‘h‘,‘e‘,‘l‘,‘l‘,‘o‘,‘w‘,‘o‘,‘r‘,‘l‘,‘d‘] <class ‘_main_.List‘> # l1的类型为当前运行文件下的一个list类 print(l1.show_midlle()) #w l1.append(1111111111111111111111) #非字符串本函数功能不允许,加不成功 #参数会传给p_object l1.append(‘SB‘) #是字符串,能成功加入 print(l1)
授权:授权是包装的一个特性, 不通过继承来做。还是想要定制一个原有的标准类型。
包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。
授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
实现授权的关键点就是覆盖__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()
#_*_coding:utf-8_*_
__author__ = ‘Linhaifeng‘
#我们来加上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()
#练习一
class List:
def __init__(self,seq):
self.seq=seq
def append(self, p_object):
‘ 派生自己的append加上类型检查,覆盖原有的append‘
if not isinstance(p_object,int):
raise TypeError(‘must be int‘)
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)
# l.append(‘3333333‘) #报错,必须为int类型
print(l.mid)
#基于授权,获得insert方法
l.insert(0,-123)
print(l)
#练习二
class List:
def __init__(self,seq,permission=False):
self.seq=seq
self.permission=permission
def clear(self):
if not self.permission:
raise PermissionError(‘not allow the operation‘)
self.seq.clear()
def __getattr__(self, item):
return getattr(self.seq,item)
def __str__(self):
return str(self.seq)
l=List([1,2,3])
# l.clear() #此时没有权限,抛出异常
l.permission=True
print(l)
l.clear()
print(l)
#基于授权,获得insert方法
l.insert(0,-123)
print(l)
原文:https://www.cnblogs.com/Josie-chen/p/8875557.html