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


    需求:
    在某项目中,我们实现了一些类,并希望能像静态语言那样(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函数做类型检查

    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]  # 将self.name变为实例P的属性
    
        def __set__(self,instance,value):
            print('in __set__')
            if not isinstance(value,self.type_):
                raise TypeError('expected an %s' % self.type_)
            instance.__dict__[self.name] = value  # 将self.name变为实例P的属性
    
        def __delete__(self,instance):
            print('in __delete__')
            del instance.__dict__[self.name]
    
    class Person(object):
        name = Attr('name', str)
        age = Attr('age', int)
        height = Attr('height', float)
    
    p = Person()
    p.name = 'Bob'
    print(p.name)
    p.age = '17'
    print(p.age)
    
    ==========================================================
    
    >>> class A:
    ...     pass
    ... 
    >>> a = A()
    >>> # a.x = value
    >>> a.__dict__['x'] = value
    Traceback (most recent call last):
      File "<ipython-input-22-5e039675ed4e>", line 1, in <module>
        a.__dict__['x'] = value
    NameError: name 'value' is not defined
    
    >>> 
    ==================================================================
    class Attr:
        def __init__(self,key,type_):
            self.key = key
            self.type_ = type_
    
        def __set__(self,instance,value):
            print('in __set__')
            if not isinstance(value,self.type_):
                raise TypeError('must be %s' % self.type_)
            instance.__dict__[self.key]= value
    
        def __get__(self,instance,cls):
            print('in __get__',instance,cls)
            return instance.__dict__[self.key]
    
        def __delete__(self,instance):
            print('in __del__',instance)
            del instance.__dict__[self.key]
    
    class Person:
        name = Attr('name',str)
        age = Attr('age',int)
    
    #a = A()
    #a.x = 5
    #a.y = 6
    ##del a.x
    #print(a.x)
    #print(a.y)
    #A.x
    p = Person()
    p.name = 'richardo'
    p.age = '32'
    
    
  • 相关阅读:
    IOS 修改UIAlertController的按钮标题的字体颜色,字号,内容
    UITableView heightForHeaderInSection遇到的坑
    .19-浅析webpack源码之compile流程-rules参数处理(2)
    .18-浅析webpack源码之compile流程-rules参数处理(1)
    .17-浅析webpack源码之compile流程-入口函数run
    .16-浅析webpack源码之编译后流程梳理
    .15-浅析webpack源码之WebpackOptionsApply模块-plugin事件流总览
    .14-浅析webpack源码之Watchpack模块
    .13-浅析webpack源码之WatcherManager模块
    .12-浅析webpack源码之NodeWatchFileSystem模块总览
  • 原文地址:https://www.cnblogs.com/Richardo-M-Q/p/13388316.html
Copyright © 2020-2023  润新知