python类型注解详解,Python3 之类型注解

0 引言:定义一个线段

假设我们使用 Python 实现数学中的整点线段的概念,即 $L = [a,b]$, 且 $a,b \in Z$。使用 Python 可以这样写:

类 LineSegment 模拟了线段的形态与长度。但是,这样的写法是不是有点繁琐?为了更加人性化,Python 提供了 typing 模块,让我们可以对代码进行注解。

1 typing 注解 Python

如果想要声明函数参数和返回值的类型,您可以这样做:

这就是被称为 function annotation 的写法。使用冒号 : 加类型名来代表参数的类型,使用箭头 -> 加类型表示返回值的类型。注解部分不会被 Python 解析器所解析。只是一种注解的方式,类似于:

注意:由于 Python 是动态语言,所以注解是对函数参数和返回值的“注释”,没有强制定义的作用。

比如,您像这样 add(1.2, 3.0) 传入参数,Python 解释器并不会报错。

输出结果并没有报错:

1.1 使用 inspect 检查 python 对象的类型

如果您想要让 Python 对类型进行检查,可以借助模块 inspect。比如:

如果对函数的参数进行检查呢?这个需要借助 sig=inspect.signature:

输出结果:

接着,可以直接获取函数的信息:

输出结果:

Parameter 是 inspect 下的一个类,可以把它看做是一个有序字典,里面存放了函数的参数和参数类型,遍历 params.values() 的 annotation 属性会得到参数的注解类型:

输出结果是:

您可以这样定义类型检查函数:

1.2 利用 python 对象的 __annotations__ 属性检查类型

下面以定义一个商品对象:

输出结果是(Any 代表 Python 很难表达的形式或者类型):

可以看出,__annotations__ 属性与 1.1 中的 params.values()[k].annotations 很相似。

这样,可以改写其类型检查函数为:

2 dataclass 提供强大的类型注解机制

dataclass 的定义位于 PEP-557,一个 dataclass 是指“一个带有默认值的可变的 namedtuple”,广义的定义就是有一个类,它的属性均可公开访问,可以带有默认值并能被修改,而且类中含有与这些属性相关的类方法,那么这个类就可以称为 dataclass,再通俗点讲,dataclass 就是一个含有数据及操作数据方法的容器。

我们先看看 dataclass 的参数:

key

含义

init

指定是否自动生成__init__,如果已经有定义同名方法则忽略这个值,也就是指定为True也不会自动生成

repr

同init,指定是否自动生成__repr__;自动生成的打印格式为class_name(arrt1:value1, attr2:value2, ...)

eq

同init,指定是否生成__eq__;自动生成的方法将按属性在类内定义时的顺序逐个比较,全部的值相同才会返回True

order

自动生成__lt__,__le__,__gt__,__ge__,比较方式与eq相同;如果order指定为True而eq指定为False,将引发ValueError;如果已经定义同名函数,将引发TypeError

frozen

设为True时对field赋值将会引发错误,对象将是不可变的,如果已经定义了__setattr__和__delattr__将会引发TypeError

参数 unsafehash 的使用比较复杂,当设置为unsafehash=True时将会根据类属性自动生成__hash__,然而这是不安全的,因为这些属性是默认可变的,这会导致hash的不一致,所以除非能保证对象属性不可随意改变,否则应该谨慎地设置该参数为True。对于 unsafehash=False 的情况将根据eq和frozen参数来生成__hash__,下面单独列出:

参数设置

含义

eq=True,frozen=True

__hash__将会生成

eq=True,frozen=False

__hash__将被设为None

eq=False,frozen=True

__hash__将使用超类(object)的同名属性(通常就是基于对象id的hash)

注意:最好去掉了__init__方法,以确保 dataclass 装饰器可以添加它生成的对应方法。

如果要覆盖 __init__,我们将失去 dataclass 的优势,因此,如果要处理任何附加功能可以使用新的 dunder 方法:__post_init__,让我们看看__post_init__方法对于我们的包装类来说是什么样子的。

由于 Python 支持中文作为变量名、类名、函数名等,所以,我可以这样定义一个 Python 类:

输出结果:

上面的代码模拟了出售商品的清单,整个代码看起来都很清爽。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值