参考链接:https://blog.csdn.net/qq_33801641/article/details/119793104
# 一、python 类型提示概述
python
是一种动态类型语言,这意味着我们在编写代码的时候更为自由,运行时不需要指定变量类型。但是与此同时 IDE
无法像静态类型语言那样分析代码,进而反馈响应的提示。如在下面的代码中
def split_str(s): | |
strs = s.split(",") | |
return strs |
由于不知道参数 s
是什么类型,所以当在 pycharm
中输入 s. 的时候不会出现 split
的语法提示。可以使用如下的程序进行类型提示,从而在程序编写时可 IDE
可以预设输入参数和输出参数类型
def split_str2(s: str) -> [str]: | |
strs = s.split(",") | |
return strs |
如果传入的参数类型错误,并不影响程序的运行,但是 IDE
会有 warning
,如下图所示,故类型提示更像是一个规范约束,并不是一个语法限制
# 二、常用类型提示
- int, long, float: 整形,长整型,浮点型;
- bool, str: 布尔型,字符串类型;
- List, Tuple, Dict, Set: 列表,元组,字典,集合;
- Iterable, Iterator: 可迭代类型,迭代器类型;
- Generator: 生成器类型;
前两行小写的不需要调用库即可使用,后三行都需要通过如from typing import List
格式进行模块的导入。
如下程序是较为复杂的类型提示方式
from typing import Tuple, List, Dict | |
# 输入第一个参数是 int 类型的数据,第二个参数是 string,第三个是 float,第四个是 bool 或 str;返回一个 Tuple 类型的数据,第一个元素是 List,第二个元素是 Tuple,第三个元素是 Dict,第四个元素可以是字符串或布尔 | |
def add(a: int, string: str, f: float, b: bool or str) -> Tuple[List, Tuple, Dict, str or bool]: | |
list1 = list(range(a)) | |
tup = (string, string, string) | |
d = {"a": f} | |
bl = b | |
return list1, tup, d, bl | |
print(add(1, "2", 123, True)) | |
# 输出结果 | |
# ([0], ('2', '2', '2'), {'a': 123}, True) |
⚠️⚠️⚠️在使用类型提示时一些需要注意的地方:
(1)指定类型时可以使用 list
、 set
、 dict
、 tuple
,但是不能像上述例子中一样指定里面元素的数据类型;
(2) List[T]
和 Set[T]
只能传入一个参数类型,传入多个会报错,但是 Tuple
可以传入多个类型;
(3)在使用 Tuple[T]
的时候,元素的数量必须和类型提示的元素数量一致,如果想要像 List[T]
一样指定一个类型,可以对所有元素生效,则需要在类型后添加 ...
即可,如 Tuple[int, ...]
。
# 三、类型别名
可以将复杂的类型赋予一个简单的别名,如下所示
# 别名 | |
vector = List[float] | |
var: vector = [1.1, 2.2] | |
# 等价写法 | |
var: List[float] = [1.1, 2.2] |
# 四、自定义新类型
可以使用 NewType(name, tp)
创建一个新类型,这个函数返回其原本的值,静态类型检查器会将新类型看作是原始类型的一个子类, tp
就是原始类型,如下程序所示
from typing import NewType | |
UserId = NewType('UserId', int) | |
def name_by_id(user_id: UserId): | |
print(user_id) | |
name_by_id(42) # Fails type check | |
name_by_id(UserId(42)) # OK | |
print(type(UserId(5))) | |
# 输出结果 | |
# 42 | |
# 42 | |
# <class 'int'> |
# 六、TypeVar 类型
TypeVar
类型的源码解释(部分)如下所示
class TypeVar(_Final, _Immutable, _root=True): | |
"""Type variable. | |
Usage:: | |
T = TypeVar('T') # Can be anything | |
A = TypeVar('A', str, bytes) # Must be str or bytes |
使用方法如下所示
# 可以是任意类型 | |
T = TypeVar('T') | |
def test(name: T) -> T: | |
print(name) | |
return name | |
test(11) | |
test("aa") | |
# 输出结果 | |
# 11 | |
# aa |
# 可以是 int,也可以是 str 类型 | |
AA = TypeVar('AA', int, str) | |
num1: AA = 1 | |
num2: AA = "123" | |
print(num1, num2) | |
# 输出结果 | |
# 1 123 |
# 七、任意类型(Any Type)
一种特殊的写法是 Any
,静态类型检查器会将每种类型都是为与 Any 兼容,将 Any 是为与每种类型兼容,使用方法如下
from typing import Any | |
def foo(item: Any): | |
# Typechecks; 'item' 可以是任意类型 | |
print(item) |
def legacy_parser(text): | |
... | |
return data | |
# 上述写法等价于下述写法 | |
# 所有没有返回类型或参数类型的函数将隐式默认使用 Any | |
def legacy_parser(text: Any) -> Any: | |
... | |
return data |
# 八、联合类型(Union)
联合类型, Union[int, str]
表示既可以是 int
,也可以是 str
,程序解释如下
vars: Union[int, str] | |
# 等价于 | |
vars: [int or str] | |
vars: Union[int] | |
# 等价于 | |
vars: int |
# 九、参数可 None 类型(Optional)
使用 Optional
是为了让 IDE
识别到该参数有一个类型提示,可以传指定的类型和 None,即参数是可选单非必要的, Optional[int]
等价于 Union[int, None]
,使用案例如下
def foo_func(arg: Optional[int] = None): | |
print(arg) | |
foo_func() | |
foo_func(1) | |
# 输出结果 | |
# None | |
# 1 |