插件窝 干货文章 python的type hints(类型标注、类型注解、类型提示)示例详解

python的type hints(类型标注、类型注解、类型提示)示例详解

类型 code 注解 class 918    来源:    2024-10-28

1. 前言

type hints(类型标注、类型注解、类型提示)是指在代码中涉及到数据交互的地方,提供数据类型的注解(显式的说明)。类型注解可以帮助第三方IDE工具(PyCharm)对代码进行类型推断,协助做代码提示;能帮助开发者自身对变量进行类型标注。类型注解可分为:变量的类型注解、函数(方法)形参列表和返回值的类型注解。总而言之,加上注解之后,我们可以直观的看出变量、函数(方法)参数列表和返回值到底是个什么东西(什么类型)。

2. 简单的类型注解

简单的类型注解(基本类型注解):可以使用int、str和list等基本类型来注解变量、函数参数和返回值的类型。

2.1 变量的类型注解

为变量设置类型注解,语法格式为:变量: 类型,代码示例如下。

num: int = 10
s: str = "hello"
my_list: list = [1,2,3,4]
my_tuple: tuple = (null,2,3)

class Student:
    pass
stu: Student = Student()

除了使用变量: 类型这种格式外,还可以在注释中进行类型注解,语法:# type: 类型,示例代码如下。

num = 10  # type: int
s = "hello"  # type: str
my_list = [1,2,3,4]  # type: list
my_tuple = (null,2,3)  # type: tuple

2.2 函数(方法)的类型注解

给函数(方法)形参类型和返回值类型进行标注,定义语法如下:

def 函数(或方法)名(形参1: 类型, 形参2: 类型, ...) -> 返回值类型:
    pass

示例代码如下。函数注解的信息,保存在__annotations__属性中可以来调用。

def sum(x: int, y: int) -> int:
    return x+y
    
sum(null,2)
print(sum.__annotations__)
# 输出:{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}

2.3 安装mypy

注意:类型注解仅仅是提示性的,不是决定性的,就算你类型注解错误也不会报错。像下面的代码就不会报错:变量num的类型注解为int,却把字符串"hello"赋给它了;变量s的类型注解为str,却把整数10赋给它了;函数sum的形参x,y和返回值都是int类型,却把字符串"hello"和"world"分别赋给参数x,y。

num: int = "hello"
s: str = 10

def sum(x: int, y: int) -> int:
    return x+y

print(sum(null,2))
print(sum("hello ","world"))

我们可以通过mypy库来检验最终代码是否符合设定的类型注解。mypy是python中有关类型的静态分析工具。

#安装 mypy
pip install mypy

# 执行下面代码来查看是否符合设定的类型注解
mypy test.py

3. 标准库typing模块

上面只是简单的类型注解,传入的类型表述能力有限,不能说明复杂的类型组成情况,因此可以引入typing模块来实现复杂的类型表达,typing是在python 3.5 才开始有的模块。

3.1 List, Tuple, Set, Dict基础用法

(1)List[int]表示由整数(int)组成的列表;

(2)Tuple[int, str, bool]表示由三个对象组成的元组,其中这三个对象的类型分别为int, str, bool;

(3)Set[int]表示由整数(int)组成的集合;

(4)Dict[int, str]表示键是int,值是str的字典。

代码示例如下

from typing import List, Tuple, Set, Dict

my_list: List[int] = [1, 2, 3, 4, 5, 6]
my_tuple: Tuple[int, str, bool] = (null, "hi", True)
my_set: Set[int] = {1, 2, 3}
my_dict: Dict[int, str] = {1: "a", 2: "b", 3: "c"}

3.2 Union和Optional

对于更为复杂的类型注解,我们可以使用联合类型注解Uniontyping模块中的Union可以给一个变量或函数返回值标注多种类型,它表示的意思。例如:data: Union[str, bytes],变量data可以是str类型或bytes类型。在Python 3.10版本及以后,推荐使用|运算符代替Union。示例代码如下:

from typing import Union

