python文件编译成so文件后用不了inspect函数_Python系列教程(二十九):函数注解和Inspect模块...

一、函数注解

1、什么是函数注解

这是在python 3.5才引进的新功能,可以给函数的参数和返回值做一个注解,但这个并不是强制类型的,也就说,就算加了函数注解,也只是一个辅助说明,并不会对函数参数进行类型检查,只能提供给函数调用者一些友好的提示信息。

函数注解的信息,保存在特殊属性__annotations__中

2、如何使用函数注解

在定义函数的时候,参数注解是在每个参数后面使用‘:’说明参数类型,返回值注解是在参数列表后面使用‘->’指定返回值类型。

注意:如果参数有默认值,默认值应该放在参数注解后面

格式:def add(x:int , y:str='a') -> int :

#定义一个添加了函数注解的f1函数

def f1(x:int,y:str,z:dict={1:3}) -> int:

pass

#通过特殊属性获取函数注解

>>>f1.__annotations__

{'x': int, 'y': str, 'z': dict, 'return': int}

3、函数注解的应用

虽然函数注解不具备强制性,不做类型检查,但是我们自己可以通过拿到函数注解,自己写一个检查函数来做类型检查。

检查函数的分析如下:

① 检查功能不应该写在每个函数中,应该抽离出来,单独写一个具有检查功能的检查函数

② 被检查的函数应该作为参数,传入到检查函数中

③ 检查函数要能拿到传入被检查函数的实际参数,然后和__annotations__里面的类型做判断

这么一分析,好像我们前面学的装饰器非常适合做这件事。

#具有检查功能的装饰器函数

def check(fn):

def wrapper(*args,**kwargs):

for k1,v1 in fn.__annotations__.items():

for k2,v2 in kwargs.items():

if k1 == k2 and  not isinstance(v2,v1):

print('error')

return

result = fn(*args,**kwargs)

return result

return wrapper

#只需要在被检查函数前面加个装饰器

@check

def f1(x:int,y:str,z:dict={1:3}) -> int:

pass

#传参类型不满足函数注解的类型,所以报错了

>>>f1(x=3,y=2,z={1:2})

error

二、Inspect模块

问题分析:通过自己写了一个检查装饰器函数,好像可以解决问题,但是我们要找到,特殊属性__annotations__是一个字典,字典是无序的,如果我们传的是位置参数呢,好像就无法正确的进行匹对检查了。

问题解决:借助Inspect模块可以解决这个问题

步骤1:获取函数的签名

格式:Inspect.signature(callable) -> sig(函数签名)

import inspect

#定义一个演示函数

def add(x:int, y:int=3, *args,**kwargs) -> int:

return x + y

#获取函数的签名

>>>sig = inspect.signature(add)

步骤2:通过函数签名的两个属性,拿到参数列表字典和返回值类型

格式:sig.parameters -> 一个有序字典,key是每一个参数,对应的value是每个参数封装的一个parameter对象

格式:sig.return__annotation  -> 返回值类型

#一个有序字典

>>>sig.parameters

OrderedDict([('x', ), ('y', ), ('args', ), ('kwargs', )])

#返回值类型

>>>sig.return_annotation

步骤3:通过parameter对象的属性,获取相应的值

格式:sig.parameters['参数名称'].属性

parameter对象有如下常用到属性

name:参数的名字

annotation:参数的注解,可能没有定义

default:参数的默认值,可能没有定义

empty:可以判断一个参数注解是否为空

kind:形参的类型(位置参数,可变位置参数,keyword_only参数,可变关键字参数),对应如下:

POSITIONAL_ONLY:位置参数

POSITIONAL_OR_KEYWORD:位置参数或关键字参数

VAR_POSITIONAL:可变位置参数,对应*args

KEYWORD_ONLY:keyword-only参数

VAR_KEYWORD:可变关键字参数,对应**kwargs

#通过parameters字典找到参数对应的parameter对象,再通过对象的属性获取响应值

>>>print(sig.parameters['x'].annotation)

>>>print(sig.parameters['x'].name)

>>>print(sig.parameters['x'].kind)

x

POSITIONAL_OR_KEYWORD

三、实际业务问题处理

通过inspect模块来写一个检查装饰器函数,可以检查调用函数传递的实参是否满足参数注解的要求。

比如:def add(x:int, y:int=3, *args:int,**kwargs) -> int:

#定义一个检查装饰器函数

def check(fn):

def wrapper(*args,**kwargs):

sig = inspect.signature(fn)

parlist = list(sig.parameters.values())

for i in parlist:

if str(i.kind) == 'VAR_POSITIONAL':

var_position = parlist.index(i)

if str(i.kind) == 'VAR_KEYWORD':

var_keyword = parlist.index(i)

for k,v in enumerate(args):

if k 

if parlist[k].annotation is not parlist[k].empty:

if not isinstance(v,parlist[k].annotation):

print('args error')

return

else:

if parlist[var_position].annotation is not parlist[var_position].empty:

if not isinstance(v,parlist[var_position].annotation):

print('args error')

return

for k,v in kwargs.items():

if k in sig.parameters:

if sig.parameters[k].annotation is not sig.parameters[k].empty and not isinstance(v,sig.parameters[k].annotation):

print('kwargs error')

return

result = fn(*args,**kwargs)

return result

return wrapper

#在需要检查的函数使用装饰器

@check

def add(x:int, y:int=3, *args:int,**kwargs) -> int:

return x + y

#验证

>>>add(3,y=10,z='3')

13

>>>add(3,y='a',z='3')

kwargs error

>>>add(3,4,'a')

args error

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值