14 - 函数参数检测-inspect模块

2024-04-13 06:38

本文主要是介绍14 - 函数参数检测-inspect模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

14 - 函数参数检测-inspect模块

 

目录

  • 1 python类型注解
  • 2 函数定义的弊端
  • 3 函数文档
  • 4 函数注解
    • 4.1 annotation属性
  • 5 inspect模块
    • 5.1 常用方法
    • 5.2 signature类
    • 5.3 parameters属性
    • 5.4 获取对象的参数签名
  • 6 检查参数

 

1 python类型注解

        类型注解,即对变量的类型,进行标注或者说明,因为Python是一门动态编译型语言,我们无法在赋值时就定义它的变量类型,所以在Python3.5以上版本新增了类型注解,但仅仅是提示作用,并不能严格控制,这是动态编译型语言的通病,下面来仔细看一下什么是Python的类型注解。

2 函数定义的弊端

        Python是动态语言,变量随时可以被赋值,且赋值为不同的类型,这就与静态语言不同了,变量的类型是在运行期决定的,而静态语言事先就已经定义好了变量的类型了。这是动态语言方便之处,但也是一种弊端,我们无法控制变量的类型,也就无法控制异常的产生。举个栗子

def add(x,y):return x + y 
print(add(1,2))
print(add('s','b'))
print(add(1,'a'))

        当用户传入两个数字时,返回它们的和,但是如果我们传递其他变量呢?比如字符串,因为Python中实现了+号的类型重载,所以说两个字符串的确可以加,但是如果是数字和字符串呢?在Python这种强类型语言中来说,属于非法操作(javascript会隐式转换),而这时,我们就需要对用户传入的数据进行类型判断,不符合本函数的需求,那么就抛个异常,或者提示等等操作,这样就不会引起后续代码在执行期崩溃。如何解决呢?其实主要有两种方式。

  • 函数文档
  • 函数注解

3 函数文档

        在函数中插入说明性文档的方式成为函数文档。

def add(x, y):"""This function used to add something:param x: int object:param y: int object:return: int object"""return x + y

在函数中,一般是定义语句后的首行使用三对双引号表示。通常存储在函数的__doc__属性中。当用户使用help(函数)时,会被打印在屏幕上。

In [68]: def add(x, y):...:     """...:     This function used to add something...:     :param x: int object...:     :param y: int object...:     :return: int object...:     """...:     return x + y...:In [69]: help(add)
Help on function add in module __main__:add(x, y)This function used to add something:param x: int object:param y: int object:return: int objectIn [70]: print(add.__doc__)This function used to add something:param x: int object:param y: int object:return: int objectIn [71]:

每次都要使用help来查看函数的说明,的确可以让使用者了解函数的参数以及返回值的类型,但并不是所有人都愿意写doc的,在这个所谓的敏捷开发时代,人们大多会以敏捷开发为借口没时间写,所以这种方法不是很用。

4 函数注解

        Python的函数注解是什么呢?首先来看一下如下代码:

def add(x: int, y: int) -> int:return x + y
  • 函数的位置形参,和默认值形参后使用冒号分隔,后面用于标识变量期望的类型。
  • 在def语句末尾,使用->符号后 指定用于标识函数执行后的返回值类型。

完成以上定义后,,主要的差别如下图:
zhushi.png?raw=trueuploading.4e448015.gif转存失败重新上传取消zhushi1

当我们在IDE中准备传入非注释类型变量时,IDE会帮我们进行颜色提示,用于表示这里传入的变量有点问题。在编写时我们尚且可以使用这种方式,对我们产生一点'警示',但是当我们写的函数被其他人调用的时候,那么就无法进行'提示'了,这个时候,我们就需要对传入的参数进行类型检查了。

我们来总结一下:

  • 函数注解在Python3.5中引入
  • 对函数的参数、返回值进行类型注解
  • 只对函数的参数做一个辅助的说明,并不对函数参数进行类型检查
  • 提供给第三方工具,做代码分析,发现隐藏的BUG
  • 函数注解的信息,保存在函数的__annotation__属性中。

python3.6 以上还添加了变量的注解:i:int = 10,当然也只是提示的作用。

4.1 annotation属性

在Python中使用__开头的表示符一般被用特殊属性,__annotation__存储的就是函数的签名信息

In [71]: def add(x: int, y: int) -> int:...:     return x + y...:In [73]: add.__annotations__
Out[73]: {'x': int, 'y': int, 'return': int}

        当我们使用变量注释时,变量名和类型就会存放在函数的__annotations__属性中。那么即然有变量存储,那么我们是不是只需要获取传入的参数,然后和annotations中存储的变量类型进行比较是不是就达到目的了呢?仔细思考一下:

  1. 参数检查势必要在函数执行前,想要在add执行前添加参数判断那么就需要使用装饰器了
  2. __annotations__的值是一个字典,字典是无序的,用户按照位置传进来参数是有序的,如何让它们形成对应关系方便我们检测呢?

下面我们来了解一下inspect模块,它可以帮我们完成这个事情。

5 inspect模块

        官方解释如下:inspect模块提供了几个有用的函数来帮助获取关于活动对象的信息,例如模块、类、方法、函数、回溯、框架对象和代码对象。例如,它可以帮助您检查类的内容、检索方法的源代码、提取并格式化函数的参数列表,或者获取显示详细回溯所需的所有信息。

5.1 常用方法

