【问题标题】:Decorator for cheking any function annotation type用于检查任何函数注释类型的装饰器
【发布时间】:2018-11-30 07:16:24
【问题描述】:

我想设计一个装饰器来检查任何函数注释类型,如果它具有相似的类型,则运行函数。 python可以做这样的事情吗? 如果python可以,请帮帮我!!

def foo (a:int):
    if foo.__annotations__.get('a') == type(a):
        pass

def boo (b:str):
    if boo.__annotations__.get('b') == type(b):
        pass

另一件事是注释是一个字典类型,我想要这样:

from type import FunctionType
def check (f:FunctionType):
    result = True
    k = [k for k in f.__annotations__.keys()]
    v = [v for v in f.__annotations__.values()]
    for i in range(len(v)):
        if v[i] != type(k[i]): #but we don't access to the type of k[i] out of th f function
            result = False
    return result       

【问题讨论】:

    标签: python decorator


    【解决方案1】:

    如果我正确理解了这个想法,也许这段代码会对你有所帮助:

    from types import FunctionType
    
    def check(f: FunctionType):
        def wrapper(*args, **kwargs):
            result = True
    
            # check args
            keys = tuple(f.__annotations__.keys())
            for ar in enumerate(args):
                if not isinstance(ar[1], f.__annotations__.get(keys[ar[0]])):
                    result = False
                    break
    
            if result:
                # check kwargs
                for k, v in kwargs.items():
                    if not isinstance(v, f.__annotations__.get(k)):
                        result = False
                        break
    
            if result:
                f(*args, **kwargs)
    
        return wrapper
    

    示例用法:

    @check
    def foo(a: str, b: int = None):
        print(f"a  = {a}")
        print(f"b  = {b}")
    
    
    # Example 1: a=324, b=32:
    foo(234, b=32)
    # result: function not executed
    
    # Example 2: a="abc", b="zzz":
    foo("abc", b="zzz")
    # result: function not executed
    
    # Example 3: a="qwe", b= not set:
    foo("qwe")
    # result: function executed, output:
    # a  = qwe
    # b  = None
    
    # Example 4: a="abc", b=99:
    foo("abc", 99)
    # result: function executed, output:
    # a  = abc
    # b  = 99
    

    装饰器检查参数类型,如果一切正常,则执行函数,否则不执行任何操作。

    【讨论】:

      【解决方案2】:
      import functools
      def annotations_checker(func):
          @functools.wraps(func)
          def wrapper(*args,**kwargs):
              TrueFalseChecker=True
              keys=tuple(func.__annotations__.keys())
              for key_num in range(len(keys)):
                  if func.__annotations__[keys[key_num]]!=type(args[key_num]):
                      break
              else:
                  value=func(*args,*kwargs)
                  return value
              return
      
          return wrapper
      

      您可以使用@annotations_checker 装饰器对任何python 方法/python 函数来检查类型注释 喜欢:

      @annotations_checker
      def test(str_example:str,int_example:int,second_str_example:str):
          print("if you can see this, the args and annonations type are same!") 
      test(1,"2",3) #the function will not work
      test("1",1,"testtest") #function will work
      

      【讨论】:

        【解决方案3】:

        类似的东西。

        import inspect
        import functools
        
        
        def check(func):
            msg = "Expected type {etype} for {para} got {got}"
            para = inspect.signature(func).parameters
            keys = tuple(para.keys())
        
            @functools.wraps(func)
            def wrapper(*args,**kwargs):
                def do_check(anno,value,para):
                    if not isinstance(value, anno):
                        raise TypeError(msg.format(etype=anno,
                            para=para,
                            got=type(value)))
        
                for i,value in  enumerate(args):
                    anno = para[keys[i]].annotation
                    do_check(anno, value, keys[i])
        
                for arg_name,value in  kwargs.items():
                    anno = para[arg_name].annotation
                    do_check(anno, value, arg_name)
        
                ret = func(*args,**kwargs)
                if "return" in func.__annotations__:
                    anno = func.__annotations__["return"]
                    do_check(anno, ret, "return")
                return ret
            return wrapper
        
        @check
        def test(a:int,b:str) -> str:
            return 'aaa'
        
        @check
        def test2(a:int,b:str) -> str:
            return 123
        

        【讨论】:

          猜你喜欢
          • 2022-09-21
          • 2019-12-05
          • 1970-01-01
          • 2013-02-10
          • 2016-08-21
          • 2019-11-13
          • 2022-06-19
          • 2018-01-12
          • 2021-04-14
          相关资源
          最近更新 更多