首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Python语法学习记录(23):函数参数注释语法、访问函数注释【inspect块代码示例】

  • 25-03-03 18:03
  • 4385
  • 11053
blog.csdn.net

1、简述

在 Python 3.x 中,增加了一个新特性:函数注释(Function Annotations),顾名思义,可做为函数额外的注释来用。

函数注释是一个可选功能,它允许在函数参数和返回值中添加任意的元数据。无论是 Python 本身还是标准库,都使用了函数注释,第三方项目可以很方便的使用函数注释来进行文档编写、类型检查、或者是其他用途。

在 Python 2.x 中,由于缺少对函数参数和返回值进行注释的标准方法,所以很多工具和库为了填补这一空白,使用了不同的方式:

自定义 decorator
自定义 docstring 格式
向函数对象添加自定义属性
显然,由于机制和语法的广泛差异,这会在一定程度上引起混乱。

为了解决这个问题,Python 3.x 引入了函数注释(详见:PEP-3107),旨在提供了一种单一的、标准的方法,来将元数据与函数参数和返回值相关联。

注意: 注释是完全可选的。

2、函数注释语法

函数注释作用是提高代码可读性,暗示传入参数及返回数据的类型。

函数注释两个部分:

  • 参数注释:以冒号(:)标记,建议传入的参数类型
  • 返回值注释:以 ->标记,建议函数返回的类型

语法结构大体如下:

def funname(para1: expression, para2: expression = 5) -> expression:
    ...
  • 1
  • 2

expression 为函数注释。函数注释可以包含类型、帮助字符串,以及其他更多信息。一般为字符串表示注释,或变量类型名。

参数注释的伪语法中,参数看起来像:identifier [: expression] [= expression]。也就是说,参数注释总在其默认值之前。当函数定义被执行时,所有的注释表达式都被求值,就像默认值一样。参数列表后面可以跟一个 -> 和一个 Python 表达式。与参数的注释一样,在执行函数定义时,将对该表达式求值。但注意表达式就相当于注释所规定的的类型或者内容并非强制,也不会有相应的检查

示例 1:

def addfun(a:"被加数"=11 , b:int=2)->"abc":
    return a+b
if __name__ == "__main__":
    print(addfun(4,4))
  • 1
  • 2
  • 3
  • 4

image-20201019212700383

示例2:

来看一个例子,有一个函数 sum(),接受三个参数 a、b、c,并返回它们的和。

def sum(a, b: int, c: 'The default value is 5' = 5) -> float:
    return a + b + c
  • 1
  • 2

其中,第一个参数 a 没有注释,第二个参数 b 带有类型为 int 的注释,第三个参数 c 带有一个帮助字符串注释并且拥有默认值,返回值用类型 float 来注释。

调用 sum() 两次,一次使用 int,一次使用字符串:

def sum(a, b: int, c: 'The default value is 5' = 5) -> float:
    return a + b + c

if __name__ == "__main__":
    print(sum(1, 2))
    print(sum('Hello', ', ', 'Python!'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

显然,注释对函数的执行没有任何影响。在这两种情况下,sum() 都做了正确的事情,只不过注释被忽略了而已。

image-20201019213810347

3、访问函数注释

函数对象有一个名为 __annotations__ 的属性,它是一个映射(dict),用于将每个参数名(key)映射到其相关的注释(value)。

注意: 映射中有一个特殊的 key,叫做"return",仅当为函数的返回值提供注释时,才会显示该 key。

回到上述示例,并检查它的注释:

type(sum.__annotations__)
<class 'dict'>
sum.__annotations__
{'c': 'The default value is 5', 'return': <class 'float'>, 'b': <class 'int'>}
  • 1
  • 2
  • 3
  • 4

之所以选择 "return",是因为它不会与任何参数名冲突。"return"是 Python 中的一个关键字,任何使用"return"作为参数名的尝试都会引发 SyntaxError。

image-20201019214200221

4、多个内容注释

倘若,函数注释中要同时包含类型和帮助字符串,可以使用具有两个 key(例如:type 和 help)的 dict:

def div(a: dict(type=float, help='the dividend'),
        b: dict(type=float, help='the divisor (must be different than 0)')) -> dict(type=float, help='the result of dividing a by b'):
    """Divide a by b"""
    return a / b

if __name__ == "__main__":
    print(div.__annotations__)
    print(div(5, 2))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

image-20201019215351224

注意: 如果要包含更多的注释(示例中是 2 个),可以在 dict 中包含更多的 key:value 对。

5、动态注释

__annotations__ 是函数的一个属性,类型为 dict。由于dict 是可变的,这意味着,可以在程序运行时动态地修改注释。

假设,想知道是否使用了参数的默认值,或者想把所有的返回值都加起来。

def sum(a, b) -> 0:
    result = a + b
    sum.__annotations__['return'] += result
    return result

if __name__ == "__main__":
    print("原始设置参数:",sum.__annotations__['return'])
    print(sum(1, 2))
    print("第一次调用后参数:",sum.__annotations__['return'])
    print(sum(3, 4))
    print("第二次调用后参数:",sum.__annotations__['return'])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

image-20201019220034620

PS: 动态注释可以在函数内部完成,也可以由装饰器完成。

6、inspect模块

代码分析,发现隐藏BUG提供给第三方工具:inspect模块

inspect 模块 的作用

(1).对是否是模块,框架,函数等进行类型检查。

(2).获取源码

(3).获取类或函数的参数的信息

以下是官方文档说明:

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

import inspect
import functools
def dect(fn):
    @functools.wraps(fn)
    def _dect(*args,**kwargs):
        sig = inspect.signature(fn)
        params = sig.parameters   #有序字典
        keys = list(params.keys())
        values = [_ for _ in params.values()]
        for i,m in enumerate(args):   #args用tuple包装二元组的方式保存位置参数
            #和注解进行比较
            if values[i].annotation is not inspect._empty:
                if isinstance(m,values[i].annotation):  
                    print("正确:",keys[i],'==', m,",属于",values[i].annotation)
                else:
                    print("不正确:",keys[i],'=', m,",不属于",values[i].annotation)
            else:
                print("没有检查需要:",keys[i])
        for k,v in kwargs.items():  
            if params[k].annotation is not inspect._empty and isinstance(v,params[k].annotation):    
                #业务需求应该是没有注解就不比较了
                print(k,'===',v)
        ret = fn(*args,**kwargs)
        return ret 
    return _dect
@dect
def add(x,y:int =7) -> int:  #add = dect(add)
    return x + y

add("1","2")
add(1,2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

image-20201019231203071

LAST、参考文献

Python3 函数注释:参数中的冒号与箭头

python标准库中inspect 模块简单介绍

Python–参数注解

文章知识点与官方知识档案匹配,可进一步学习相关知识
Python入门技能树基础语法函数416623 人正在系统学习中
注:本文转载自blog.csdn.net的呆呆象呆呆的文章"https://blog.csdn.net/qq_41554005/article/details/109174607"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top