函数参数注解

参数注解

Python是动态语言,变量随时可以被赋值,且能赋值为不同的另外类型
Python不是静态编译型语言,变量类型是在运行期决定的
动态语言很灵活,但是这种特性也是弊端

def add(x,y):
    return x+y
 print(add(4,5))  #9
 print(add("hello","word"))  # "helloword"

难发现:由于不做任何类型检查,直到运行期问题才显现出来,或者线上运行时才能暴露处问题
难使用:函数的使用者看到函数的时候,并不知道你的函数的设计,并不知道应该传入什么类型的数据

  • 增加文档Documenttation String
    这只是一个惯例,不是强制标准,不能要求程序员一定为函数提供说明文档
    函数定义更新了,文档未必同步更新
def add(x:int,y:int)->int:
'''
:param x:int
:param y:int
:return: int
'''
    return x+y

函数注解Function Annotations

  • python 3.5引入
  • 对函数的参数进行类型注解
  • 对函数的返回值进行类型注解
  • 只对函数参数做一个辅助的说明,并不对函数参数进行类型检查
  • 提供给第三方工具,做代码分析,发现隐藏的bug
  • 函数注解的信息,保存在__annotation__属性中
add.__annotations__
{'x':<class 'int'>,'y':<class 'int'>, 'return'<class 'int'>}  

变量注解python3.6引入 它也只是一种对变量的说明,非强制 i:int = 3

业务应用
函数参数类型检查
思路

  • 函数参数的检查,一定是在函数外,如要把检查代码侵入到函数中
  • 函数应该作为参数,传入到检查函数中
  • 检查函数拿到函数传入的实际参数,与形参声明对比
  • __annotations__是一个字典,其中包括返回值类型的声明.假设要做位置参数的判断,无法和字典中的声明对应 使用inspect模块

inspect模块
提供获取对象信息的函数,可以检查函数和类 类型检查
signature(callable),获取签名(函数签名包含了一个函数的信息,包含函数名,它的参数类型,他所在的类和名称空间及其他信息)

import inspect
def add(x:int,y:int,*args,**keargs)->int:
    return x+y
sig = inspect.signature(add)
print(sig,type(sig)) #函数签名
print(sig.parameters['x'])

inspect.isfunction(add),是否是函数
inspect.ismethod(add),是否是类的方法
还有很多is函数,需要的时候查阅inspect模块帮助

parameter对象

  • 保存在元组中,是只读的
  • name,参数的名字
  • annotation,参数的注解,可能没有定义
  • default,参数的缺省值,可能没有定义
  • empty,特殊的类,用来标记default属性或者注释annotation属性的空值
  • kind,实参如何绑定到形参,就是形参的类型
    POSITIONAL_ONLY,值必须是位置参数提供
    POSITIONAL_OR_KEYWORD,值可以作为关键字或者位置参数提供
    VAR_POSITIONAL,可变位置参数,对应*args
    KEYWORD_ONLY,keyword-noly参数,对应*或者*args之后的出现非可变关键字参数
    VAR_KEYWORD,可变关键字参数,对应**kwargs
import inspect
def add(x,y:int=6 ,*args,z,t=10,**kwargs):
    return x+y
sig = inspect.signature(add)
print(sig)
print('params : ',sig.parameters)    #有序字典
print('return :',sig.return_annotation)
for i,item in enumerate(sig.parameters.items()):
    name,param = item
    print(i+1,name,param.annotation,param.kind,param.default)
    print(param.default is param.empty,end = '\n')
import inspect

def check(fn):
    def wrapper(*args,**kwargs):
        sig = inspect.signature(fn)
        params = sig.parameters
        values = list(params.values())
        for i,p in enumerate(args):
            param = values[i]
            if param.annotation is not inspect._empty and not isinstance(p,param.annotation):
                print(p,'!==',values[i].annotation)
        for k,v in kwargs.items():
            if params[k].annotation is not inspect._empty and not isinstance(v,params[k].annotation):
                print(k,v,'!====',params[k].annotation)
        return fn(*args,**kwargs)
    return wrapper

@check
def add(x,y:int=7)->int:
    return x+y
print(add(10,5))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值