python 类型注解

函数定义的弊端

  • python 是动态语言,变量随时可以被赋值,且能赋值为不同类型
  • python 不是静态编译型语言,变量类型是在运行器决定的
  • 动态语言很灵活,但是这种特性也是弊端
def add(x,y):
    return x+y
print(add(4,5))
print(add(‘hello‘,‘world‘))
print(add(4,‘hello‘)) #报错,TypeError: unsupported operand type(s) for +: ‘int‘ and ‘str‘
  • 难发现:由于不做任何类型检查,直到运行期问题才显现出来,或者线上运行时才能暴露出问题
  • 难使用:函数的使用者看到函数的时候,并不知道你的函数的设计,并不知道应该传入什么类型数据

如何解决这种动态语言定义的弊端呢?

  • 增加文档Docmentation String

    • 这是一个惯例,不是强制标准,不能要求程序员一定为函数提供说明文档
    • 函数定义更新了,文档未必同步更新
def add(x,y):
    """
    :param x:int
    :param y:int
    :return:int
    """
    return x+y
print(help(add))
  • 函数注解

    • python3.5引入
    • 对函数的参数进行类型注解
    • 对函数的返回值进行类型注解
    • 只对函数参数做一个辅助说明,并不对函数参数进行类型检查
    • 提供给第三方工具,做代码分析,发现隐形bug
    • 函数注解的信息,保存在__annotations__属性中
    • python3.6中引入变量注解
      • i:int = 3
def add(x:int,y:int)->int:
    """
    :param x:int
    :param y:int
    :return:int
    """
    return x+y
print(help(add))
print(add(4,5))
print(add("jax","zhai"))   #在pycharm里参数是灰色

函数参数类型检查

思路:

  • 函数参数的检查,一定是在函数外
  • 函数应该作为参数,传入到检查函数中
  • 检查函数拿到函数传入的实际参数,与形参声明对比
  • __annotations__属性是一个字典,其中包括返回值类型的声明,假设要做一个位置参数的判断,无法和字典中的声明对应,使用inspect模块
  • inspect模块
    • 提供获取对象信息的函数,可以检查函数和类、类型检查

inspect模块

  • signature(callable),获取签名(函数签名包含一个函数的信息,包括函数名、它的参数类型、它所在的类和名称空间及其他信息)
import inspect
def add(x:int,y:int,*args,**kwargs)->int:
    return x+y
