组合的方式完成授权
1、包装是在之前原有的方法的基础上,在做一点改动,这叫包装,就像包装那个append方法
现在我们来做一个open方法
class Open: def __init__(self,filename,mode="r",encoding="utf8"): self.filename=filename self.mode=mode self.encoding=encoding def __getattr__(self, item): print(item) f1=Open("a.txt","r") f1.read C:\python35\python3.exe D:/pyproject/day26/授权.py read
2、啥都没做,那我们来改动一下
现在就创建了一个a.txt
class Open: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 self.mode=mode self.encoding=encoding def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 print(item) f1=Open("a.txt","w")#f1传给self a.txt传给filename w 传给mode print(f1.file) f1.read#此时read并不存在,所以触发了__getattr__ C:\python35\python3.exe D:/pyproject/day26/授权.py <_io.TextIOWrapper name='a.txt' mode='w' encoding='utf8'> read
3、再改善一下
class Open: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 #self.file里面调用了系统的open方法,封装成了自己的open方法,具有系统的open方法的所有特性 self.mode=mode self.encoding=encoding def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 return getattr(self.file,item)#self.file-->f1.file item-->"read" f1=Open("a.txt","w")#f1传给self a.txt传给filename w 传给mode print(f1.file) print(f1.read)#此时read并不存在 C:\python35\python3.exe D:/pyproject/day26/授权.py <_io.TextIOWrapper name='a.txt' mode='w' encoding='utf8'> <built-in method read of _io.TextIOWrapper object at 0x000000000057EA68>
4、我们看下我们自己的这个read跟系统的open方法的read是不是一个东西
class Open: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 #self.file里面调用了系统的open方法,封装成了自己的open方法,具有系统的open方法的所有特性 self.mode=mode self.encoding=encoding def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 return getattr(self.file,item)#self.file-->f1.file item-->"read" f1=Open("a.txt","w")#f1传给self a.txt传给filename w 传给mode print(f1.file) print(f1.read)#获取我们的实例的自己写的read方法,但是实例里面没有,类里面也没有,最终触发了getattr sys_f=open("b.txt","w+") print(getattr(sys_f,"read"))#获取系统的open的read方法 C:\python35\python3.exe D:/pyproject/day26/授权.py <_io.TextIOWrapper name='a.txt' mode='w' encoding='utf8'> <built-in method read of _io.TextIOWrapper object at 0x000000000055EA68> <built-in method read of _io.TextIOWrapper object at 0x000000000055EB40>
5、现在f.write也能调用了。read你会调用了write也是一样的呀,实例里面没有,类里面也没有,最终触发了getattr,getattr里面是调用的系统的open方法里面的write。所以肯定是可以的
class FileHandle: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 #self.file里面调用了系统的open方法,封装成了自己的open方法,具有系统的open方法的所有特性 self.mode=mode self.encoding=encoding def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 return getattr(self.file,item)#self.file-->f1.file item-->"read" f1=FileHandle("a.txt","r+")#f1传给self a.txt传给filename w 传给mode print(f1.read)#获取我们实例自己写的read方法,但是实例里面没有,类里面也没有,最终触发了getattr print(f1.write) C:\python35\python3.exe D:/pyproject/day26/授权.py <built-in method read of _io.TextIOWrapper object at 0x00000000005AEA68> <built-in method write of _io.TextIOWrapper object at 0x00000000005AEA68>
6、我们执行一下write操作看看能不能写入到文件里面
结果是a.txt里面成功写入了,现在就牛逼了。我们发现我们的实例f1是通过FileHandle这个方法进行write的,并不是系统的open的方法里面的write属性,是经过了getattr中转了一下。
class FileHandle: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 #self.file里面调用了系统的open方法,封装成了自己的open方法,具有系统的open方法的所有特性 self.mode=mode self.encoding=encoding def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 return getattr(self.file,item)#self.file-->f1.file item-->"read" f1=FileHandle("a.txt","r+")#f1传给self a.txt传给filename w 传给mode print(f1.read)#获取我们实例自己写的read方法,但是实例里面没有,类里面也没有,最终触发了getattr f1.write("1111111\n")
7、我们seek一下,再读一下,到这一步,我们发现,相当于open的所有的方法都传递过来了,都可以正常使用了,上一个是学的包装,继承和派生完成的包装,继承是父类由什么我就继承过来,现在到这里就相当于把open里面的方法继承过来了
class FileHandle: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 #self.file里面调用了系统的open方法,封装成了自己的open方法,具有系统的open方法的所有特性 self.mode=mode self.encoding=encoding def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 return getattr(self.file,item)#self.file-->f1.file item-->"read" f1=FileHandle("a.txt","r+")#f1传给self a.txt传给filename w 传给mode f1.write("123456\n") f1.seek(1) print(f1.read()) C:\python35\python3.exe D:/pyproject/day26/授权.py 23456
8、上面完成了读操作了,还没有完成写操作呢
实例再调用wirte的方法的时候,先在实例的属性字典里面找,然后去类的属性字典里面找,找不到的话才会触发getattr,所以我们想完成写操作,就在类里面定义一个write的方法就行了,当实例调用的时候会先从类里面找到write就直接执行了
class FileHandle: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 #self.file里面调用了系统的open方法,封装成了自己的open方法,具有系统的open方法的所有特性 self.mode=mode self.encoding=encoding def write(self,line): print("自己的类里面的定义的write",line) def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 return getattr(self.file,item)#self.file-->f1.file item-->"read" f1=FileHandle("a.txt","w+")#f1传给self a.txt传给filename w 传给mode f1.write("123456\n") f1.seek(1) print(f1.read()) C:\python35\python3.exe D:/pyproject/day26/授权.py 自己的类里面的定义的write 123456
现在这个write就是调用的自己在类里面定义的那个write方法了,并没有真实的写入到文件中去,而且单纯的打印了一下东西
9、如何实现文件的真正的写操作呢
class FileHandle: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 #self.file里面调用了系统的open方法,封装成了自己的open方法,具有系统的open方法的所有特性 self.mode=mode self.encoding=encoding def write(self,line): # print("自己的类里面的定义的write",line) self.file.write(line) def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 return getattr(self.file,item)#self.file-->f1.file item-->"read" f1=FileHandle("a.txt","w+")#f1传给self a.txt传给filename w 传给mode f1.write("123456\n")#把f1传给self,把123456传给line f1.seek(1) print(f1.read()) C:\python35\python3.exe D:/pyproject/day26/授权.py 23456
10、给文件内容的前面每行都加上时间
import time class FileHandle: def __init__(self,filename,mode="r",encoding="utf8"): # self.filename=filename self.file=open(filename,mode,encoding=encoding)#得到的是一个文件句柄 #self.file里面调用了系统的open方法,封装成了自己的open方法,具有系统的open方法的所有特性 self.mode=mode self.encoding=encoding def write(self,line): # print("自己的类里面的定义的write",line) t=time.strftime("%Y-%m-%d %X")#定义时间格式 self.file.write("%s %s" %(t,line))#进行字符串拼接 def __getattr__(self, item):#当实例调用的属性不存在的时候触发它 return getattr(self.file,item)#self.file-->f1.file item-->"read" f1=FileHandle("a.txt","w+")#f1传给self a.txt传给filename w 传给mode f1.write("123456\n")#把f1传给self,把123456传给line f1.write("234567\n") f1.write("789123\n") 2018-06-20 22:37:13 123456 2018-06-20 22:37:13 234567 2018-06-20 22:37:13 789123
这种就是组合的方式,给self.file赋予了一个文件描述符,然后利用__getattr__来return所有正常的open里面的所有的属性,如果我们不自己定制write的方法的话,所有的方法就已经是跟系统的方法一样了,但是我们自己定制了write的方法了,给前面加了时间,当然也可以做其他的,比如直接pass,那其他人在调用write的方法的时候就写入不了了