python3类型注解

一、类型注解说明

我们知道 Python 是一种动态语言,变量以及函数的参数是不区分类型。因此我们定义函数只需要这样写就可以了:

1
2
def add(x, y):
return x + y

坏处就是对于别人代码,无法一眼判断出参数的类型,IDE 也无法给出正确的提示。所以python3.5+就提供了类型注解:

1
2
def add(x: int, y: int) -> int:
return x + y

: 类型 的形式指定函数的参数类型,用 -> 类型 的形式指定函数的返回值类型。

Python 解释器并不会因为这些注解而提供额外的校验,没有任何的类型检查工作。也就是说,这些类型注解加不加,对你的代码来说没有任何影响

类型注解的好处:

  1. 让别的程序员看得更明白。
  2. 让 IDE 了解类型,从而提供更准确的代码提示、补全和语法检查(包括类型检查)。

在函数的 __annotations__ 属性中会有你设定的注解:

1
2
3
4
def add(x: int, y: int) -> int:
return x + y

print(add.__annotations__)

输出:

{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}

二、类型标注支持

1.函数参数以及返回值

1
2
def add(x: int, y: int) -> int:
return x + y

2.变量(3.6+后支持)

1
2
3
4
5
from typing import List
info = {"a": 1, "b": "b"}
a: int = info["a"]
b: str = info["b"]
l: List[int] = [1, 2, 3]

3. Any类型

Any 是一种特殊的类型。静态类型检查器将所有类型视为与 Any 兼容,反之亦然, Any 也与所有类型相兼容。

这意味着可对类型为 Any 的值执行任何操作或方法调用,并将其赋值给任何变量:一般用于不确定的返回值上。

1
2
3
4
from typing import Any

def fun(item: Any)->Any:
pass

4. object类型

Any 相似,所有的类型都是 object 的子类型。然而不同于 Any,反之并不成立: object 不是 其他所有类型的子类型。

这意味着当一个值的类型是 object 的时候,类型检查器会拒绝对它的几乎所有的操作。把它赋值给一个指定了类型的变量(或者当作返回值)是一个类型错误。比如说:

1
2
3
4
def fun(item: object) -> int:
# mypy test.py会输出:error: "object" has no attribute "magic"
item.magic()
return 1

使用 object 示意一个值可以类型安全地兼容任何类型。使用 Any 示意一个值地类型是动态定义的。

三、高级用法

1.类型别名

类型别名通过将类型分配给别名来定义,用于简化复杂类型注解。

1
2
3
4
5
6
7
8
from typing import Dict, Tuple, Sequence

ConnectionOptions = Dict[str, str]
Address = Tuple[str, int]
Server = Tuple[Address, ConnectionOptions]

def broadcast_message(message: str, servers: Sequence[Server]) -> None:
pass

等同于以下注解:

1
2
3
4
def broadcast_message(
message: str,
servers: Sequence[Tuple[Tuple[str, int], Dict[str, str]]]) -> None:
pass

2.Callable

期望特定签名的回调函数的框架可以将类型标注为 Callable[[Arg1Type, Arg2Type], ReturnType]

1
2
3
4
5
6
7
8
from typing import Callable

def feeder(cbfun: Callable[[], str]) -> None:
pass

def async_query(on_success: Callable[[int], None],
on_error: Callable[[int, Exception], None]) -> None:
pass

3.多类型注解

1
2
3
4
from typing import Union

def fun(i: Union[str, int])->Union[str, int]:
return i * 2

四、类型注解检测

通过 mypy 库来检验最终代码是否符合注解。mypy是一个Python命令行应用 (Python command line application ),可以轻松集成到我们的代码流中。

需要安装:pip isntall mypy

例如:test.py有以下内容

1
tmp: int = "test"

执行命令:mypy test.py

如果类型都符合,则不会有任何输出,否则就会给出类似输出:

test.py:1: error: Incompatible types in assignment (expression has type "str", variable has type "int")

坚持原创技术分享,您的支持将鼓励我继续创作!