python类型注释
Python是当今使用的最流行的编程语言之一,并且有充分的理由:它是开源的,具有广泛的用途(例如Web编程,业务应用程序,游戏,科学编程等等),并且有一个充满活力和敬业精神的社区来支持它。 这个社区的原因是我们在Python软件包索引 (PyPI)中拥有如此众多,种类繁多的软件包,以扩展和改进Python并解决不可避免的小问题。
在本系列中,我们研究了七个PyPI库,它们可以帮助您解决常见的Python问题。 今天,在最后一篇文章中,我们将探讨mypy “类固醇的Python 轻巧套 ”。
py
Python是一种“动态类型”语言。 但是,有时让其他人(无论是机器人还是人类)知道期望的类型是件好事。 传统上,人类优先考虑:函数的输入和输出类型在文档字符串中描述。 MyPy允许您使机器人处于平等地位,让他们知道要使用的类型。
让我们看下面的代码:
def add_one
(
input
) :
return
input +
1
def print_seven
(
) :
five
=
"5"
seven
= add_one
( add_one
( five
)
)
print
( seven
)
调用print_seven会引发TypeError,通知我们我们无法添加字符串和数字:我们无法添加“ 5”和1。
但是,直到运行代码,我们才能知道这一点。 运行代码(如果正确的话)会在屏幕上产生打印输出:副作用。 相对而言,一种相对无害的副作用,但仍然是一种副作用。 是否可以这样做而又不会冒任何副作用?
我们只需要让机器人知道会发生什么。
def add_one
(
input :
int
) -
>
int :
return
input +
1
def print_seven
(
) -
>
None :
five
=
"5"
seven
= add_one
( add_one
( five
)
)
print
( seven
)
我们使用类型注释来表示add_one需要一个整数并返回一个整数。 这不会更改代码的作用。 但是,现在我们可以要求安全的机器人为我们找到问题了。
$ mypy typed.
py
typed.
py :
6 : error: Argument
1 to
"add_one" has incompatible
type
"str"
; expected
"int"
对于我们做错的事情,我们有一个很好的可读性说明。 让我们修复print_seven 。
def print_seven
(
) -
>
None :
five
=
5
seven
= add_one
( add_one
( five
)
)
print
( seven
)
如果我们对此进行mypy操作,将不会有任何抱怨; 我们修复了该错误。 令人高兴的是,这也导致了工作代码。
当然,Python类型系统会变得很深。 遇到如下特征的签名并不少见:
from typing
import Dict
, List
, Mapping
, Sequence
def unify_results
(
results1: Mapping
[
str
, Sequence
[
int
]
]
,
results2: Mapping
[
str
, Sequence
[
int
]
]
) -
> Dict
[
str
, List
[
int
]
] :
pass
在那种情况下,请记住,一切都是对象:是的,甚至是类型。
ResultsType
= Mapping
[
str
, Sequence
[
int
]
]
ConcreteResultsType
= Dict
[
str
, List
[
int
]
]
def unify_results
( results1: ResultsType
, results2: ResultsType
) -
> ConcreteResultsType:
pass
我们将输入类型定义为抽象类型(使用Mapping和Sequence )。 例如,这允许发送defaultdict ,该字符串将字符串映射到元组。 这通常是正确的选择。 我们还选择保证签名中的具体返回类型。 这更具争议性:有时为了减少担保以允许将来的更改来更改返回类型,这很有用。
MyPy允许渐进式注释:并非必须立即注释所有内容。 没有任何注释的函数将不进行类型检查。
继续注释!
查看本系列中的前几篇文章:
python类型注释