包装和授权
# 包装和授权
# 包装的过程:一个类型通常是对已存在的类型的一些定制,
# 这种做法可以新建,修改或删除原有产品的功能,其它的则保持原样。
# 授权是包装的一个特性。
# 授权的过程:所有更新的功能都是由新类的某部分来处理,
# 但已存在的功能就授权给对象的默认属性。
# 授权的过程:所有更新的功能都是由新类的某部分来处理,
# 但已存在的功能就授权给对象的默认属性。
#
# 应用: 定制自己的数据类型:
# 1.继承的方式
# 2.授权的方式
举个例子
# 举个例子
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()
# 练习一:重写自定制列表的append和insert方法
class List(list):
def append(self,object:str):
if not isinstance(object,int):
raise TypeError("must int")
super().append(object)
def insert(self, index: int, object):
if not isinstance(object,int):
raise TypeError("must int")
super().insert(index,object)
l=List([1,2,3])
print(l)
# [1, 2, 3]
l.append(4) #会调用类本身的append方法
print(l)
# [1, 2, 3, 4]
# l.append("hello") 我们重写了append方法,要求他只能接受int
# raise TypeError("must int")
l.insert(0,-1) #第一个0是索引,必需是int,第二个规定是int
# l.insert(0,"hello") #报错,因为我们重写了增加和插入方法,非int类型插入报错,必须是int类型
print(l)
# [-1, 1, 2, 3, 4]
# 练习二:根据需求自定制列表
# 练习:
# 定制自己的列表类型,要求定制的自己的__init__方法,
# 定制自己的append:只能向列表加入字符串类型的值
# 定制显示列表中间那个值的属性(提示:property)
# 其余方法都使用list默认的,比如insert()可以插入数字(提示:__getattr__加反射)
# 练习二
class List:
def __init__(self, seq):
self.seq = seq
def append(self, p_object):
' 派生自己的append加上类型检查,覆盖原有的append'
if not isinstance(p_object, str):
raise TypeError('must be str')
else:
self.seq.append(p_object)
@property
def mid(self):
'新增自己的方法'
index = len(self.seq) // 2
return self.seq[index]
# 没有该属性时候的处理方式,自动调用__getattr__,自动调用原列表insert方法
# 注意此处,因为是对象的属性是self,但是getattr里面的是自己定制的init,self.seq,否则造成递归
def __getattr__(self, item):
print("传入__getattr__:",self.seq,item)
return getattr(self.seq, item)
# 造成递归
# def __getattr__(self, item):
# return getattr(self,item)
def __str__(self):
return str(self.seq)
x = ['h', 'e', 'l', 'l']
l = List(x)
print(l)
# ['h', 'e', 'l', 'l']
# 实现取特定数据类型的添加
l.append('o')
print(l)
# ['h', 'e', 'l', 'l', 'o']
# 实现取中间值方法
print(l.mid)
# l
# 其余方法用默认的,比如insert
l.insert(0, -123)
print(l)
# 传入__getattr__: ['h', 'e', 'l', 'l', 'o'] insert 列表序列和方法
# [-123, 'h', 'e', 'l', 'l', 'o']
练习三:权限与列表
# 练习三
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 __setattr__(self, key, value):
if not self.permission:
raise PermissionError('not allow the operation')
else:
self.__dict__[key] = value
def __setattr__(self, key, value):
if not isinstance(value, str):
raise TypeError("must be str")
self.__dict__[key] = value
def __delattr__(self, item):
self.__dict__.pop()
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)