类型提示
# Python类型提示
# 介绍
Python是一种动态类型语言,这意味着我们在编写代码的时候更为自由,运行时不需要指定变量类型。
但是与此同时IDE无法像静态类型语言那样分析代码,及时给我们相应的提示,比如字符串的split方法。由于不知道参数s是什么类型,所以当你敲s.的时候不会出现split方法的语法提示。
def split_str(s):
strs = s.split(",")
2
没有使用类型提示时,想说明变量的数据类型只能通过注释,例如:primes = [] # primes is a list。
此时我们就可以在声明变量时手动添加类型提示,这样在传错数据类型时,IDE才能正确显示智能语法提示。但类型提示仅仅只是一个规范约束,并不是一个语法限制,如果需要限制可以使用Pydantic库进行数据类型限制。
# 常用提示类型
int:整数类型
long:长整类型
float:浮点类型
bool:布尔类型
str:字符串类型
以下类型需要从typing模块中导入:
List:列表类型
Tuple:元组类型
Dict:字典类型
Set:集合类型
Literal:
Iterable:可迭代类型
Iterator:迭代器类型
Generator:生成器类型
# 类型提示声明
变量名: 提示的类型
变量名: 类型1 or 类型2 、变量名: 类型1 | 类型2
也可以同时声明两个提示的类型,表示既可以是
[类型1]也可以是[类型2]
# 使用例子
# int
# 声明变量是int类型
num: int = 0
2
# bool
# 声明变量是bool类型
bool_var: bool = True
2
# Dict
# 声明变量是字典类型
dict_var: Dict = {}
# 声明变量是字典类型,且键是字符串类型,值是int类型
dict_var: Dict[str, int] = {}
2
3
4
5
# List
# 声明变量是列表类型
primes: List = []
# 声明变量是列表类型、且元素为int类型
primes: List[int] = []
2
3
4
5
List[T]和Set[T]中只能传一个类型,传多个的话,IDE不会报错但运行时会报错。例如
List[int, str]运行会报错。
# Tuple
# 声明变量是元组类型、且元素为int类型
t: Tuple[int, ...] = 1, 2, 3
2
Tuple[T]中可以传多个类型,运行不会报错,如Tuple[int, str],但是需要值数量与类型数量对上,否则IDE会警告。可以写
...来表示值可能有多个,但写...时类型只能指定一个,否则会语法错误。
# 形参提示声明
不仅提供了函数参数列表的类型提示,也提供了函数返回的类型提示,且使用方法类似。
def 函数名(变量名: 类型) -> 返回值类型: ...
def hello(name: str) -> str:
return 'Hello ' + name
def greeting(name: str, obj: Dict[str, List[int]]) -> None:
print(name, obj)
2
3
4
5
# 类型别名
可以给复杂的类型取个别名,调用会更方便。
定义:别名 = 类型
引用:变量名: 类型别名 = 值
user_type = Tuple[Dict[str, str], ...]
user_obj = ({"name": "alis"})
2
3
ConnectionOptions = Dict[str, str]
Address = Tuple[str, int]
Server = Tuple[Address, ConnectionOptions]
def broadcast_message(message: str, servers: Server) -> None:
print(message, servers)
message = "发送服务器消息"
servers = (("127.0.0.1", 127), {"name": "服务器1"})
broadcast_message(message, servers)
> 发送服务器消息 (('127.0.0.1', 127), {'name': '服务器1'})
2
3
4
5
6
7
8
9
10
11
12
13
14
# 其他数据类型
# Callable
# 介绍
Callable表示是可调用的对象类型。可以用于函数参数的类型声明、判断对象是否可调用等。
# 使用
# 导入类型
from typing import Callable
def hello(s: str):
print(s)
# 判断对象是否是可调用类型
print(isinstance(hello, Callable))
# 声明变量是可调用类型,同时声明参数类型和返回值类型
a: Callable[[str], None] = hello
a("Hello")
2
3
4
5
6
7
8
9
10
11
12
# Any
# 介绍
Any是一种特殊的类型,可以将其当做任意类型。如果不声明类型,默认就是Any类型,但声明可以使语义更明确。
# 使用方法
# 导入类型
from typing import Any
name: Any = "hello"
2
3
4
# Union
# 介绍
Union可以用于声明多种类型,以表示值可能为多种类型。
声明单个类型同等于该类型:
Union[int] == int重复的类型参数会自动忽略掉:
Union[int, str, int] == Union[int, str]会自动忽略类型参数顺序:
Union[int, str] == Union[str, int]Union嵌套Union会自动解包:
Union[Union[int, str], float] == Union[int, str, float]
# 使用方法
Union[类型1, 类型2...]
# 导入类型
from typing import Union
# 表示name参数可能为int或str类型
def hello(name: Union[int, str]) -> None:
print("hello " + name)
2
3
4
5
6
# Optional
# 介绍
Optional可以表示该参数为可选参数类型,表示既可以传指定的类型,也可以为不传。
# 使用方法
Optional[类型] 其中只能写一个类型。
# 导入类型
from typing import Optional
# 表示name参数既可以传str类型,也可以传None
def foo_func(name: Optional[str] = "alis"):
print(name)
2
3
4
5
6
# Literal
# 介绍
Literal是用于只接受指定字面值的枚举类型。
# 使用方法
Literal[值1, 值2, ...]
# 导入类型
from typing import Literal
# 表示gender参数只接受"male"、"female"、"Unknown"这三个值
def foo_func(gender: Literal["male", "female", "Unknown"]):
print(gender)
2
3
4
5
6
# Annotated
# 介绍
Annotated不是类型,而是一个内置的泛型工具,用于在类型声明中附加额外的元数据,且不改变原始类型本身。
语法:
Annotated[实际类型, 元数据1, 元数据2, ...]
# 使用
from typing import Annotated
from fastapi import Query
# 传统写法
@app.get("/items/")
def read_items(q: str = Query(min_length=3)):
...
# Annotated写法
# 推荐使用该写法,虽然两者效果一样,但是该写法更加清晰、可读性更强
@app.get("/items/")
def read_items(q: Annotated[str, Query(min_length=3)]):
...
2
3
4
5
6
7
8
9
10
11
12
13