zoukankan      html  css  js  c++  java
  • 描述符__get__(),__set__(),__delete__()(三十七)

    http://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12

    描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
    __get__():调用一个属性时,触发
    __set__():为一个属性赋值时,触发
    __delete__():采用del删除属性时,触发

    定义一个描述符
    class Foo: #在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
        def __get__(self, instance, owner):
            pass
        def __set__(self, instance, value):
            pass
        def __delete__(self, instance):
            pass
    View Code

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

    #描述符Str
    class Str:
        def __get__(self, instance, owner):
            print('Str调用')
        def __set__(self, instance, value):
            print('Str设置...')
        def __delete__(self, instance):
            print('Str删除...')
    
    #描述符Int
    class Int:
        def __get__(self, instance, owner):
            print('Int调用')
        def __set__(self, instance, value):
            print('Int设置...')
        def __delete__(self, instance):
            print('Int删除...')
    
    class People:
        name=Str()
        age=Int()
        def __init__(self,name,age): #name被Str类代理,age被Int类代理,
            self.name=name
            self.age=age
    
    #何地?:定义成另外一个类的类属性
    
    #何时?:且看下列演示
    
    p1=People('alex',18)
    '''
    Str设置...
    Int设置...
    '''
    
    # #描述符Str的使用
    p1.name # Str调用
    p1.name='zhangsan' # Str设置...
    del p1.name # Str删除...
    #
    # #描述符Int的使用
    p1.age # Int调用
    p1.age=18 # Int设置...
    del p1.age # Int删除...
    
    # #我们来瞅瞅到底发生了什么
    print(p1.__dict__) # {}
    print(People.__dict__) # {'__weakref__': <attribute '__weakref__' of 'People' objects>,
                            # '__dict__': <attribute '__dict__' of 'People' objects>, '__doc__': None,
                            # '__init__': <function People.__init__ at 0x0000013E94AC5E18>, '__module__': '__main__',
                # 'name': <__main__.Str object at 0x0000013E94AD81D0>, 'age': <__main__.Int object at 0x0000013E94AD8198>}
    
    
    # #补充
    print(type(p1) == People) #type(obj)其实是查看obj是由哪个类实例化来的 True
    print(type(p1).__dict__ == People.__dict__) # True
    View Code
    #描述符Str
    class Str:
        def __get__(self, instance, owner):
            print('Str调用')
        def __set__(self, instance, value):
            print('Str设置...')
            instance.__dict__['name'] = value
        def __delete__(self, instance):
            print('Str删除...')
    
    #描述符Int
    class Int:
        def __get__(self, instance, owner):
            print('Int调用')
        def __set__(self, instance, value):
            print('Int设置...')
            instance.__dict__['age'] = value
        def __delete__(self, instance):
            print('Int删除...')
    
    class People:
        name=Str()
        age=Int()
        def __init__(self,name,age): #name被Str类代理,age被Int类代理,
            self.name=name
            self.age=age
    
    p1=People('alex',18)
    print(p1.__dict__) # {'name': 'alex', 'age': 18}
    View Code

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

     class Foo:
         def __set__(self, instance, value):
             print('set')
         def __get__(self, instance, owner):
             print('get')

    非数据描述符:没有实现__set__()

    class Foo:
         def __get__(self, instance, owner):
             print('get')

      注意事项:

    一 描述符本身应该定义成新式类,被代理的类也应该是新式类
    二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
    三 要严格遵循该优先级,优先级由高到底分别是
    1.类属性
    2.数据描述符
    3.实例属性
    4.非数据描述符
    5.找不到的属性触发__getattr__()

    #描述符Str
    class Str:
        def __init__(self,key):
            self.key = key
        def __get__(self, instance, owner):
            print('Str调用')
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print('Str设置...')
            if type(value) is not str:
                raise TypeError("类型错误")
            instance.__dict__[self.key] = value
        def __delete__(self, instance):
            print('Str删除...')
            instance.__dict__.pop(self.key)
    
    #描述符Int
    class Int:
        def __init__(self,key):
            self.key = key
        def __get__(self, instance, owner):
            print('Int调用')
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print('Int设置...')
            if type(value) is not int:
                raise TypeError("请输入int型")
            instance.__dict__['age'] = value
        def __delete__(self, instance):
            print('Int删除...')
            instance.__dict__.pop(self.key)
    
    class People:
        name=Str("name")
        age=Int("age")
        def __init__(self,name,age): #name被Str类代理,age被Int类代理,
            self.name=name
            self.age=age
    
    p1=People("zhangsan",18)
    print(p1.__dict__) # {'age': 18, 'name': 'zhangsan'}
    print(p1.age)
    del p1.age
    print(p1.__dict__) # {'age': 18}

    上面代码改进:

    class Typed:
        def __init__(self,key, expected_type):
            self.key = key
            self.expected_type = expected_type
        def __get__(self, instance, owner):
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            if not isinstance(value, self.expected_type):
                raise TypeError("%s is not %s" %(value, self.expected_type))
            instance.__dict__[self.key] = value
        def __delete__(self, instance):
            instance.__dict__.pop(self.key)
    
    class People:
        name=Typed("name", str)
        age=Typed("age", int)
        def __init__(self,name,age): #name被Str类代理,age被Int类代理,
            self.name=name
            self.age=age
    
    #p1=People(99,18) # TypeError: 99 is not <class 'str'>
    p1=People("zhangsan",'18') # TypeError: 18 is not <class 'int'>
  • 相关阅读:
    iuplua test failure
    lua C++ wrapper
    lua
    Redux系列01:从一个简单例子了解action、store、reducer
    Meteor入门介绍
    Express入门介绍vs实例讲解
    React半科普文
    Express模版引擎hbs备忘
    Gulp:插件编写入门
    gulp.src()内部实现探究
  • 原文地址:https://www.cnblogs.com/xiangtingshen/p/10463924.html
Copyright © 2011-2022 走看看