my_list: List[Union[int,str]] = [1,3,5,"hello,"world"]
my_dict: Dict[str, Union[str, int]]= {"name": "Jack", "age": 16}

(1)List[Union[str,int]]:该列表中的元素可以是int类型的对象,也可以是str类型的对象;

(2)Dict[str, Union[str, int]]:该字典中的键为str,值是str和int都可以。

  typing模块中的Optional类型,它是Union的一个特殊情况。如果一个变量可以是None或其他类型,推荐使用Optional类型,其中Optional[int]等价于Union[int, None]Optional[Union[str, int, float]]等价于Union[str, int, float, None]。对了,Optional[]里面只能写一个数据类型,代码示例如下

num1: Optional[Union[int, str, float]] = None
num2: Union[int, str, float,None] = None

3.3 类型别名(type alias)

因为在python中一切皆为对象,所以可将复杂一点的类型赋给某个变量,也就是起个别名,这样使用起来较为方便。

var_int = int
num1: int = 10
num2: var_int
# 以上两种类型注解的方式等价

from typing import List, Dict

list_alias = List[int]
dict_alias = Dict[str, list_alias]
my_dict: dict_alias = {"a": [1,2,3], "b": [4,5,6]}
# 以上两种类型注解的方式等价

3.4 Callable

Callable是一个可调用对象类型,语法格式为:Callable[[参数类型], 返回类型],包括可调用对象的参数类型和返回值类型。例如:Callable[[int], str],这里的int表示可调用对象的参数类型,str代表可调用对象的返回值类型。

from typing import Callable

def print_name(name: str) -> None:
    print(f"name:{name}")

def get_name(func: Callable[[str], None]):
    return func

# 利用isinstance(对象, Callable)来判断当前对象是否为可调用对象
# print(isinstance(print_name, Callable))  # 输出 True

fun = get_name(print_name)
fun("zhangsan")

3.5 TypeVar和Generic

泛型是一种可以在不指定具体类型的情况下编写可复用代码的技术。Python中的泛型是使用typing模块中的TypeVarGeneric进行实现的。TypeVar用于定义泛型类型变量,而Generic用于定义泛型类。

(1)泛型类型变量:用于表示不确定的类型。泛型类型变量通常使用大写字母命名,比如 T、U、V。

T = TypeVar('T')  # 创建一个泛型类型变量T,T可以是任意类型

(2)泛型函数:是可以接受一个或多个泛型类型参数的函数,这些参数可以用来指定函数参数的类型、返回值的类型或函数内部使用的其他类型。

from typing import TypeVar,List

T = TypeVar('T')

def print_list(my_list: List[T]) -> None:
    print(my_list)

print_list([2,4,6,8])  # 可以打印整数列表
print_list(["hh","aa","www"])  # 可以打印字符串列表

(3)约束泛型:有时候我们希望泛型类型只能是特定的类型,在这种情况下,我们可以使用泛型约束来限制泛型类型的范围。

from typing import TypeVar,List

T = TypeVar('T',int,float)  # 泛型类型变量T可以是int,也可以是float类型

def print_list(my_list: List[T]) -> None:
    print(my_list)

print_list([2,4,6,8])  # 可以打印整数列表
print_list([1.2, 2.3, 3.4])  # 可以打印浮点数列表

(4)泛型类:是可以接受一个或多个泛型类型参数的类。这些参数可以用来指定类的属性类型、方法参数类型、方法返回值类型或类内部使用的其他类型。

from typing import TypeVar, Generic

T = TypeVar('T')

class Student(Generic[T]):  # 继承Generic[T],
    def __init__(self, name: T) -> None:
        self.name = name

    def get_name(self) -> T:
        return self.name
    
stu = Student[str]("zhangsan")  # 或者stu = Student("zhangsan")
print(stu.get_name())  # 输出:zhangsan

3.6 Any 类型

静态类型检查器将所有类型视为与Any兼容,这意味着可对类型为Any的值执行任何操作或方法调用,并将其赋值给任何变量。

from typing import Any

a = 10 # 变量a在默认情况下为Any类型

def print_info(var: Any) -> None:
    print(var)

print_info(11)
print([1,2,3,4])
print("string")

最后再说一句:如果你按照规范的格式进行类型注解,却发现报错误,那很大可能是python版本太低。比如下面代码中的类型注解就是在python 3.10开始支持的,3.10版本以下的不支持该语法格式的类型注解。

x: int | float = 2 # 表示 or Python 3.10 开始支持

参考文章:

  • Python 标准库 typing 类型注解标注
  • typing —— 对类型提示的支持

总结 

到此这篇关于python的type hints(类型标注、类型注解、类型提示)的文章就介绍到这了,更多相关Python类型提示Type Hints内容请搜索插件窝以前的文章或继续浏览下面的相关文章希望大家以后多多支持插件窝!