7-6 如何使用描述符对实例属性做类型检查

一、描述符包含__get__、__set__或__delete__三个方法中的一个就是描述符。类似于7-4中的property类,内部也是实现了这三个方法。

class Descriptor(object):
    def __get__(self,instance,cls):
        print('in __get__ ',instance,cls )

    def __set__(self,instace,cls):
         print('in __set__ ',instance,cls )

    def __delete__(self,instace,cls):
         print('in __delete__ ',instance,cls )
#在另一个类中定义一个类的属性是描述符的实例时,A这个的一个实例a对这个属性x进行操作时,会被描述符里的结果所截获
class A(object):
    x = Descriptor()   

a = A()

a.x        #用实例a调用属性,instance传入的是类A,实际上现在x不是a的属性,返回的是instance的__dict__[]字典的元素
A.x        #直接用类调用属性,instance传入的是none 
print(a.__dict__)

结果输出:

('in __get__ ', <__main__.A object at 0x02727A90>, <class '__main__.A'>)
('in __get__ ', None, <class '__main__.A'>)
{}        #输出结果为空,说明x不是a的属性

二、使x成为a的属性

class Descriptor(object):
    def __get__(self,instance,cls):
        print('in __get__ ',instance,cls )
        return instance.__dict__['x']

    def __set__(self,instance,value):
        print('in __set__ ' )
        instance.__dict__['x'] = value   #用动态绑定属性添加到类中

    def __delete__(self,instance):
         print('in __delete__ ',instance )


class A(object):
    x = Descriptor()

a = A()

a.x = 5       #注意必须要先赋值才能使用。类似于定义对象时要先赋值是同理
#A.x
print(a.__dict__)

输出结果:

in __set__ 
{'x': 5}

三、一个判断属性类型的例子

class Attr(object):
    def __init__(self,name,type_):
        self.name = name;
        self.type_ = type_
    def __get__(self,instance,cls):
        #print('in __get__ ',instance,cls )
        return instance.__dict__[self.name]

    def __set__(self,instance,value):
        if not isinstance(value,self.type_):   #使用isinstance()判断类型
            raise TypeError("except a %s" %self.type_)
        #print('in __set__ ' )
        instance.__dict__[self.name] = value

    def __delete__(self,instance):
         #print('in __delete__ ',instance )
         del instance.__dict__[self.name]


class Person(object):
    name = Attr('name',str)
    age = Attr('age',int)
    height = Attr('height',float)

lilei = Person()

lilei.name = 'lilei'
lilei.age = 18
lilei.height = 1.80

print(lilei.name,lilei.age,lilei.height)

结果输出:

('lilei', 18, 1.8)
zhang = Person()

#zhang.name = 89
zhang.age = "zhangliang"
输出结果:
Traceback (most recent call last):
  File "C:/视频/python高效实践技巧笔记/7类与对象相关话题/descriptor7-6.py", line 39, in <module>
    zhang.age = "zhangliang"
  File "C:/视频/python高效实践技巧笔记/7类与对象相关话题/descriptor7-6.py", line 13, in __set__
    raise TypeError("except a %s" %self.type_)
TypeError: except a <type 'int'>

 

posted on 2018-05-08 15:30  石中玉smulngy  阅读(175)  评论(0)    收藏  举报

导航