zoukankan      html  css  js  c++  java
  • Python装饰器实现函数动态类型检查

    函数动态类型检查的装饰器代码

    import inspect
    import functools
    
    def typeHints(fn):
        @functools.wraps(fn)
        def wrap(*args, **kwargs):
            sig = inspect.signature(fn)
            params = sig.parameters
            # 处理kwargs:字典
            for k, v in kwargs:
                param = params[k]
                if param.annotation != inspect._empty and not isinstance(v, param.annotation):
                    raise TypeError('parameter {} requires {}, but got {}'.format(k, param.annotation, type(v)))
            # 处理args:元组
            for i, x in enumerate(args):
                param = list(params.values())[i]
                if param.annotation != inspect._empty and not isinstance(x, param.annotation):
                    raise TypeError('parameter {} requires {}, but got {}'.format(param.name, param.annotation, type(x)))
            ret = fn(*args, **kwargs)
            return ret
        return wrap
    
    
    @typeHints
    def add(x: int, y: int) -> int:
        return x + y
    
    @typeHints
    def add1(x, y:int) -> int:
        return x + y
    
    print(add(3, 5))	# 输出结果为8
    print(add1(1, 2))	# 输出结果为3
    

    类型检查主要使用了inspect库。本次代码运行环境是python3.5.2。inspect库的使用方法在下面介绍。

    inspect模块

    检查函数动态类型时,我们主要使用的是inspect库中的signature类,parameter类。可以使用help方法查看inspect的详细信息:

    import inspect
    help(inspect)
    

    inspect库的源代码见:/home/clg/.pyenv/versions/3.5.2/lib/python3.5/inspect.py

    这个库用来获取Python动态对象的有用信息,比如本次用到的注解。

    Signature类

    Signature是inspect模块的一个类,inspect模块的signature函数用来获取一个Signature对象,函数原型如下:

    signature() - get a Signature object for the callable

    Signature类有一个属性是OrderedDict类型的parameters,存储的是参数名称到参数对象(Parameter类的对象)的一个有序映射。

    Parameter类

    Parameter类的对象主要用来组成signature()返回的Signature对象的parameters属性。Parameter类有两个常用的属性:

    • name :str 参数的名称
    • annotation 参数的注解,如果没有注解,则annotation为Parameter.empty

    inspect模块示例

    def add(x: int, y: int) -> int:
        return x + y
    
    import inspect
    sig = inspect.signature(add)
    print(sig.parameters)
    print(sig.parameters['x'])
    print(sig.parameters.values())
    
    # 输出结果
    OrderedDict([('x', <Parameter "x:int">), ('y', <Parameter "y:int">)])
    x:int
    odict_values([<Parameter "x:int">, <Parameter "y:int">])
    

    odict_values类似于list,但是不支持下表操作,因此需要用list()转化为list之后再做下表操作。


    记得帮我点赞哦!

    精心整理了计算机各个方向的从入门、进阶、实战的视频课程和电子书,按照目录合理分类,总能找到你需要的学习资料,还在等什么?快去关注下载吧!!!

    resource-introduce

    念念不忘,必有回响,小伙伴们帮我点个赞吧,非常感谢。

    我是职场亮哥,YY高级软件工程师、四年工作经验,拒绝咸鱼争当龙头的斜杠程序员。

    听我说,进步多,程序人生一把梭

    如果有幸能帮到你,请帮我点个【赞】,给个关注,如果能顺带评论给个鼓励,将不胜感激。

    职场亮哥文章列表:更多文章

    wechat-platform-guide-attention

    本人所有文章、回答都与版权保护平台有合作,著作权归职场亮哥所有,未经授权,转载必究!

  • 相关阅读:
    了解AOP
    Struts2 拦截器与Spring AOP的区别
    Spring核心技术之IoC和AOP
    产品经理历险记-2-如何把需求聊得更细
    产品经理历险记-1-记录一次事故
    C# 使用 Lotus notes 公共邮箱发送邮件
    设计模式 5/23 原型模式
    设计模式 4/23 建造者模式
    设计模式 3/23 抽象工厂模式
    设计模式 2/23 工厂模式(二)
  • 原文地址:https://www.cnblogs.com/CHLL55/p/13757575.html
Copyright © 2011-2022 走看看