zoukankan      html  css  js  c++  java
  • Day 28 类的用法延伸

    ###上下文管理协议,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法,即在类中添加__enter__, __exit__方法

    class Open:

        def __init__(self,name):

            self.name=name

        def __enter__(self):

            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')

            # return self

        def __exit__(self, exc_type, exc_val, exc_tb):

            print('with中代码块执行完毕时执行我啊')

            # return True

    with Open('a.txt') as f:  #Open('a.txt’)相当于对象实例化,with Open('a.txt') 触发__enter__运行,__enter__的返回值赋值给f

        print('=====>执行代码块')

        print(f.xxxxx) #当执行不存在的,触发__exit__,若return True则吞掉异常,若return值不为True则吐出异常

    __exit__的运行完毕就代表了整个with语句的执行完毕

    ###实现控制实例化数据类型

    class Type:

        def __init__(self,key,expected_type):

            self.key=key

            self.expected_type=expected_type

        def __get__(self, instance, owner):

            print("触发get")

            return instance.__dict__[self.key]

        def __set__(self, instance, value): #此处的selfType对应的实例,instancePeople对应的实例

            print("触发set")

            if not isinstance(value,self.expected_type):

                raise TypeError

            instance.__dict__[self.key]=value

        def __delete__(self, instance):

            print('触发delete')

            instance.__dict__.pop(self.key)

    class People:

        name=Type('name',str)

        age=Type('age',int)

        def __init__(self,name,age):

            self.name=name

            self.age=age

    p1=People("xyy",19) #触发set

    print(p1.name)

    print(p1.__dict__)

    del p1.name

    #####类的装饰器的基本原理

    def deco(obj):

        obj.x=1

        obj.y=2

        obj.z=3

        return obj

    @deco  # Foo=deco(Foo)

    class Foo:

        pass

    print(Foo.__dict__) # 查看x,y,z

    ####用类装饰器按不同的类里添加属性

    def Typed(**kwargs):

        def deco(obj):

            print("------------->",kwargs)

            for key,val in kwargs.items():

                setattr(obj,key,val)

            return obj

        print("==============>",kwargs)

        return deco

    @Typed(x=1,y=2,z=3)   # @Typed(x=1,y=2,z=3)>>>@deco

    class Foo:

        pass

    print(Foo.__dict__) #查看x,y,z

    @Typed(name="xyy")

    class Bar:

        pass

    print(Bar.__dict__)

    ################

    ######装饰器是函数时

    class Room:

        def __init__(self,length,width,hight):

            self.length=length

            self.width=width

            self.hight=hight

        @property #area=property(area)相当于给类添加数据属性

        def area(self):

            return self.width*self.length

        @property

        def v(self):

            return self.area*self.hight

    r1=Room(2,3,5)

    print(r1.area)

    print(r1.v)

    print(Room.__dict__)#查看areav

    ######装饰器是类时,自定制(模拟)property

    class Diyproperty:

        def __init__(self,func):

            print("-------->执行Diyproperty",func)

            self.func=func

        def __get__(self, instance, owner):

            print("---->触发get")

            res=self.func(instance)

            return res

    class Room:

        """在类Diyproperty里添加get属性,@Diyproperty即相当于描述符

        area=Diyproperty(area),因此func=area"""

        def __init__(self,length,width,hight):

            self.length=length

            self.width=width

            self.hight=hight

        @Diyproperty #area=Diyproperty(area)相当于实例化,触发Diyproperty的__init__的运行。同时相当于给Room类添加数据属性,在Room的数学字典里key"area" 对应value"Diyproperty(area)"

        def area(self):

            print("-------执行area")

            return self.width*self.length

        @Diyproperty

        def volume(self):

            print("-------执行volume")

            return self.area*self.hight

    r1=Room(2,3,5)

    # print("面积是:",r1.area)

    # print(r1.area.func(r1))   #手动运行,最好不这么做

    print("体积是:",r1.volume) #触发描述符的__get__方法

    # print(Room.__dict__)   #查看areav

    ##############解决用类调用描述符的__get__方法时返回None的问题

    class Diyproperty:

        def __init__(self,func):

            print("-------->执行Diyproperty",func)

            self.func=func

        def __get__(self, instance, owner):

            print("---->触发get")

            if instance is None#用类调用描述符触发

                return self  

            res = self.func(instance)

            return res

    class Room:

        """在类Diyproperty里添加get属性,@Diyproperty即相当于描述符

        area=Diyproperty(area),因此func=area"""

        def __init__(self,length,width,hight):

            self.length=length

            self.width=width

            self.hight=hight

        @Diyproperty #area=Diyproperty(area)相当于实例化,触发Diyproperty__init__的运行。同时相当于给Room类添加数据属性,在Room的数学字典里key"area" 对应value"Diyproperty(area)"

        def area(self):

            print("-------执行area")

            return self.width*self.length

    r1=Room(2,3,5)

    print(Room.area) #当类调用描述符的__get__属性时返回None。故需用if instance is None:进行判断

    #########关于property的补充

    #第一种方法

    class Foo:

        @property

        def AAA(self):

            print("执行AAA")

        @AAA.setter

        def AAA(self,val):

            print("执行set")

        @AAA.deleter

        def AAA(self):

            print("执行delete")

    p1=Foo()

    p1.AAA="xyy"

    print(p1.__dict__)

    # del p1.AAA

    #第二种方法

    class Foo:

        def get_AAA(self):

            print("执行get")

        def set_AAA(self,val):

            print("执行set",val)

        def del_AAA(self):

            print("执行delete")

        AAA=property(get_AAA,set_AAA,del_AAA) #顺序不能变,此处property相当于做了一件描述符的事

    p1=Foo()

    p1.AAA

    p1.AAA="xyy"

    print(p1.__dict__)

    del p1.AAA

    >>>

    执行get

    执行set xyy

    {}

    执行delete

    ######元类

    元类的实例为类,类的实例为对象

    type是python的一个内建元类

    两种定义类的方式:

    class定义类

    type('类名',(object,),{key1:value1,})

    声明元类:metaclass=type

    #########自定制元类,查看参数

    class DiyType(type):

        def __init__(self,a,b,c):

            print("元类的构造函数执行")

            print(a)

            print(b)

            print(c)

    class Foo(metaclass=DiyType): #DiyType(Foo,’Foo’,(),{}),触发DiyTypeinit运行返回结果Foo

        """metaclass用来声明元类"""

        def __init__(self,name):

            self.name=name

    >>>

    元类的构造函数执行

    Foo

    ()

    {'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x11434b1e0>}

    ###上下文管理协议,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法,即在类中添加__enter__, __exit__方法

    class Open:

        def __init__(self,name):

            self.name=name

        def __enter__(self):

            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')

            # return self

        def __exit__(self, exc_type, exc_val, exc_tb):

            print('with中代码块执行完毕时执行我啊')

            # return True

    with Open('a.txt') as f:  #Open('a.txt’)相当于对象实例化,with Open('a.txt') 触发__enter__运行,__enter__的返回值赋值给f

        print('=====>执行代码块')

        print(f.xxxxx) #当执行不存在的,触发__exit__,若return True则吞掉异常,若return值不为True则吐出异常

    __exit__的运行完毕就代表了整个with语句的执行完毕

    ###实现控制实例化数据类型

    class Type:

        def __init__(self,key,expected_type):

            self.key=key

            self.expected_type=expected_type

        def __get__(self, instance, owner):

            print("触发get")

            return instance.__dict__[self.key]

        def __set__(self, instance, value): #此处的selfType对应的实例,instancePeople对应的实例

            print("触发set")

            if not isinstance(value,self.expected_type):

                raise TypeError

            instance.__dict__[self.key]=value

        def __delete__(self, instance):

            print('触发delete')

            instance.__dict__.pop(self.key)

    class People:

        name=Type('name',str)

        age=Type('age',int)

        def __init__(self,name,age):

            self.name=name

            self.age=age

    p1=People("xyy",19) #触发set

    print(p1.name)

    print(p1.__dict__)

    del p1.name

    #####类的装饰器的基本原理

    def deco(obj):

        obj.x=1

        obj.y=2

        obj.z=3

        return obj

    @deco  # Foo=deco(Foo)

    class Foo:

        pass

    print(Foo.__dict__) # 查看x,y,z

    ####用类装饰器按不同的类里添加属性

    def Typed(**kwargs):

        def deco(obj):

            print("------------->",kwargs)

            for key,val in kwargs.items():

                setattr(obj,key,val)

            return obj

        print("==============>",kwargs)

        return deco

    @Typed(x=1,y=2,z=3)   # @Typed(x=1,y=2,z=3)>>>@deco

    class Foo:

        pass

    print(Foo.__dict__) #查看x,y,z

    @Typed(name="xyy")

    class Bar:

        pass

    print(Bar.__dict__)

    ################

    ######装饰器是函数时

    class Room:

        def __init__(self,length,width,hight):

            self.length=length

            self.width=width

            self.hight=hight

        @property #area=property(area)相当于给类添加数据属性

        def area(self):

            return self.width*self.length

        @property

        def v(self):

            return self.area*self.hight

    r1=Room(2,3,5)

    print(r1.area)

    print(r1.v)

    print(Room.__dict__)#查看areav

    ######装饰器是类时,自定制(模拟)property

    class Diyproperty:

        def __init__(self,func):

            print("-------->执行Diyproperty",func)

            self.func=func

        def __get__(self, instance, owner):

            print("---->触发get")

            res=self.func(instance)

            return res

    class Room:

        """在类Diyproperty里添加get属性,@Diyproperty即相当于描述符

        area=Diyproperty(area),因此func=area"""

        def __init__(self,length,width,hight):

            self.length=length

            self.width=width

            self.hight=hight

        @Diyproperty #area=Diyproperty(area)相当于实例化,触发Diyproperty的__init__的运行。同时相当于给Room类添加数据属性,在Room的数学字典里key"area" 对应value"Diyproperty(area)"

        def area(self):

            print("-------执行area")

            return self.width*self.length

        @Diyproperty

        def volume(self):

            print("-------执行volume")

            return self.area*self.hight

    r1=Room(2,3,5)

    # print("面积是:",r1.area)

    # print(r1.area.func(r1))   #手动运行,最好不这么做

    print("体积是:",r1.volume) #触发描述符的__get__方法

    # print(Room.__dict__)   #查看areav

    ##############解决用类调用描述符的__get__方法时返回None的问题

    class Diyproperty:

        def __init__(self,func):

            print("-------->执行Diyproperty",func)

            self.func=func

        def __get__(self, instance, owner):

            print("---->触发get")

            if instance is None#用类调用描述符触发

                return self  

            res = self.func(instance)

            return res

    class Room:

        """在类Diyproperty里添加get属性,@Diyproperty即相当于描述符

        area=Diyproperty(area),因此func=area"""

        def __init__(self,length,width,hight):

            self.length=length

            self.width=width

            self.hight=hight

        @Diyproperty #area=Diyproperty(area)相当于实例化,触发Diyproperty__init__的运行。同时相当于给Room类添加数据属性,在Room的数学字典里key"area" 对应value"Diyproperty(area)"

        def area(self):

            print("-------执行area")

            return self.width*self.length

    r1=Room(2,3,5)

    print(Room.area) #当类调用描述符的__get__属性时返回None。故需用if instance is None:进行判断

    #########关于property的补充

    #第一种方法

    class Foo:

        @property

        def AAA(self):

            print("执行AAA")

        @AAA.setter

        def AAA(self,val):

            print("执行set")

        @AAA.deleter

        def AAA(self):

            print("执行delete")

    p1=Foo()

    p1.AAA="xyy"

    print(p1.__dict__)

    # del p1.AAA

    #第二种方法

    class Foo:

        def get_AAA(self):

            print("执行get")

        def set_AAA(self,val):

            print("执行set",val)

        def del_AAA(self):

            print("执行delete")

        AAA=property(get_AAA,set_AAA,del_AAA) #顺序不能变,此处property相当于做了一件描述符的事

    p1=Foo()

    p1.AAA

    p1.AAA="xyy"

    print(p1.__dict__)

    del p1.AAA

    >>>

    执行get

    执行set xyy

    {}

    执行delete

    ######元类

    元类的实例为类,类的实例为对象

    type是python的一个内建元类

    两种定义类的方式:

    class定义类

    type('类名',(object,),{key1:value1,})

    声明元类:metaclass=type

    #########自定制元类,查看参数

    class DiyType(type):

        def __init__(self,a,b,c):

            print("元类的构造函数执行")

            print(a)

            print(b)

            print(c)

    class Foo(metaclass=DiyType): #DiyType(Foo,’Foo’,(),{}),触发DiyTypeinit运行返回结果Foo

        """metaclass用来声明元类"""

        def __init__(self,name):

            self.name=name

    >>>

    元类的构造函数执行

    Foo

    ()

    {'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x11434b1e0>}

  • 相关阅读:
    splice() 的用法
    JAVA 序列化
    对象的组合
    基于SSM框架实现简单的登录注册
    SpringMVC 处理映射
    基于高德地图的位置服务开发(二)
    基于高德地图的位置服务开发(一)
    Spring MVC页面重定向
    Spring MVC
    Spring MVC
  • 原文地址:https://www.cnblogs.com/xuwinwin/p/11663378.html
Copyright © 2011-2022 走看看