zoukankan      html  css  js  c++  java
  • python 面向对象2

    面向对象的迭代器协议

    class Foo:
        def __init__(self,n):
            self.n = n
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.n == 13:
                raise StopIteration("终止了")
            self.n += 1
            return self.n
    
    f1 = Foo(10)
    # print(f1.__next__())
    # print(f1.__next__())
    # print(f1.__next__())
    # print(f1.__next__())
    
    for i in f1:        #obj=iter(f1) ------> f1.__iter__()   for循环会自动捕捉到终止条件
        print(i)        #obj.__next__()
    
    1 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
    __get__():调用一个属性时,触发
    __set__():为一个属性赋值时,触发
    __delete__():采用del删除属性时,触发

    2 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)

    3 描述符分两种
    一 数据描述符:至少实现了__get__()和__set__()
    二 非数据描述符:没有实现__set__()

    4 注意事项:
    一 描述符本身应该定义成新式类,被代理的类也应该是新式类
    二 必须把描述符定义成另一个类的类属性,不能为定义到构造函数中
    三 要严格遵循该优先级,优先级由高到底分别是
    1.类属性
    2.数据描述符
    3.实例属性
    4.非数据描述符
    5.找不到的属性触发__getattr__()
    class Foo:   #描述符
        def __get__(self, instance, owner):
            print("__get__")
    
        def __set__(self, instance, value):
            print("__set__")
    
        def __delete__(self, instance):
            print("__delete__")
    
    class Bar:
        x = Foo()  #描述了x属性
        def __init__(self,n):
            self.x = n
    
    #触发描述符
    b1 = Bar(10)      #触发描述符的set方法
    print(b1.__dict__)  #空字典
    
    print(Bar.__dict__)
    
    b1.x   #触发描述符的get方法
    
    del b1.x #触发描述符的delete方法
    

    描述符的应用

    #描述符
    class Type:
        def __get__(self, instance, owner):      #instance是被描述的类的实例,就是p1
            print("__get__方法")
            print("instance参数[ %s ]"%instance)
            print("owner参数[ %s ]" % owner)
    
        def __set__(self, instance, value):
            print("__set__方法")
            print("instance参数[ %s ]" % instance)
            print("value参数[ %s ]" % value)
    
        def __delete__(self, instance):
            print("__delete__方法")
            print("instance参数[ %s ]" % instance)
    
    
    class People:
        name = Type()   #描述了name 属性
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    p1 = People("tom",18)  #执行描述符的set方法
    
    print("---->>>>>",p1)
    
    p1.name   #执行描述符的get方法
    
    p1.name = "liaoboshi"   #执行描述符的set方法
    
    print(p1.__dict__)    #没有name这个属性,因为描述符的方法没有返回值
    

     描述符的应用

    #描述符
    class Type:
        def __init__(self,key,expected_type):
            self.key = key
            self.expected_type = expected_type
    
        def __get__(self, instance, owner):      #instance是被描述的类的实例,就是p1
            print("__get__方法")
            return instance.__dict__[self.key]
    
        def __set__(self, instance, value):
            print("__set__方法")
            if not isinstance(value,self.expected_type):   #检测传进来的类型
                raise TypeError(" %s 你传入的类型不是 %s"%(self.key,self.expected_type))
            instance.__dict__[self.key] = value
    
        def __delete__(self, instance):
            print("__delete__方法")
            instance.__dict__.pop(self.key)
    
    
    class People:
        name = Type("name",str)   #描述了name 属性(描述符要传2个参数)
        age = Type("age",int)     #描述了age 属性(描述符要传2个参数)
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    p1 = People("tom",18)
    # p2 = People(213,18) #报错,name传入的类型必须是字符串型
    

    类的装饰器

    def deco(obj):
        print("========>",obj)    #obj就是Foo类本身
    
        obj.x = 1111111
        obj.y = 2222222
        return obj
    
    @deco    # Foo=deco(Foo)
    class Foo:
        pass
    
    print(Foo.__dict__)   #属性字典里有x 和 y 属性
    

     类的装饰器

    def Typed(**kwargs):
        def deco(obj):
            for key,val in kwargs.items():
                setattr(obj,key,val)
    
            return obj
    
        return deco
    
    @Typed(x=1,y=2,z=3)  #@Typed(x=1,y=2,z=3) --->@deco  ---> Foo=deco(Foo)
    class Foo:
        pass
    
    print(Foo.__dict__)
    
    
    @Typed(name="tom")  #@Typed(name="tom") --->@deco  ---> Foo=deco(Foo)
    class Bar:
        print()
    
    print(Bar.name)
    

    类的装饰器的应用

    #描述符
    class Type:
        def __init__(self,key,expected_type):
            self.key = key
            self.expected_type = expected_type
    
        def __get__(self, instance, owner):      #instance是被描述的类的实例,就是p1
            print("__get__方法")
            return instance.__dict__[self.key]
    
        def __set__(self, instance, value):
            print("__set__方法")
            if not isinstance(value,self.expected_type):   #检测传进来的类型
                raise TypeError(" %s 你传入的类型不是 %s"%(self.key,self.expected_type))
            instance.__dict__[self.key] = value
    
        def __delete__(self, instance):
            print("__delete__方法")
            instance.__dict__.pop(self.key)
    
    
    def deco(**kwargs):  #kwargs={"name":str,"age":int}
        def wrapper(obj): #obj=People
            for key,val in kwargs.items(): #(("name",str),("age",int))
                setattr(obj,key,Type(key,val))   #setattr(People,"name",Type("name",str))
    
            return obj
    
        return wrapper
    
    @deco(name=str,age=int)   #@deco(name=str,age=int)  ===>   @wrapper ===>People=wrapper(People)
    class People:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    p1 = People("tom",18)
    
    利用描述符自定制property
    class Lazyproperty:
        def __init__(self,funy):  #funy ==>area
            print("=====>",funy)
            self.funy = funy
    
        def __get__(self, instance, owner):
            if instance is None:
                return self
            res = self.funy(instance)
            return res
    
    class Room:
        def __init__(self,name,width,length):
            self.name = name
            self.width = width
            self.length = length
    
        # @property
        @Lazyproperty     # area= Lazyproperty(area)
        def area(self):
            return self.width * self.length
    
    r1 = Room("厕所",1,1)
    print(r1.area)
    print(r1.__dict__)
    
    
    
    
    
    class Lazyproperty:
        def __init__(self,funy):  #funy ==>area
            print("=====>",funy)
            self.funy = funy
    
        def __get__(self, instance, owner):
            if instance is None:
                return self
            res = self.funy(instance)
    
            setattr(instance,self.funy.__name__,res)   #把返回值加到属性字典里
    
            return res
    
    class Room:
        def __init__(self,name,width,length):
            self.name = name
            self.width = width
            self.length = length
    
        # @property
        @Lazyproperty     # area= Lazyproperty(area)
        def area(self):
            return self.width * self.length
    
    r1 = Room("厕所",1,1)
    print(r1.area)
    print(r1.__dict__)
    
    
    

     上下文管理协议

    class Open:
        def __init__(self,name):
            self.name = name
    
        def __enter__(self):
            print("执行了__enter__")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("执行了__exit__")
    
    
    with Open("a.txt") as f:      #执行这一行的时候,会自动调用__enter__方法
        print(f)         # f 就是Open类产生的对象
        print(f.name)     #with as 里面的代码执行完的时候,会自动调用__exit__方法
    
    print("------------------>>>>>>>>")
    
    
    
    
    class Open:
        def __init__(self,name):
            self.name = name
    
        def __enter__(self):
            print("执行了__enter__")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("执行了__exit__")
            print(exc_type)     #没有异常输出None,有就输出异常的类型
            print(exc_val)    #没有异常输出None,有就输出异常的值
            print(exc_tb)     #没有异常输出None,有就输出traceback
            return True      #返回True,吞掉异常
    
    with Open("a.txt") as f:      #执行这一行的时候,会自动调用__enter__方法
        print(f)          # f 就是Open类产生的对象
        print(dsafsfsf)  #异常的情况下,会执行__exit__,如果返回True,会吞掉异常,执行with as 外面的代码,
                         # 如果返回不是Ture,吐出异常,不会执行with as 外面的代码,报错
        print(f.name)     #with as 里面的代码执行完的时候,会自动调用__exit__方法
    
    print("------------------>>>>>>>>")
    

    metaclass

    1 class Foo:
    2     pass
    3 
    4 f1=Foo() #f1是通过Foo类实例化的对象
    

    python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)

    上例可以看出f1是由Foo这个类产生的对象,而Foo本身也是对象,那它又是由哪个类产生的呢?

    1 #type函数可以查看类型,也可以用来查看对象的类,二者是一样的
    2 print(type(f1)) # 输出:<class '__main__.Foo'>     表示,obj 对象由Foo类创建
    3 print(type(Foo)) # 输出:<type 'type'> 
    

    2 什么是元类?

    元类是类的类,是类的模板

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

    元类的实例为类,正如类的实例为对象(f1对象是Foo类的一个实例Foo类是 type 类的一个实例)

    type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象

    3 创建类的两种方式

    方式一:

    1 class Foo:
    2     def func(self):
    3         print('from func')
    

     方式二:

    1 def func(self):
    2         print('from func')
    3 x=1
    4 Foo=type('Foo',(object,),{'func':func,'x':1})
    

     4 一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类(顺便我们也可以瞅一瞅元类如何控制类的创建,工作流程是什么)

    class Mytype(type):
        def __init__(self,what,bases=None,dict=None):
            print(what,bases,dict)
    
        def __call__(self, *args, **kwargs):
            print('--->')
            obj=object.__new__(self)
            self.__init__(obj,*args,**kwargs)
            return obj
    class Room(metaclass=Mytype):
        def __init__(self,name):
            self.name=name
    
    r1=Room('alex')
    print(r1.__dict__)
    
    自定制元类精简版
    
     
     
  • 相关阅读:
    python常用库
    python多线程
    python内存泄漏
    用python实现js语言里的特性
    nginx + uwsgi
    mysql语句
    urllib模块
    提取数据xpath,re,css
    selenium模块
    脱壳
  • 原文地址:https://www.cnblogs.com/liaoboshi/p/6223357.html
Copyright © 2011-2022 走看看