• Python开发之路


    1.描述符的应用

    用描述符实行类型检测

    class Dtype:
        def __init__(self,key,expect_type):
            self.key = key 
            self.expect_type = expect_type
    
        def __get__(self, instance, owner):
            return instance.__dict__[self.key]
    
        def __set__(self, instance, value):
            if not isinstance(value,self.expect_type):
                raise TypeError('%s传入的类型有误,应该为%s'%(self.key,self.expect_type))
            instance.__dict__[self.key] = value
    
        def __delete__(self, instance):
            instance.__dict__.pop[self.key]
    class People:
        name = Dtype('name',str)
        age = Dtype('age',int)
        def __init__(self,name,age):
            self.name = name
            self.age = age
    p1 = People('chris','18')
    print(p1.__dict__)

     2.类的装饰器

    def daju(**kwargs):
        def deco(obj):
            for k,v in kwargs.items():
                setattr(obj,k,v)
            return obj
        return deco
    @daju(x=1,y=2)  #先运行daju(x=1,y=2) 返回一个deco 相当于@deco  Foo=deco(Foo) 
    class Foo:
        pass
    print(Foo.__dict__)

    此时实现了 对类的修饰 加入了x,y的属性

    加入对类型的限制:

    class Typed:
        def __init__(self,key,expect_type):
            self.key = key
            self.expect_type = expect_type
        def __set__(self, instance, value):
            if not isinstance(value,self.expect_type):
                raise TypeError('%s输入的类型有误,应为%s类型' %(self.key,self.expect_type))
            instance.__dict__[self.key] = value
    
    
    def deco(**kwargs):  #kwargs 接收到 {'name' = str, 'age' = int, 'salary' = float}
        def wrapper(obj):
            for k,v in kwargs.items():
                print(k,v)
                setattr(obj,k,Typed(k,v))  #设置值时,将K给描述符代理 实现类型限制 既name = Typed('name',str)
                #setattr(Foo,'name',Typed('name',str)) 上面相当于执行这个  Foo.name = Typed('name',str)
            return obj
        return wrapper
    
    @deco(name = str, age = int, salary = float) #装饰器代替了三个重复的代码 实现给Foo类设定属性 只不过这个属性是描述符 对类的类型实现限制
    class Foo:
        # name = Typed('name',str)
        # age = Typed('age',int)
        # salary = Typed('salary',str)
        def __init__(self,name,age,salary):
            self.name = name
            self.age = age
            self.salary = salary
    p1 = Foo('chris',19,25.7)
    print(Foo.__dict__)
    print(p1.__dict__)

    3.利用描述符自定制property

    class Lazyproperty:
        def __init__(self,func):
            self.func = func
            # print('22222')
        def __get__(self, instance, owner):  #实例调用时instance是实例自己 owner 为其所在的类 类调用时instance 为 None owner为类自己
            if instance is None:
                return self
            val = self.func(instance)
            return val
    class Room:
        def __init__(self,name,length,width):
            self.name = name
            self.length = length
            self.width = width
        @Lazyproperty  # area = Lazyproperpy(area) 也是在增加描述符
        def area(self):
            return self.length * self.width
    
    r1 = Room('厕所',18,23)
    print(Room.area)
    print(r1.area)
    print(r1.area)
    print(r1.area)

     !!!此时实例调用area方法时会触发get方法,get方法中会自动将area算出来的值保存在实例的字典中,又因为Lazyproperty为非数据描述符,优先级低于实例属性,所以下次调用area方法时,会优先从实例属性字典中查找,所以不会触发get方法

    4.自定制property功能实现延迟计算功能:定义set方法使描述符成为数据描述符,因此每次调用时都会从数据描述符中调用get方法

    import  time
    class Lazyproperty:
        def __init__(self,func):
            self.func = func
            # print('22222')
        def __get__(self, instance, owner):  #实例调用时instance是实例自己 owner 为其所在的类 类调用时instance 为 None owner为类自己
            time.sleep(2)
            print('get方法')
            if instance is None:
                return self
            val = self.func(instance)
            setattr(instance,self.func.__name__,val) #将area算出来的结果存放到实例自己的属性名为area的字典当中
            return val
        def __set__(self, instance, value):
            pass
    class Room:
        def __init__(self,name,length,width):
            self.name = name
            self.length = length
            self.width = width
        @Lazyproperty  # area = Lazyproperpy(area) 也是在增加描述符
        def area(self):
            return self.length * self.width
    
    r1 = Room('厕所',18,23)
    print(r1.area)
    print(r1.area)
    print(r1.area)

     5.利用描述符自定制一个classmethod

    class ClassMethod:
        def __init__(self,func):
            self.func=func
    
        def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
            def feedback(*args,**kwargs):
                print('在这里可以加功能啊...')
                return self.func(owner,*args,**kwargs)
            return feedback
    
    class People:
        name='linhaifeng'
        @ClassMethod # say_hi=ClassMethod(say_hi)
        def say_hi(cls,msg):
            print('你好啊,帅哥 %s %s' %(cls.name,msg))
    
    People.say_hi('你是那偷心的贼')
    
    p1=People()
    p1.say_hi('你是那偷心的贼')
    

    6.property补充 为静态属性设置值时用的。setter方法 删除静态属性值时 用.deleter方法

    class Foo:
        @property
        def AAA(self):
            print('get的时候运行我啊')
    
        @AAA.setter
        def AAA(self,value):
            print('set的时候运行我啊')
    
        @AAA.deleter
        def AAA(self):
            print('delete的时候运行我啊')
    
    #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
    f1=Foo()
    f1.AAA
    f1.AAA='aaa'
    del f1.AAA
    或者
    lass Foo:
        def get_AAA(self):
            print('get的时候运行我啊')
    
        def set_AAA(self,value):
            print('set的时候运行我啊')
    
        def delete_AAA(self):
            print('delete的时候运行我啊')
        AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应
    
    f1=Foo()
    f1.AAA
    f1.AAA='aaa'
    del f1.AAA
    复制代码

    应用场景如下:

    class Goods:
    
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        @property
        def price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
    
        @price.setter
        def price(self, value):
            self.original_price = value
    
        @price.deleter
        def price(self):
            del self.original_price
    
    
    obj = Goods()
    obj.price         # 获取商品价格
    obj.price = 200   # 修改商品原价
    print(obj.price)
    del obj.price     # 删除商品原价
    View Code

    7.元类

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

    type是pyhton的一个内建元类,用来直接控制生成类

    FFo = type('Foo',(object,),{'x':1}) # 用type创建类 第一个参数为类名,第二个参数为继承的类,新式类默认加个object,第三个参数是属性

    模拟元类帮你生成对象的过程:可以自己控制实例化的过程 定制自己的逻辑

    class Mytype(type):
        def __init__(self,a,b,c):
            print('这是我的元类')
    
        def __call__(self, *args, **kwargs):
            obj = object.__new__(self) ##产生一个Foo的对象 self就是Foo
            self.__init__(obj,*args,**kwargs) #为Foo生成的对象的字典里加属性
            return obj
    class Foo(metaclass=Mytype):  #相当于MYtype('Foo',(object),{}) 传过去四个参数
        def __init__(self,name):
            self.name = name
    f1 = Foo('chris')  #相当于在执行Mytype的call方法
  • 相关阅读:
    Filter 过滤器
    struts2 action接收请求参数和类型转换
    Struts2入门学习
    struts2请求参数校验
    IntelliJ IDEA 使用心得与常用快捷键
    关于动态代理详解
    web.xml文件详解
    关于mysql插入数据异常
    关于控制台输出 警告 log4j:WARN No appenders could be found for logger
    Hive load from hdfs 出错
  • 原文地址:https://www.cnblogs.com/caixiaowu/p/12421427.html
Copyright © 2020-2023  润新知