sig =  inspect.signature(add)
print(sig,type(sig)) #获取签名
print(‘params :‘,sig.parameters) #OrderedDict
print(‘return :‘,sig.return_annotation) #返回值类型
print(sig.parameters[‘y‘], type(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.isclass(add) #是不是类
inspect.ismodule(add) #是不是模块
inspect.isbuiltin(add) #是不是内建对象
  • Parameter对象

    • 保存在元组中,是只读的
    • name ,参数的名字
    • annotation 参数注解,可能没有定义
    • default 参数的缺省值,可能没有定义
    • empty 特殊的类,用来标记default属性或者注释annotation属性的空值
    • kind 实参如何绑定到形参,就是形参的类型
      • POSITIONAL_ONLY,值必须是位置参提供
      • 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(sig)
print(‘params : ‘, sig.parameters)
print(‘return : ‘, sig.return_annotation)
print(‘~~~~~~~~~~~~~~~~‘)
for i,item in enumerate(sig.parameters.items()):
    name,param = item
    print(i+1,name,param.annotation,param.kind,param.default)
    print(param.default is param.empty, end = ‘\n\n‘)

有函数如下:

def add(x,y:int=7) -> int:
    return x + y
  • 检查用户输入是否符合参数注解的要求?
  • 思路:
    • 调用时,判断用户输入的实参是否符合要求
    • 调用时,用户感觉上还是在调用add函数
    • 对用户输入的数据和声明的类型进行对比,如果不符合,提示用户
def check(fn):
    def wrapper(*args,**kwargs):
        sig = inspect.signature(fn)
        params = sig.parameters
        values = list(params.values())
        #print(values)
        for i,p in enumerate(args):
           # print(i,p)
            params = values[i]
            #print(params.annotation,params.empty)
            if params.annotation is not params.empty and not isinstance(p,params.annotation):
                print(p,‘!==‘,values[i].annotation)
        for k,v in kwargs.items():
            if sig.parameters[k].annotation is not inspect._empty and not isinstance(v,sig.parameters[k].annotation):
                print(k,v,‘!===‘,sig.parameters[k].annotation)
        return fn(*args,**kwargs)
    return wrapper
@check
def add(x,y:int=7) -> int:
    return x + y
#print(add(20,10))
print(add(20,y=10))
print(add(y=10,x=20))

原文地址:https://www.cnblogs.com/xzkzzz/p/11378842.html

时间: 2024-11-07 05:46:13

python 类型注解的相关文章

Python类型注解(inspect模块)

函数定义的弊端 Python是动态语言,变量随时可以被赋值,且能赋值为不同的类型,同时Python不是静态编译型语言,变量类型是在运行器决定的,动态语言很灵活,但是这种特性也是弊端. def add(x, y): return x + y print(add(4, 5)) print(add('hello', 'world')) add(4, 'hello') # 结果为: 9 helloworld ------------------------------------------------

python类型注解

function annotation 写法: 使用冒号 : 加类型代表参数类型 默认值参数示例:b: int = 2 使用 -> 加类型代表返回值类型 python解释器运行时并不会检查类型,类型不对也不会抛异常,仅仅是注解而已.示例: def plus(a: int, b: int = 2) -> int: return a + b python 解析器并不会在意类型注解,严格来说这是不对的,Python 会把类型信息放在 __annotations__ 属性中: >>>

?Python 3 新特性:类型注解——类似注释吧,反正解释器又不做校验

?Python 3 新特性:类型注解 Crossin ? 上海交通大学 计算机应用技术硕士 95 人赞同了该文章 前几天有同学问到,这个写法是什么意思: def add(x:int, y:int) -> int: return x + y 我们知道 Python 是一种动态语言,变量以及函数的参数是不区分类型.因此我们定义函数只需要这样写就可以了: def add(x, y): return x + y 这样的好处是有极大的灵活性,但坏处就是对于别人代码,无法一眼判断出参数的类型,IDE 也无法

Python3新特性 类型注解 以及 点点点

Python3新特性 类型注解 以及 点点点 ... Python3 的新特性 Python 是一种动态语言,变量以及函数的参数是 不区分类型 的 在 函数中使用类型注解 相当于 给 形参的 类型 设置了一个备注 # 使用类型注解 a b 参数需要 int 类型的 变量 def func(a: int = ..., b: int = ...): return a + b 使用 PyCharm 编写python代码时 函数调用会有默认参数的 提示 如果传递的 参数不是 指定的类型 正常使用也不会报

介绍几款 Python 类型检查工具

微软在 Github 上开源了一个 Python 静态类型检查工具:pyright ,引起了社区内的多方关注. 微软在开源项目上的参与力度是越来越大了,不说收购 Github 这种大的战略野心,只说它家开源的 VS Code 编辑器,在猿界已经割粉无数,连我们 Python 圈的红人 Kenneth Reitz (多个开源项目的作者,包括 requests.requests-html.responder等)都对它赞不绝口. 如今开源的 Pyright ,口碑还不错,那我们就来看看它有啥本事,顺便

typing-python用于类型注解的库

简介 动态语言的灵活性使其在做一些工具,脚本时非常方便,但是同时也给大型项目的开发带来了一些麻烦. 自python3.5开始,PEP484为python引入了类型注解(type hints),虽然在pep3107定义了函数注释(function annotation)的语法,但仍然故意留下了一些未定义的行为.现在已经拥有许多对于静态类型的分析的第三方工具,而pep484引入了一个模块来提供这些工具,同时还规定一些不能使用注释(annoation)的情况 #一个典型的函数注释例子,为参数加上了类型

C Python类型互换

从Python到C的转换用PyArg_Parse*系列函数,int PyArg_ParseTuple():把Python传过来的参数转为C:int PyArg_ParseTupleAndKeywords()与PyArg_ParseTuple()作用相同,但是同时解析关键字参数:它们的用法跟C的sscanf函数很像,都接受一个字符串流,并根据一个指定的格式字符串进行解析,把结果放入到相应的指针所指的变量中去,它们的返回值为1表示解析成功,返回值为0表示失败. 从C到Python的转换函数是PyOb

Java 8的类型注解:工具和机会

在以前的Java版本中,开发者只能将注解(Annotation)写在声明中.对于Java 8,注解可以写在使用类型的任何地方,例如声明.泛型和强制类型转换等语句: @Encrypted String data;List strings;myGraph = (@Immutable Graph) tmpGraph; 乍一看,类型注解并不是Java新版本最炫的特性.事实上,注解只是语法!工具决定了注解的的语义(即,它们的含义和行为).本文介绍新的注解语法和实用工具,以提高生产力和构建更高质量的软件.

Java 8 新特性:扩展注解(类型注解和重复注解) ——诺诺"涂鸦"记忆

----------   诺诺学习技术交流博客.期待与您交流!    ---------- 详情请查看:http://blog.csdn.net/sun_promise  注解 (注:先回顾下JDK1.5版本出现的注解 ,然后再解释JDK 8的注解 更新内容.) 一.注解(JDK1.5) 1.注解(@): 注解就相当于一种标记,在程序中加了注解就等于为程序加了某种标记.(JDK1.5新特性). 2.作用: 告诉javac编译器或者java开发工具--向其传递某种信息,作为一个标记. 3.了解注解