目录
  • 1、如何使用描述符对实例属性做类型检查?
    • 实际案例:
    • 解决方案:
  • 2、代码演示

    1、如何使用描述符对实例属性做类型检查?

    实际案例:

    在某项目中,我们实现了一些类,并希望能像静态类型语言那样(C,C++,Java)对它们的实例属性做类型检查。

    p = Person()
        p.name = 'Bob'	# 名字属性必须是str
        p.age = 18	        # 年龄必须是int
        p.height = 1.83	# 身高必须是float

    要求:(1)可以对实例变量名指定类型

    (2)赋予不正确类型时抛出异常

    解决方案:

    使用描述符来实现需要类型检查的属性:分别实现__get__, __set__,__delete__方法,在__set__内使用isinstance函数做类型检查。

    拓展:静态类型语言变量只能引用一种确定类型的对象并且不能改变。类型检查是由编译器在编译阶段完成的,对于Python动态类型语言来讲一个变量可以引用任意类型的对象并且可以实时发生改变,也就是解释器不能完成类型检查,只能自己去实现。

    什么是描述符?描述符就是包含__get__, __set__,__delete__这样方法的类,这三个方法只要包含其中一个那它就是描述符。

    实例属性就是在一个类中将另一个类的实例作为该类的一个数属性。

    2、代码演示

    (1)描述符定义和访问流程介绍

    class Descriptor(object):
        def __get__(self, instance, cls):
            # instance用于区分使用类访问x,还是使用实例访问x
            print('in __get__', instance, cls)
            return instance.__dict__['x']
        def __set__(self, instance, value):
            # 在set中对于类型进行检查
            print('in __set__')
            instance.__dict__['x'] = value
        def __delete__(self, instance):
            print('in __del__')
    class A(object):
        # 在类中定义一个类属性x
        x = Descriptor()
    a = A()
    # 会被Descriptor的__get__方法所截获
    print(a.x)
    # 直接使用类A访问类属性,instance会被传入None
    print(A.x)
    # 会被Descriptor的__set__方法所截获
    a.x = 5
    # 会被Descriptor的__del__方法所截获
    del a.x
    '''
    通常来说在描述符这些方法当中访问的是instance.__dict__这个字典,
    也就是对于它的真正属性进行操作。
    '''
    a = A()
    a.x = 5
    print(a.__dict__)

    (2)实现使用描述符检查实例属性类型

    class Attr(object):
        def __init__(self, name, type_):
            self.name = name
            self.type_ = type_
        def __get__(self, instance, cls):
            return instance.__dict__[self.name]
        def __set__(self, instance, value):
            # 对字段类型做检测
            if not isinstance(value, self.type_):
                raise TypeError('expected an %s' % self.type_)
            instance.__dict__[self.name] = value
        def __delete__(self, instance):
            del instance.__dict__[self.name]
    class Person(object):
        # 定义一个name字段,申请描述符实例
        name = Attr('name', str)
        age = Attr('age', int)
        height = Attr('height', float)
    p = Person()
    p.name = 'Bob'
    print(p.name)
    # age赋值字符串类型抛出异常错误
    # p.age = '17'
    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。