zoukankan      html  css  js  c++  java
  • 对于传入的参数做类型检测,(类型注解)

      1 # 在init之前做判断,但是耦合度太高
      2 class Person:
      3     def __init__(self, name:str, age:int):
      4         params = ((name, str), (age, int))
      5         if not self.typecheck(params):
      6             raise TypeError
      7         self.name = name
      8         self.age = age
      9 
     10     def typecheck(self, params):
     11         for p, t in params:
     12             if not isinstance(p, t):
     13                 return False
     14         return True
     15 
     16 使用装饰器,使用inspect模块完成
     17 
     18 import inspect
     19 
     20 def typecheck(fn):
     21     def wrapper(*args, **kwargs):
     22         sig  = inspect.signature(fn)
     23         params = sig.parameters # OrderedDict([('self', <Parameter "self">), ('name', <Parameter "name: str">), ('age', <Parameter "age: int">)])
     24 
     25         keys = list(params.keys())
     26         print(keys)
     27         values = list(params.values())
     28         print(values)
     29         # 位置参数
     30         for i, v in enumerate(args[1:]):
     31             if type(v) is not (values[1:])[i].annotation:
     32                 raise Exception('-------Different Tyeps')
     33         # 关键字参数
     34         for i, v in kwargs.items(): # i=age, v=12
     35             for key in keys:
     36                 if key == i and params[key].annotation != inspect._empty and type(v) is not params[key].annotation:
     37                     raise Exception('+++++++Different Types')
     38     return wrapper
     39 
     40 class Person:
     41 
     42     @typecheck  # __init__ = typecheck(__init__)
     43     def __init__(self, name:str, age:int=12):
     44         self.name = name
     45         self.age = age
     46 
     47 p = Person('jack', age=12) # 没有键值对的方式
     48 
     49 使用描述器 将属性放到自己的属性字典中
     50 class TypeCheck:
     51     def __init__(self, flag, type):
     52         self.flag = flag
     53         self.type = type
     54 
     55     def __get__(self, instance, owner):
     56         return instance.__dict__[self.flag]
     57 
     58     def __set__(self, instance, value):
     59         if isinstance(value, self.type):
     60             instance.__dict__[self.flag] = value
     61         else:
     62             raise TypeError
     63 
     64 
     65 class Person:
     66     name = TypeCheck('name', str)
     67     age = TypeCheck('age', int)
     68 
     69     def __init__(self, name:str, age:int):
     70         self.name = name
     71         self.age = age
     72 
     73 p = Person('tom', 18)
     74 print(p.name)
     75 print(p.age)
     76 print(p.__dict__)
     77 
     78 使用描述器 将属性放到描述器实例的属性字典中
     79 class TypeCheck:
     80     def __init__(self, flag, type):
     81         self.flag = flag
     82         self.type = type
     83         self.data = {}
     84 
     85     def __get__(self, instance, owner):
     86         # return instance.__dict__[self.flag]
     87         print(self.__dict__)
     88         return self.data[self.flag]
     89 
     90     def __set__(self, instance, value):
     91         if isinstance(value, self.type):
     92             # instance.__dict__[self.flag] = value
     93             self.data[self.flag] = value
     94         else:
     95             raise TypeError
     96 
     97 class Person:
     98     name = TypeCheck('name', str)
     99     age = TypeCheck('age', int)
    100 
    101     def __init__(self, name:str, age:int):
    102         self.name = name
    103         self.age = age
    104 
    105 p = Person('tom', 12)
    106 print(p.name)
    107 print(p.age)
    108 print(p.__dict__)
    109 
    110 上面属于硬编码,将描述器写到 逻辑代码中。
    111 现在将其提取出来,作为装饰器
    112 函数装饰器
    113 class TypeCheck:
    114     def __init__(self, flag, type):
    115         self.flag = flag
    116         self.type = type
    117 
    118     def __get__(self, instance, owner):
    119         return instance.__dict__[self.flag]
    120 
    121     def __set__(self, instance, value):
    122         if isinstance(value, self.type):
    123             instance.__dict__[self.flag] = value
    124         else:
    125             raise TypeError
    126 
    127 import inspect
    128 def typeassert(cls):
    129     sig = inspect.signature(cls)
    130     params = sig.parameters
    131     for flag, value  in params.items():
    132         # cls.__dict__[flag] = TypeCheck(flag, value.annotation) # 只有实例能添加属性到字典中,通过操作字典
    133         if value.annotation != inspect._empty: # 或者,value.empty
    134             setattr(cls, flag, TypeCheck(flag, value.annotation))
    135     return cls
    136 
    137 @typeassert # Person=typeassert(Person)
    138 class Person:
    139     # name = TypeCheck('name', str)
    140     # age = TypeCheck('age', int)
    141     def __init__(self, name:str, age:int):
    142         self.name = name
    143         self.age = age
    144 
    145 p = Person('tom', 18)
    146 print(p.name)
    147 print(p.age)
    148 print(p.__dict__)
    149 
    150 上面属于硬编码,将描述器写到 逻辑代码中。
    151 现在将其提取出来,作为装饰器
    152 类装饰器
    153 
    154 class TypeCheck:
    155     def __init__(self, flag, type):
    156         self.flag = flag
    157         self.type = type
    158 
    159     def __get__(self, instance, owner):
    160         return instance.__dict__[self.flag]
    161 
    162     def __set__(self, instance, value):
    163         if isinstance(value, self.type):
    164             instance.__dict__[self.flag] = value
    165         else:
    166             raise TypeError
    167 
    168 import inspect
    169 class TypeAssert:
    170     def __init__(self, cls):
    171         sig = inspect.signature(cls)
    172         params = sig.parameters
    173         for flag, value  in params.items():
    174             if value.annotation != inspect._empty: # 或者,value.empty
    175                 setattr(cls, flag, TypeCheck(flag, value.annotation))
    176         self.cls = cls
    177 
    178     def __call__(self, *args, **kwargs):
    179         return self.cls(*args, **kwargs)
    180 
    181 @TypeAssert # Person=TypeAssert(Person)
    182 class Person:
    183     def __init__(self, name:str, age:int):
    184         self.name = name
    185         self.age = age
    186 
    187 p = Person('tom', 18)
    188 print(p.__dict__)
    189 print(p.name)
    190 print(p.age)
    191 print(p.__dict__)
    为什么要坚持,想一想当初!
  • 相关阅读:
    Linux进程间通信—消息队列
    Linux进程间通信—信号
    Linux进程间通信—信号量
    Linux进程间通信—管道
    Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字
    安全文件传输系统
    嵌入式mp3播放器
    用C语言实现面向对象的开发
    Haskell 差点儿无痛苦上手指南
    Oracle EBS 入门
  • 原文地址:https://www.cnblogs.com/JerryZao/p/9692972.html
Copyright © 2011-2022 走看看