前记
现在,新出的语言都是走静态语言的路线,动态语言也都开始引入类似于静态语言的增强,而Python通过TypeHints来引入静态语言的增强.
一开始用着Python写起代码非常爽,但是在大项目且多人合作时,会发现重构代码非常艰难或者不敢去修改历史代码.在引入TypeHints后,通过IDE的增强或者mypy等检查,能使我们重构代码方便,且让代码健壮.
历史进程
Python作为一个非常灵活的动态语言,也不是一下子就拥有TypeHints的,而是通过PEP 3107, PEP 483, PEP 484,PEP 526,PEP 544,PEP 586,PEP 589, PEP 591,慢慢的使TypeHint变得完整
1.PEP 3107 TypeHints的主要依赖
PEP 3107,在06年就已经提出来了,TypeHints的主要依赖,然,而此方案一开始跟TypeHints并没有什么关系,官方对于这个提案处于放养阶段,只是让函数拥有了注解功能:
2.PEP 483
PEP 483并没有去怎么实现TypeHints,而是简明扼要的写清楚 Python 的类型系统建设方向、边界.理清Type是语法分析的概念,而class是运行时概念,class都是一个type,但type不一定是class.
同时PEP 483还介绍了一些常用的基础类型Any, Callabel,Optional, Tuple等,同时还支持泛型,也支持使用注释标记类型,防止被循环引用
3.PEP484
PEP 484是TypeHints的核心,首先它确定了Python仍将是一种动态类型语言,并不强制Python成为静态语言,同时讲解了TypeHints的几个新特性:
- 为已经存在的库添加类型描述文件(.pyi),用这些文件描述 Python 代码的带类型签名,可以通过运行mypy去调用这些文件检查python代码类型是否准确.
- 允许使用 @overload 进行类型重载,但是只是用于代码检查时,实际上只有未被overload装饰的函数才能真正的被使用到
- 使用typing.TYPE_CHECKING,让一些库只有在运行检查时才引入 1234import typingif typing.TYPE_CHECKING:import expensive_mod
4.PEP 526
上面一直在说的都是函数,而在PEP526后,变量和类属性都可以支持TypeHints了, 在PEP526后可以如下使用:
上面的代码实际上并未创建变量,而是把变量和类型存在全局的__annotations__中, 如果是类属性,
那么变量则会存在类的__annotations__中.
5.PEP544
544中主要说的是静态鸭子类型,我们都知道Python的动态类型是动态鸭子类型,当认为一个类看起来像鸭子,那就认为他是鸭子,PEP544也是这样,只不过把确定的结果当成TypeHint反馈给代码检查工具.如官网给的例子:
代码中定义了 Bucket 这种类型,并且提供了两个类成员。这两个类成员刚好是 Interator 的定义。 那么在实际使用中,就可以使用 Bucket 替换 Iterable。
6.PEP563
在编写树节点的时候,如果我们使用TypeHints,那我们就会碰到循环依赖的问题,而PEP563就是为了解决这个问题的,在使用PEP563后我们可以如下通过使用'变量'
来解决:
7.Python3.8 PEP 对TypeHints的增强
在Python3.8中,多了几个PEP,不过比较简单,只是对TypeHint的一个完善
PEP586非常简单,只是支持以字面量来作为类型使用, 但一般不推荐这样用:
123456789Literal[26]Literal[0x1A] # Exactly equivalent to Literal[26]Literal[-4]Literal["hello world"]Literal[b"hello world"]Literal[u"hello world"]Literal[True]Literal[Color.RED] # Assuming Color is some enumLiteral[None]PEP589则支持对每个dict的key进行类型标注
12345678910from typing import TypedDictclass Movie(TypedDict):name: stryear: intmovie: Movie = {'name': 'Blade Runner', 'year': 1982}# 没有PEP589之前只能如下编写, 同时不能对每个key进行检查...from typing import Dict, Unionmove_dict: Dict[str, Union[str, int]]PEP591增加 final / Final, final是一个装饰器,用于声明一个类不能被更改或者继承,而Final则是声明变量不可被修改
8.总结
在Python中,TypeHints能帮我们写的代码更加健全,同时借助IDE,我们也可以非常快速的编写或者更改代码,减少我们一些开发时间.
不过Typehints只能在编写代码时,被IDE检查进行提示,或者被检查工具用于代码检查,在实际代码中并不会生效,但是由于Python把TypeHints的一些变量存放在相关的__annotations__中,所以我们还是可以在运行中调用__annotations__提取TypeHints并对参数进行类型判断或者转换,这在web中非常有用,目前有个叫Pydantic
的库就是专门处理这类应用的,非常不错
本文链接: http://so1n.me/2020/06/03/通过Pep了解TypeHints/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
