函数定义的弊端:
python是动态语言,变量随时可以被赋值,且能赋值为不同的类型;
python不是静态编译语言,变量类型是在运行器决定的;
动态语言很灵活,但是这种特性也是弊端;
def add(x, y):
return x + y
print(add(4, 5))
print(add('hello', 'world'))
add(4, 'hello')#
难发现:由于不做任何类型检查,直到运行期间问题才显现出来,或者线上运行时才能暴露出问题;
难使用:函数的使用者看到函数的时候,并不知道你的函数的设计,并不知道应该传入什么类型的数据;
如何解决这种动态语言定义的弊端呢?
增加文档Documentation String
这只是一个惯例,不是强制标准,不能要求程序员一定为函数提供说明文档;
函数定义更新了,文档未必同步更新;
def add(x, y):
'''
:param x: int
:param y: int
:return: int
'''
return x + y
print(help(add))
那有没有别的方法呢?
函数注解Function Annotations
def add(x: int, y: int) -> int:
'''
:param x: int
:param y: int
:return: int
'''
return x + y
print(help(add))
print(add('hello', 'world')) ###思考一下这里会报错吗?
Python 3.5引入
对函数的参数进行类型注解;
对函数的返回值进行类型注解;
只对函数参数做一个辅助的说明,并不对函数参数进行类型检查;
提供给第三方工具,做代码分析,发现隐藏的bug;
函数注解的信息,保存在__annotations__属性中
add.__annotations__
{'y': <class 'int'>, 'x': <class 'int'>, 'return': <class 'int'>}
业务应用
函数参数类型检查
思路:
函数参数的检查,一定是在函数外;
函数应该作为参数,传入到检查函数中;
检查函数拿到函数传入的实际参数,与形参声明对比;
__annotations__属性是一个字典,其中包括返回值类型的声明。假设要做位置参数的判断,无法和
字典中的声明对应。
使用inspect模块
inspect模块:
提供获取对象信息的函数,可以检查函数和类、类型检查。
signature(callable),获取签名(函数签名包括了一个函数的信息,包括函数名,参数类型,它所在的类和名称空间及其他信息)
import inspect
def add(x: int, y: int, *args, **kwargs) -> int:
return x + y
sig = inspect.signature(add)
print(sig)
print("param : ", sig.parameters)#OrderedDict
print("return :", sig.return_annotation)
print(sig.parameters['y'])
print(sig.parameters['x'].annotation)
print(sig.parameters['args'])
print(sig.parameters['args'].annotation)
print(sig.parameters['kwargs'])
print(sig.parameters['kwargs'].annotation)
inspect.isfunction(add), 是否是函数;
inspect.ismethod(add), 是否是类的方法
inspect.isgenerator(add), 是否是生成器对象;
inspect.isgeneratorfunction(add), 是否是生成器函数;
inspect.isclass(add), 是否是类;
inspect.ismodule(inspect), 是否是模块
isclass.isbuiltin(print), 是否是内建对象
还有很多is函数,需要的时候查阅inspect模块帮助;
parameter对象
保存在元组中,是只读的;
name, 参数的名字;
annotation, 参数的注解,可能没有定义;
default, 参数的缺省值,可能没有定义;
empty,特殊的类,用来标记default属性或者注释annotation属性的空值;
kind,实参如何绑定到形参,就是形参的类型
POSITIONAL_ONLY ,值必须是位置参数提供
POSITIONAL_OR_KEYWORD, 值可以作为关键字或者位置参数提供;
VAR_POSITIONAL, 可变位置参数,对应*args;
KEYWORD_ONLY, keyword_only参数,对应*或者*args之后出现的非可变关键字参数;
VAR_KEYWORD,
转载于:https://blog.51cto.com/limingyu/2311079