• 上下文管理协议和元类


    上下文管理协议和元类

    返回首页

    item系列:

    把对象操作属性模拟成字典的格式。

     #把对象操作属性模拟成字典的格式
    class Foo:
        def __init__(self,name):
            self.name=name
        def __setattr__(self, key, value):
            print('setattr===>')
        def __getitem__(self, item):
            # print('getitem',item)
            return self.__dict__[item]
        def __setitem__(self, key, value):
            print('setitem-----<')
            self.__dict__[key]=value
        def __delitem__(self, key):
            self.__dict__.pop(key)
            # self.__dict__.pop(key)
        # def __delattr__(self, item):
        #     print('del obj.key时,我执行')
        #     self.__dict__.pop(item)
    
    f=Foo('George')
    f.name='Wang'
    f['name']='George'
    # print(f.name)
    # f.name='George'
    # f['age']=18
    # print(f.__dict__)
    #
    # del f['age'] #del f.age
    # print(f.__dict__)
    # print(f['name'])

    __slots__方法:对象不会去建立新的名称空间,这样可以节省内存。但是它会限制使用属性,所以它的使用场景是一个类要产出多个固定的属性的时候,这时就可以用__slots__来统一管理了。 

    class People:
        x=1
        def __init__(self,name):
            self.name=name
    
        def run(self):
            pass
    
    print(People.__dict__)  #查看People的属性
    p=People('alex')
    print(p.__dict__)
    
    
    class People:
        __slots__=['x','y','z']
    
    p=People()
    print(People.__dict__)
    
    p.x=1
    p.y=2
    p.z=3
    print(p.x,p.y,p.z)
    # print(p.__dict__)
    
    p1=People()
    p1.x=10
    p1.y=20
    p1.z=30
    print(p1.x,p1.y,p1.z)
    print(p1.__dict__)

    实现迭代器协议

    from collections import Iterable,Iterator
    class Foo:
        def __init__(self,start):
            self.start=start
    
        def __iter__(self):
            return self
    
        def __next__(self):
            return 'aSB'
    
    f=Foo(0)
    # f.__iter__()  #有__iter__就是可迭代的
    # f.__next__()  #有__next__就是迭代器
    
    print(isinstance(f,Iterable))
    print(isinstance(f,Iterator))
    print(next(f)) #f.__next__()
    print(next(f)) #f.__next__()
    print(next(f)) #f.__next__()
    
    for i in f: #先执行__iter__方法,变成迭代器,然后就可以__next__, res=f.__iter__() #__iter__得到的就是自己self #next(res)
        print(i)

    例如:

    ######有一个初始值,每次自加一
    from collections import Iterable,Iterator
    class Foo:
        def __init__(self,start):
            self.start=start
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.start > 10:
                raise StopIteration
            n=self.start
            self.start+=1
            return n
    
    f=Foo(0)
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    # print(next(f))
    for i in f:
        print('====>',i)

    模拟range:

    class Range:
        '123'
        def __init__(self,start,end):
            self.start=start
            self.end=end
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.start == self.end:
                raise StopIteration
            n=self.start
            self.start+=1
            return n
    
    for i in Range(0,3):
        print(i)
    
    print(Range.__doc__)

    析构函数: __del__,在__del__中定义一些清理操作。比如关闭。

    import time
    class Open:
        def __init__(self,filepath,mode='r',encode='utf-8'):
            self.f=open(filepath,mode=mode,encoding=encode)
    
        def write(self):
            pass
    
        def __getattr__(self, item):
            return getattr(self.f,item)
    
        def __del__(self):
            print('----->del')
            self.f.close()
    
    f=Open('a.txt','w')
    f1=f  #f1=f时,先执行print("=====>")的操作,在去执行def f
    del f
    print('=========>')

    上下文管理协议

    # with open('a.txt','r') as f:
    #     print('--=---->')
    #     print(f.read())
    
    # with open('a.txt', 'r'):
    #     print('--=---->')
    
    class Foo:
        def __enter__(self):
            print('=======================》enter')
            return 111111111111111
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('exit')
            print('exc_type',exc_type)
            print('exc_val',exc_val)
            print('exc_tb',exc_tb)
            return True
    
    # with Foo(): #res=Foo().__enter__()
    #     pass
    
    with Foo() as obj: #res=Foo().__enter__() #obj=res  #with Foo() as obj是将with Foo()的结果给obj。
        print('with foo的自代码块',obj)
        raise NameError('名字没有定义')
        print('************************************')
    
    print('1111111111111111111111111111111111111111')

    实现上下文管理协议

    class Open:
        def __init__(self,filepath,mode,encode='utf-8'):
            self.f=open(filepath,mode=mode,encoding=encode)
            self.filepath=filepath
            self.mode=mode
            self.encoding=encode
    
        def write(self,line):
            print('write')
            self.f.write(line)
    
        def __getattr__(self, item):
            return getattr(self.f,item)
    
        def __enter__(self):
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.f.close()
            return True
    
    with Open('aaaaa.txt','w') as write_file: #write_file=Open('aaaaa.txt','w')
        write_file.write('123123123123123
    ')
        write_file.write('123123123123123
    ')
        #print(sssssssssssssss)
        write_file.write('123123123444123123
    ')

    call方法:

    对象后面加括号,触发执行。

    注:构造方法的执行是由创建对象触发的,即:对象=类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class People:
        def __init__(self,name):
            self.name=name
    
        def __call__(self, *args, **kwargs):
            print('call')
    
    p=People('George')
    print(callable(People))
    print(callable(p))
    p() #加call方法会直接触发call方法的运行,打印call

    元类:元类是类的类,是类的模板。

    元类是用来控制如何创建类的,正如类是创建对象的模板一样。

    # class People:
    #     def __init__(self,name):
    #         self.name=name
    #
    # p=People('egon')
    # print(type(p))
    # print(type(People))
    #####typer产生类,类产生对象。
    
    # class Foo:
    #     x=1
    #     def run(self):
    #         pass
    # print(type(Foo))
    
    #####type成为元类,是所有类的类,利用type模拟class关键字的创建类的过程
    def run(self):
        print('%s is runing' %self.name)
    
    class_name='Bar'  #类的名字
    bases=(object,)   #类的继承关系
    class_dic={       #类的属性字典
        'x':1,
        'run':run
    }
    print(class_dic)
    Bar=type(class_name,bases,class_dic)
    print("Bar",Bar)
    print(type(Bar))

    自定制元类:

    class Mymeta(type):  #Mymeta继承type这个元类
        def __init__(self,class_name,class_bases,class_dic):
            # print(self)
            # print(class_name)
            # print(class_bases)
            # print(class_dic)
            for key in class_dic:
                if not callable(class_dic[key]):continue
                if not class_dic[key].__doc__:
                    raise TypeError('小子,你没写注释,赶紧去写')
            # type.__init__(self,class_name,class_bases,class_dic)
    
    class Foo(metaclass=Mymeta):  #metaclass=Mymeta是指定元类
        x=1
        def run(self):
            'run function'
            print('running')
    
    # Foo=Mymeta('Foo',(object,),{'x':1,'run':run})  #实例化
    print(Foo.__dict__)
    
    
    class Mymeta(type):
         def __init__(self,class_name,class_bases,class_dic):
                pass
         def __call__(self, *args, **kwargs):
            print(self)
            obj=self.__new__(self)
            self.__init__(obj,*args,**kwargs) #obj.name='egon'
            return obj
    class Foo(metaclass=Mymeta):
        x=1
        def __init__(self,name):
            self.name=name #obj.name='egon'
        def run(self):
            'run function'
            print('running')
            
    print(Foo.__dict__)
    f=Foo('egon')
    print(f)
    print(f.name)

    ------- END -------

  • 相关阅读:
    [置顶] Objective-C,/,ios,/iphone开发基础:分类(category,又称类别)
    23个移动app界面上的旋钮和刻度盘设计示例
    com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: SELECT command denied to user’
    山沟沟里的实业路(3)
    挨踢江湖之十九
    如何用Python从本地将一个文件备份到Google Drive
    SQL Server 索引和表体系结构(包含列索引)
    UVa 263
    C语言之基本算法40—字符串删除元音字母倒序输出
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(1)
  • 原文地址:https://www.cnblogs.com/george92/p/14662869.html
Copyright © 2020-2023  润新知