组合的方式完成授权

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的方法的时候就写入不了了

posted @ 2018-06-22 21:40  gouguoqi  阅读(257)  评论(0编辑  收藏  举报