参数注解

本文介绍了Python 3.6引入的参数注解功能,包括对函数参数和返回值的类型注解,用于辅助说明和代码分析,以及如何利用`__annotations__`属性和`inspect`模块进行参数检查。通过示例展示了如何使用`signature`获取函数信息,并解释了不同类型的形参绑定方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、对函数的参数进行类型注解

2、对函数的返回值进行类型注解

3、只对函数参数做一个辅助说明,并不对函数参数进行类型检查

4、提供给第三方工具,做代码分析,发现隐藏BUG

5、函数注解的信息,保存在__annotations__属性中

def add(x: int, y: int, *args,  **kwargs) -> int:
    ret = x + y
    return ret


print(add.__annotations__)

out:
{'y': <class 'int'>, 'return': <class 'int'>, 'x': <class 'int'>}  # 无序字典

Python 3.6引入

变量注解:  i: int = 3

业务应用:

函数参数的检查,一定是要函数外

函数应作为参数,传入到检查函数中

检查函数拿到函数传入的实际参数,与形参声明对比

__annotations__属性是一个字典,其中包括返回值类型的声明

假设要做位置参数的判断,无法和字典中的声明对应,要使用inspect模块

 

inspect模块

提供获取对象信息的函数,可以检查函数的类、类型检查

signature(callable),获取签名

签名包含了一个函数的信息,包括函数名,参数类型,它所在的类和名称空间及其他信息

 

Parameter对象

1、保存在元组中,是只读的

2、name,参数的名字

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

4、default,参数的缺省值,可能没有定义

5、empty,特殊的类,用来标记default属性或者注解annotation属性的空值

6、kind,实参如何绑定到形参,就是形参的类型

POSITIONAL_ONLY,值必须是位置参数提供,Python没有实现,因为也是通过关键字传参

POSITIONAL_OR_KEYWORD,值可以作为关键字或者位置参数提供

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

KEYWORD_ONLY,keyword-only参数,对应*,或者*args后出现的非可变关键字参数

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

import inspect


def add(x: int, y: int, *args, **kwargs) -> int:
    return x + y


sig = inspect.signature(add)
print(1, sig)
print(2, 'params : ', sig.parameters)  # OrderedDict
print(3, 'return : ', sig.return_annotation)
print(4, sig.parameters['y'])
print(5, sig.parameters['x'].annotation)
print(6, sig.parameters['args'])
print(7, sig.parameters['args'].annotation)
print(8, sig.parameters['kwargs'])
print(9, sig.parameters['kwargs'].annotation)


print(inspect.isfunction(add))   # 是否是函数
print(inspect.ismethod(add))  # 是否是类的方法
print(inspect.isgenerator(add))  # 是否是生成器对象
print(inspect.isgeneratorfunction(add))  # 是否是生成器函数
print(inspect.isclass(add))  # 是否是类
print(inspect.ismodule(inspect))  # 是否是模块
print(inspect.isbuiltin(print))   # 是否是内建对象


out:
1 (x:int, y:int, *args, **kwargs) -> int
2 params :  OrderedDict([('x', <Parameter "x:int">), ('y', <Parameter "y:int">), ('args', <Parameter "*args">), ('kwargs', <Parameter "**kwargs">)])
3 return :  <class 'int'>
4 y:int
5 <class 'int'>
6 *args
7 <class 'inspect._empty'>
8 **kwargs
9 <class 'inspect._empty'>
True
False
False
False
False
True
True
import inspect


def add(x, y: int=7, *args, z, t=10, **kwargs) -> int:
    return x + y


sig = inspect.signature(add)
print(sig)
print('params : ', sig.parameters)
print('return : ', sig.return_annotation)
print('~~~~~~~~~~~~~~~~')
for i, item in enumerate(sig.parameters.items()):
    print(item)
    name, param = item
    print(i+1, name, param, param.annotation, param.kind, param.default)
    print(param.default is param.empty, end='\n\n')

out:
(x, y:int=7, *args, z, t=10, **kwargs) -> int
params :  OrderedDict([('x', <Parameter "x">), ('y', <Parameter "y:int=7">), ('args', <Parameter "*args">), ('z', <Parameter "z">), ('t', <Parameter "t=10">), ('kwargs', <Parameter "**kwargs">)])
return :  <class 'int'>
~~~~~~~~~~~~~~~~
('x', <Parameter "x">)
1 x x <class 'inspect._empty'> POSITIONAL_OR_KEYWORD <class 'inspect._empty'>
True

('y', <Parameter "y:int=7">)
2 y y:int=7 <class 'int'> POSITIONAL_OR_KEYWORD 7
False

('args', <Parameter "*args">)
3 args *args <class 'inspect._empty'> VAR_POSITIONAL <class 'inspect._empty'>
True

('z', <Parameter "z">)
4 z z <class 'inspect._empty'> KEYWORD_ONLY <class 'inspect._empty'>
True

('t', <Parameter "t=10">)
5 t t=10 <class 'inspect._empty'> KEYWORD_ONLY 10
False

('kwargs', <Parameter "**kwargs">)
6 kwargs **kwargs <class 'inspect._empty'> VAR_KEYWORD <class 'inspect._empty'>
True

 

业务应用:

参数有注解就要求实参类型和声明应该一致

import inspect


def check(fn):
    def wrapper(*args, **kwargs):
        print(args, kwargs)
        sig = inspect.signature(fn)   # 签名
        params = sig.parameters  # 有序字典
        values = list(params.values())
        print(values)
        # 位置参数处理
        for i, p in enumerate(args):
            print(i, p)
            print('===') if isinstance(p, values[i].annotation) or values[i].annotation is values[i].empty else print('xxx')
            print('##', values[i].annotation)
        # 关键字参数处理
        for k, v in kwargs.items():
            print(k, v)
            print('====') if isinstance(v, params[k].annotation) else print('xxxx')
            print('###', params[k].annotation)
        return fn(*args, **kwargs)
    return wrapper


@check
def add(x, y: int=7) -> int:  # 业务函数
    return x + y


print(add(5, 7))
print(add(y=4, x=9))



Out:
[<Parameter "x">, <Parameter "y:int=7">]
0 5
===
## <class 'inspect._empty'>
1 7
===
## <class 'int'>
12
[<Parameter "x">, <Parameter "y:int=7">]
y 4
====
### <class 'int'>
x 9
xxxx
### <class 'inspect._empty'>
13

out:
(5, 7) {}
[<Parameter "x">, <Parameter "y:int=7">]
0 5
xxx
## <class 'inspect._empty'>
1 7
===
## <class 'int'>
12
() {'x': 9, 'y': 4}
[<Parameter "x">, <Parameter "y:int=7">]
x 9
xxxx
### <class 'inspect._empty'>
y 4
====
### <class 'int'>
13

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值