利用typing做到更好的类型提示
mypy
mypy是一个可以帮助我们检查类型的第三方库,通过 pip insatll mypy
安装,然后执行 mypy <py文件>
即可自动帮我们检测数据类型是否使用正确.例如我们有这样一段代码。
from typing import List
my_type = List[int]
test: my_type = [1, 2, 3]
我们期望创建一个列表,列表内部的数据是int类型,当我们按照规矩创建 test
之后利用 mypy
检查,可以得到结果
但是假如我们并不按规矩创建 test
呢?例如我们创建 test
为 test: my_type = [1, 2, "three"]
,此时再利用 mypy
检查会得到结果
是的,mypy会明确指出不合预期的数据类型,并告诉我们发生在那里
List的使用
当我们需要列表的内部是int类型时我们可以这样操作
from typing import List
def test_fun(value: List[int]):
return sum(value)
# test_fun([1, 2, 3])
Tuple
当需要传入一个元祖时我们可以使用 Tuple
from typing import Tuple
test: Tuple[str, int, float] = ("one", 2, 3.0)
可以发现Tuple
与List
略有不同, Tuple
需要指定每一个位置上元素的类型。假如我们并不关注某个元素的数据类型时,我们可以直接使用内置类型 tuple
test: tuple = ("one", 2, 3.0, [4, 5, 6])
Dict
当我们需要字典的内部键值对类型时我们可以这样操作
from typing import Dict
my_type = Dict[str, int]
# test: my_type = {"one": 1, "two": 2, "three": 3}
注意此段代码第2行中,str指定的是字典中每一个键的类型;int指定的是字典中每一个值的类型。
TypedDict
上面我们用 Dict
做到了类型提示,但假如我们不满足于此,我们想为每一个键设置不同类型的值的提示要怎么办呢?利用 TypeDict
可以解决这个问题。
from typing import TypedDict, List
class MyType(TypedDict):
one: str
two: List[int]
# test: MyType = {"one": "str", "two": [1, 2]}
Union
当我们输入的参数类型有多种可选项时可以使用 Union
from typing import Union
def test(value: Union[str, int]):
return value
# test(value="1")
# test(value=2)
需要注意的是从Python3.10开始 Union
被替换为 |
意味着 Union[X, Y]
等价于 X | Y
def test(value: str | int):
return value
# test(value="1")
# test(value=2)
Callable
当你需要使用一个函数作为参数时,这个参数的类型提示可以使用 Callable
from typing import Callable
def test_1(x: int, y: int) -> int:
return x + y
def test_2(x: int, y: int, fun: Callable) -> int:
output = fun(x, y)
return output
# test_2(1, 2, test_1)
同时我们可以利用 Callable
指定被传入函数的参数的类型提示,规则为 [[传入参数1的类型, 传入参数2的类型...], 返回数据的类型]
from typing import Callable
def test_1(x: int, y: int) -> int:
return x + y
def test_2(x: int, y: int, fun: Callable[[int, int], int]) -> int:
output = fun(x, y)
return output
# test_2(1, 2, test_1)
Any
当传入的参数可以为任何类型的时候可以使用 Any
from typing import Any
def test(value: Any):
return value
Optional
当你的函数参数有默认值,导致参数不是必须要传入的参数,那么你可以尝试使用 Optional
来做到类型提示
from typing import Optional
def test(value: Optional[int] = None):
return value
# test()
从上面的代码我们发现, Optional
作用几乎和带默认值的参数等价。但其实是有些许区别的,假设我们声明参数为 value: int = None
用静态检查工具去检查代码时会返回错误给我们。而我们为 value
指定数据类型为 Optional[int]
但默认值为 None
经过静态检查工具也不会返回错误。所以其实Optional[X]
是等价于 Union[X, None]
的。
Sequence
Sequence
所提示的是任何可以被索引的数据: 列表,元祖,字符串等
from typing import Sequence
def test(value: Sequence[str]):
print(value)
# test(["1", "2", "3"])
# test(("1", "2", "3"))
# test("1233")
注意在定义函数时 []
中只可以指定一个数据类型,意味着在我们传入的列表或者元祖等可索引数据时,内部元素的数据类型需要是统一的。