zoukankan      html  css  js  c++  java
  • python之装饰器强制函数上的类型检查

    问题:通过装饰器想对函数参数进行强制类型检查,并且指定所有参数类型,也可以指定部分参数类型

    未装饰的函数:

    def spam(x, y, z=42):
        print(x,y,z)
    
    spam('hello',1) #hello 1 42

    写装饰器前,运用到了inspect中的signature签名函数,signature()获取函数的参数签名信息

    sig = signature(spam)
    print(sig) #(x, y, z=42)
    
    print(type(sig.parameters['x'].name)) #<class 'str'>
    print(type(sig.parameters)) #<class 'mappingproxy'>
    print(sig.parameters.items()) #odict_items([('x', <Parameter "x">), ('y', <Parameter "y">), ('z', <Parameter "z=42">)])
    bind_partial() 方法来执行从指定类型到名称的部分绑定:
    bound_types = sig.bind_partial(int,str,z=int) #允许忽略任何参数(int,z=int)
    print(bound_types) #<BoundArguments (x=<class 'int'>, z=<class 'int'>)>
    print(bound_types.arguments) #OrderedDict([('x', <class 'int'>), ('z', <class 'int'>)])
    print(bound_types.arguments['x']) #<class 'int'>

    bind() 跟bind_partial() 类似,但是它不允许忽略任何参数:

    bound_values = sig.bind(1,2,3) #不允许忽略任何参数
    print(bound_values) #<BoundArguments (x=1, y=2, z=3)>
    print(bound_values.arguments) #OrderedDict([('x', 1), ('y', 2), ('z', 3)])

    了解完这些之后,开始实现该装饰器了~

    下面是使用装饰器技术来实现 @typeassert

    from inspect import signature
    from functools import wraps
    
    def typeassert(*ty_args,**ty_kwargs):
        def decorate(func):
            if not __debug__:
                return func
    
            sig = signature(func)
            bound_types = sig.bind_partial(*ty_args,**ty_kwargs).arguments
    
            @wraps(func)
            def wrapper(*args,**kwargs):
                bound_values = sig.bind(*args,**kwargs)
    
                for name,value in bound_values.arguments.items():
                    if name in bound_types:
    
                        if not isinstance(value,bound_types[name]):
                            raise TypeError('Argument {} must be {}'.format(name,bound_types[name]))
                return func(*args,**kwargs)
    
            return wrapper
        return decorate
    
    @typeassert(str,z=int)
    def spam(x, y, z=42):
        print(x,y,z)
    
    spam(1,'ds','www') #TypeError: Argument x must be <class 'str'>
     
  • 相关阅读:
    Pycharm简单使用教程
    【Jenkins学习】【第二节】 jenkins构建触发器定时任务
    Docker之从零开始制作docker镜像
    手机APP自动化环境搭建
    格式字符详解
    Bash Shell之内建命令和保留字
    asp.net 实现后台异步处理的方式
    Spring3.2.0 之后各个版本完整包下载地址
    Oracle的rollup、cube、grouping sets函数
    C# 委托类型及使用
  • 原文地址:https://www.cnblogs.com/Kerryworld/p/11905764.html
Copyright © 2011-2022 走看看