分类方法名称功能
判断inspect.getmodulename(path)获取模块名称
 inspect.ismodule(object)是不是个模块
 inspect.isclass(object)是不是个类
 inspect.ismethod(object)是不是一个方法
 inspect.isfunction(object)是不是一个函数
 inspect.isgeneratorfunction(object)是不是一个生成器函数
 inspect.isgenerator(object)是不是一个生成器
 inspect.iscoroutinefunction(object)是不是一个协程函数
获取信息inspect.getmodulename(path)获取模块名称
 inspect.getsource(object)获取对象的原码(并不会解析装饰器原码)

5.2 signature类

        首先我们要说的是函数的签名信息:它包含了了函数的函数名、它的参数类型,它所在的类和名称空间及其他信息,签名对象(signature object)表示可调用对象的调用签名信息和它的注解信息,当我们使用signature()时,它会重新返回一个包含可调用对象信息的签名对象。

5.3 parameters属性

        signature类的parameters属性,它里面存放的是函数的参数注解和返回值注解,组成的有序字典,其中参数注解的格式为:参数名称,使用inspect.Parameters类包装的参数注解,这个参数注解很强大,它包含如下常用的方法:

方法名称含义
empty等同于inspect._empty表示一个参数没有被类型注释
name参数的名称
default参数的默认值,如果一个参数没有默认值,这个属性的值为inspect.empty
annotation参数的注解类型,如果参数没有定义注解,这个属性的值为inspect.empty
kind参数的类型

这里的参数类型表示的是inspect内置参数类型(其实就是几个常用的函数参数定义类型而已,只是换个名字而已)

_POSITIONAL_ONLY         = _ParameterKind.POSITIONAL_ONLY       # 位置参数_only
_POSITIONAL_OR_KEYWORD   = _ParameterKind.POSITIONAL_OR_KEYWORD # 位置或关键字参数
_VAR_POSITIONAL          = _ParameterKind.VAR_POSITIONAL        # 可变位置参数
_KEYWORD_ONLY            = _ParameterKind.KEYWORD_ONLY          # keyword-only参数
_VAR_KEYWORD             = _ParameterKind.VAR_KEYWORD           # 可变关键字参数

其中POSITIONAL_ONLY,Python中没有被实现。

5.4 获取对象的参数签名

根据上面讲的方法,我们可以通过如下方式,简单的获取参数的签名:

In [11]: import inspect...:...: def add(x: int, y: int) -> int:...:     return x + y...:...: sig = inspect.signature(add)...: params = sig.parameters...: print(params)
OrderedDict([('x', <Parameter "x:int">), ('y', <Parameter "y:int">)])In [21]: params['x'].annotation
Out[21]: int    # 如果没有定义x的参数注解,那么这里就是inspect._empty

通过它的属性,搭配有序字典这个特性,有没有很兴奋?参数有序,传入的实参有序,还能获取参数注解的类型,那么就可以开工进行参数检查了!

6 检查参数

以上面函数为例子,当给add函数传入的x,y时进行参数检查,如果x,y不是int类型,那么返回异常,并退出函数

import inspect
import functoolsdef check(fn):@functools.wraps(fn)   # 等于 wrapper.__annotation__ = fn.__annotation__ 还有其他的属性比如__doc__,__module__等def wrapper(*args, **kwargs):sig = inspect.signature(fn)   # 获取add函数签名信息params = sig.parameters     # 获取add函数的参数信息values = list(params.values())   # 由于params是个有序字典,那么values也是有序的,只需根据索一一对应判断即可for i, k in enumerate(args):   # 遍历用户传入的位置参数if values[i].annotation != inspect._empty:   # 如果定义了参数注解,则开始检查if not isinstance(k, values[i].annotation):   # 如果检查不通过,曝出异常raise('Key Error')for k,v in kwargs.items():if params[k].annotation != inspect._empty:if not isinstance(v,params[k].annotation):raise('Key Error')return fn(*args, **kwargs)return wrapper@check
def add(x: int, y: int) -> int:return x + yadd(4,y=5)

所有巧合的是要么是上天注定要么是一个人偷偷的在努力。

这篇关于14 - 函数参数检测-inspect模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/899401

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X

基于 YOLOv5 的积水检测系统:打造高效智能的智慧城市应用

在城市发展中,积水问题日益严重,特别是在大雨过后,积水往往会影响交通甚至威胁人们的安全。通过现代计算机视觉技术,我们能够智能化地检测和识别积水区域,减少潜在危险。本文将介绍如何使用 YOLOv5 和 PyQt5 搭建一个积水检测系统,结合深度学习和直观的图形界面,为用户提供高效的解决方案。 源码地址: PyQt5+YoloV5 实现积水检测系统 预览: 项目背景

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.

Jenkins构建Maven聚合工程,指定构建子模块

一、设置单独编译构建子模块 配置: 1、Root POM指向父pom.xml 2、Goals and options指定构建模块的参数: mvn -pl project1/project1-son -am clean package 单独构建project1-son项目以及它所依赖的其它项目。 说明: mvn clean package -pl 父级模块名/子模块名 -am参数

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

[数据集][目标检测]血细胞检测数据集VOC+YOLO格式2757张4类别

数据集格式:Pascal VOC格式+YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2757 标注数量(xml文件个数):2757 标注数量(txt文件个数):2757 标注类别数:4 标注类别名称:["Platelets","RBC","WBC","sickle cell"] 每个类别标注的框数: