python 是动态语言,运行时不需要声明变量类型,但是从长远来看(后期维护,代码可读性,方便开发,重构)来看,个人觉得这个是必要的,Python 3.5 引入了一个类型系统,允许开发者指定变量类型。它的主要作用是方便开发,python解释器运行时将会过滤掉类型提示。
它使用通过PEP-3107(Python 3.0+)添加的函数标注以及通过PEP-526(Python 3.6+)添加的变量标注。这些可以使得在编写代码时,
- 使用:语句将信息附加到变量或函数参数中。
- -> 运算符用于将信息附加到函数/方法的返回值中。
这种方法的好处是:
- 这是实现类型提示的规范方式,这意味着是类型提示中最干净的一种方式。
- 因为类型信息附加在代码的右侧,这样我们可以立刻明晰类型。
缺点是:
- 它不向后兼容。至少需要Python 3.6才能使用它。
- 强制你导入所有类型依赖项,即使它们根本不在运行时使用。
- 在类型提示中,会使用到复合类型,例如List[int]。而为了构造这些复杂类型,解释器在首次加载此文件时需要执行一些操作。
这样发现,最后两点与我们之前列出的类型系统的初始目标相矛盾:
即在运行时基本上将所有类型信息作为注释处理。
为了解决这些矛盾,Python 3.7引入了 PEP-563 ~ postponed evaluation of annotations 。
加入以下语句,解释器将不再构造这些复合类型。(亲测:必须是文件的第一行加入这个,不然报错)
from __future__ import annotations
类型提示的优点:
- 便于阅读理解
- 消除认知开销,易于调试,轻松了解对象类型和如何调用
- 易于重构
1,变量类型提示
a: int = 1
b: float = 1.1
c: bool = True
d: list = ["1", "2", "3"]
e: dict = {"a": "b"}
f: set = {"a", "b", "c"}
g: tuple = ("a", "b", "c")
2,函数类型提示
def test(a:int, b:list) -> return_type:
....
3,使用标准库 typing 标记复合类型
from typing import Any,Union,List,Dict,TypedDict,Callable,Optional,Sequence
1,list用法
a: List[str] = ['a', 'b']
2,Dict 用法
b: Dict[str, str] = {'a': '1', 'b': '2'}
3,Union 用法
Union[a, b](或 a | b)表示 a 或 b
c: Dict[str, Union[str, int]] = {'a': '1', 'b': 2}
4,Callable 用法
当你需要传入一个函数作为参数的时候,这个参数的类型提示可以为 Callable。
def test(a: int, func: Callable) -> int:
...
5,Any 用法
任意类型
d: Any = 1
6,Optional 用法
如果你的函数使用可选参数,具有默认值,那么你可以使用类型模块中的 Optional 类型
def test(a: Optional[int] = 1) -> int:
...
7,Sequence 用法
Sequence 类型的对象是可以被索引的任何东西:列表、元组、字符串、对象列表、元组列表的元组等。
def test(a: Sequence):
print(a[0])
...
8,Tuple 用法
Tuple 类型的工作方式与 List 类型略有不同,Tuple 需要指定每一个位置的类型:
t: Tuple[int, int, int] = (1, 2, 3)
如果你不关心元组中每个元素的类型,你可以继续使用内置类型 tuple。
t: tuple = (1, 2, 3, ["1", "2"], {"name": "zsc"})
9,嵌套用法
a: List[dict[str, int]] = [{'a': 1},{'b':2}]