Python类型系统typing模块示例详解

 更新时间:2025年06月28日 11:17:58   作者:cugleem  
Python的typing库提供了丰富的类型注解支持,使得开发者可以在代码中明确表示函数参数和返回值的类型,下面这篇文章主要介绍了Python类型系统typing模块的相关资料,需要的朋友可以参考下

1. 模块概述

typing 模块在 Python 3.5 中引入,用于支持类型提示(Type Hints)。它提供了:

  • 用于类型注释的工具
  • 泛型类型支持
  • 类型别名
  • 回调协议
  • 以及其他高级类型系统特性

2. 基础类型提示

2.1 基本类型注释

from typing import List, Dict, Set, Tuple, Optional

# 变量类型注释
name: str = "Alice"
age: int = 30
is_student: bool = False

# 函数参数和返回值类型注释
def greet(name: str) -> str:
    return f"Hello, {name}"

# 容器类型
numbers: List[int] = [1, 2, 3]
person: Dict[str, str] = {"name": "Alice", "email": "alice@example.com"}
unique_numbers: Set[int] = {1, 2, 3}
coordinates: Tuple[float, float] = (10.5, 20.3)

# 可选类型
maybe_name: Optional[str] = None  # 等同于 Union[str, None]

2.2 类型别名

from typing import List, Tuple

# 创建类型别名
Vector = List[float]
Point = Tuple[float, float]

def scale_vector(v: Vector, factor: float) -> Vector:
    return [x * factor for x in v]

def distance(p1: Point, p2: Point) -> float:
    return ((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)**0.5

3. 复合类型

3.1 Union 类型

  • 表示属于Union中的任意一种类型均合法
from typing import Union

def process_value(value: Union[int, str]) -> None:
    if isinstance(value, int):
        print(f"Processing integer: {value}")
    else:
        print(f"Processing string: {value}")

process_value(10)    # Processing integer: 10
process_value("hi")  # Processing string: hi

3.2 Optional 类型

  • Optional[str] = Union[str, None]
from typing import Optional

def find_user(user_id: int) -> Optional[str]:
    users = {1: "Alice", 2: "Bob"}
    return users.get(user_id)

print(find_user(1))  # Alice
print(find_user(3))  # None

3.3 Any 类型

  • 表示可以使用任何类型,不建议常用
from typing import Any

def process_any(value: Any) -> Any:
    print(f"Processing {value}")
    return value

result = process_any(10)      # Processing 10
result = process_any("text")  # Processing text

4. 泛型类型

4.1 TypeVar

from typing import TypeVar, List, Sequence

T = TypeVar('T')  # 任意类型
Num = TypeVar('Num', int, float)  # 仅限于int和float

def first_element(items: Sequence[T]) -> T:
    return items[0]

print(first_element([1, 2, 3]))    # 1
print(first_element(["a", "b"]))   # a

4.2 Generic 类

from typing import TypeVar, Generic, List

T = TypeVar('T')

class Stack(Generic[T]):
    def __init__(self) -> None:
        self.items: List[T] = []
    
    def push(self, item: T) -> None:
        self.items.append(item)
    
    def pop(self) -> T:
        return self.items.pop()

int_stack = Stack[int]()
int_stack.push(1)
int_stack.push(2)
print(int_stack.pop())  # 2

5. 函数类型

5.1 Callable

from typing import Callable

def apply_func(func: Callable[[int, int], int], a: int, b: int) -> int:
    return func(a, b)

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

print(apply_func(add, 3, 5))  # 8

5.2 可调用对象协议

from typing import Protocol

class Adder(Protocol):
    def __call__(self, a: int, b: int) -> int:
        ...

def apply_adder(adder: Adder, x: int, y: int) -> int:
    return adder(x, y)

print(apply_adder(lambda a, b: a + b, 10, 20))  # 30

6. 带元数据的类型Annotated

Annotated 是 Python typing 模块中一个强大但常被忽视的类型注解工具,它允许我们在类型提示中添加额外的元数据。这个功能在 Python 3.9 中引入,为类型系统提供了更大的灵活性。Annotated 的基本形式如下:

from typing import Annotated

Annotated[<type>, <metadata1>, <metadata2>, ...]

其中:

  • <type> 是基础类型
  • <metadata> 可以是任意对象,提供额外的类型信息

6.1 基本示例

from typing import Annotated

# 给int类型添加单位信息
Distance = Annotated[int, "meters"]
Temperature = Annotated[float, "celsius"]

def get_distance() -> Distance:
    return 100

def get_temperature() -> Temperature:
    return 25.5

6.2 核心特性

  • 保留类型信息

Annotated 不会改变原始类型,只是附加元数据:

from typing import Annotated, get_type_hints

UserId = Annotated[int, "user identifier"]

def get_user(id: UserId) -> str:
    return f"user_{id}"

# 获取类型提示
hints = get_type_hints(get_user)
print(hints)  # {'id': typing.Annotated[int, 'user identifier'], 'return': <class 'str'>}
  • 多重元数据

可以附加多个元数据项:

from typing import Annotated

# 带有范围和单位的温度类型
BoundedTemp = Annotated[float, "celsius", (0.0, 100.0)]

def check_temp(temp: BoundedTemp) -> bool:
    return 0.0 <= temp <= 100.0

6.3 应用场景

  • 数据验证

结合 Pydantic 等库进行数据验证:

from typing import Annotated
from pydantic import BaseModel, Field

PositiveInt = Annotated[int, Field(gt=0)]

class User(BaseModel):
    id: PositiveInt
    name: str

# 有效数据
user = User(id=1, name="Alice")

# 无效数据会引发验证错误
# user = User(id=-1, name="Bob")  # 抛出ValidationError
  • 参数约束

在 FastAPI 等框架中指定参数约束:

from typing import Annotated
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(
    q: Annotated[str, Query(min_length=3, max_length=50)] = "default"
):
    return {"q": q}
  • 文档增强

为类型添加文档信息:

from typing import Annotated
from typing_extensions import Doc  # Python 3.11+

DatabaseConnection = Annotated[
    str,
    Doc("A connection string in the format 'user:password@host:port/database'"),
    Doc("Example: 'admin:secret@localhost:5432/mydb'")
]

def connect_db(conn_str: DatabaseConnection) -> None:
    """Connect to the database."""
    print(f"Connecting with: {conn_str}")

6.4 与其他类型工具结合

  • 与 NewType 结合
from typing import Annotated, NewType

UserId = NewType('UserId', int)
AnnotatedUserId = Annotated[UserId, "primary key"]

def get_user_name(user_id: AnnotatedUserId) -> str:
    return f"user_{user_id}"

print(get_user_name(UserId(42)))  # user_42
  • 与 Literal 结合
from typing import Annotated, Literal

HttpMethod = Literal["GET", "POST", "PUT", "DELETE"]
AnnotatedHttpMethod = Annotated[HttpMethod, "HTTP method"]

def log_request(method: AnnotatedHttpMethod) -> None:
    print(f"Received {method} request")

log_request("GET")  # 有效
# log_request("HEAD")  # 类型检查器会报错

6.5 运行时访问元数据

from typing import Annotated, get_type_hints

def extract_metadata(annotated_type):
    origin = get_origin(annotated_type)
    if origin is not Annotated:
        return None
    return get_args(annotated_type)[1:]  # 返回元数据部分

# 定义带注解的类型
Count = Annotated[int, "counter", "must be positive"]
hints = get_type_hints(lambda x: x, localns={'x': Count})
metadata = extract_metadata(hints['x'])

print(metadata)  # ('counter', 'must be positive')

6.6. 实际案例:数据库字段类型

from typing import Annotated, Optional
from datetime import datetime

# 定义带约束的字段类型
Username = Annotated[str, "username", "max_length=32", "alphanumeric"]
Email = Annotated[str, "email", "max_length=255"]
CreatedAt = Annotated[datetime, "auto_now_add=True"]
UpdatedAt = Annotated[Optional[datetime], "auto_now=True", "nullable=True"]

class UserProfile:
    def __init__(
        self,
        username: Username,
        email: Email,
        created_at: CreatedAt,
        updated_at: UpdatedAt = None
    ):
        self.username = username
        self.email = email
        self.created_at = created_at
        self.updated_at = updated_at

# 这些注解可以被ORM框架或序列化库读取并使用

Annotated 为 Python 的类型系统提供了强大的扩展能力,使得类型提示不仅可以用于静态检查,还能携带丰富的运行时信息,为框架开发和复杂系统设计提供了更多可能性。

7. 高级类型特性

7.1 Literal 类型

from typing import Literal

def draw_shape(shape: Literal["circle", "square", "triangle"]) -> None:
    print(f"Drawing a {shape}")

draw_shape("circle")    # 正确
draw_shape("square")    # 正确
# draw_shape("rectangle")  # 类型检查器会报错

7.2 TypedDict

from typing import TypedDict, Optional

class Person(TypedDict):
    name: str
    age: int
    email: Optional[str]

alice: Person = {"name": "Alice", "age": 30}
bob: Person = {"name": "Bob", "age": 25, "email": "bob@example.com"}

7.3 NewType

from typing import NewType

UserId = NewType('UserId', int)
admin_id = UserId(1)

def get_user_name(user_id: UserId) -> str:
    return f"user_{user_id}"

print(get_user_name(admin_id))        # 正确
# print(get_user_name(12345))        # 类型检查器会报错

8. 运行时类型检查

8.1 typeguard

虽然 typing 模块主要用于静态类型检查,但可以与第三方库如 typeguard 结合实现运行时检查:

from typeguard import typechecked
from typing import List

@typechecked
def process_numbers(numbers: List[int]) -> float:
    return sum(numbers) / len(numbers)

print(process_numbers([1, 2, 3]))  # 2.0
# process_numbers([1, '2', 3])    # 运行时抛出TypeError

8.2 get_type_hints

from typing import get_type_hints, List, Dict

def example(a: int, b: str = "default") -> Dict[str, List[int]]:
    return {b: [a]}

print(get_type_hints(example))
# 输出: {'a': <class 'int'>, 'b': <class 'str'>, 'return': Dict[str, List[int]]}

9. Python 3.10+ 新特性

9.1 联合类型语法糖

# Python 3.10 之前
from typing import Union

def old_way(x: Union[int, str]) -> Union[int, str]:
    return x

# Python 3.10+
def new_way(x: int | str) -> int | str:
    return x

9.2 TypeGuard

from typing import TypeGuard, List, Union

def is_str_list(val: List[Union[str, int]]) -> TypeGuard[List[str]]:
    return all(isinstance(x, str) for x in val)

def process_items(items: List[Union[str, int]]) -> None:
    if is_str_list(items):
        print("All strings:", [s.upper() for s in items])
    else:
        print("Mixed types:", items)

process_items(["a", "b", "c"])  # All strings: ['A', 'B', 'C']
process_items([1, "b", 3])      # Mixed types: [1, 'b', 3]

10. 迁移策略

10.1 逐步添加类型提示

# 第一阶段:无类型提示
def old_function(x):
    return x * 2

# 第二阶段:添加简单类型提示
def partially_typed_function(x: int) -> int:
    return x * 2

# 第三阶段:完整类型提示
from typing import TypeVar, Sequence

T = TypeVar('T')
def fully_typed_function(items: Sequence[T], multiplier: int) -> list[T]:
    return [item * multiplier for item in items]

10.2 处理动态类型代码

import types
from typing import Any, Union, cast

def dynamic_function(func: Union[types.FunctionType, types.BuiltinFunctionType]) -> Any:
    result = func()
    # 如果我们知道特定函数的返回类型,可以使用cast
    if func.__name__ == 'get_answer':
        return cast(int, result)
    return result

typing 模块总结

  • 为 Python 添加静态类型提示支持
  • 提供丰富的类型注解工具(ListDictUnion 等)
  • 支持泛型编程(TypeVarGeneric
  • 包含高级类型特性(LiteralTypedDictProtocol 等)
  • 与 Python 3.10+ 的新语法(| 运算符)良好集成
  • 类型提示在运行时几乎没有性能影响,因为它们主要被静态类型检查器使用
  • typing 模块中的一些特殊形式(如 Generic)可能会引入轻微的开销
  • 在性能关键代码中,考虑使用简单的类型提示或仅在开发时使用类型检查

总结 

到此这篇关于Python类型系统typing模块示例详解的文章就介绍到这了,更多相关Python类型系统typing模块内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python PyInstaller库基本使用方法分析

    Python PyInstaller库基本使用方法分析

    这篇文章主要介绍了Python PyInstaller库基本使用方法,结合实例形式分析了Python PyInstaller库的功能、安装及相关使用注意事项,需要的朋友可以参考下
    2019-12-12
  • 使用matplotlib创建Gif动图的实现

    使用matplotlib创建Gif动图的实现

    本文主要介绍了使用matplotlib创建Gif动图的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • 推荐10款最受Python开发者欢迎的Python IDE

    推荐10款最受Python开发者欢迎的Python IDE

    这篇文章收集了一些对开发者非常有帮助的,最好的10款Python IDE,包括Vim,Eclipse with PyDev,Sublime Text,PyCharm等知明Python开发工具
    2018-09-09
  • django进阶之cookie和session的使用示例

    django进阶之cookie和session的使用示例

    这篇文章主要介绍了django进阶之cookie和session的使用示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Python matplotlib绘图时使用鼠标滚轮放大/缩小图像

    Python matplotlib绘图时使用鼠标滚轮放大/缩小图像

    Matplotlib是Python程序员可用的事实上的绘图库,虽然它比交互式绘图库在图形上更简单,但它仍然可以一个强大的工具,下面这篇文章主要给大家介绍了关于Python matplotlib绘图时使用鼠标滚轮放大/缩小图像的相关资料,需要的朋友可以参考下
    2022-05-05
  • python切片及sys.argv[]用法详解

    python切片及sys.argv[]用法详解

    Sys.argv[]是用来获取命令行参数的,sys.argv[0]表示代码本身文件路径,所以参数从1开始。下面通过实例代码给大家介绍python切片及sys.argv[]用法,需要的朋友参考下吧
    2018-05-05
  • python range实例用法分享

    python range实例用法分享

    在本篇文章里小编给大家整理了关于python range实例用法,有需要的朋友们可以学习参考下
    2020-02-02
  • 利用Python演示数型数据结构的教程

    利用Python演示数型数据结构的教程

    这篇文章主要介绍了利用Python演示数型数据结构的教程,核心代码其实只有一行(XD),需要的朋友可以参考下
    2015-04-04
  • python selenium xpath定位操作

    python selenium xpath定位操作

    这篇文章主要介绍了python selenium xpath定位操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • python 爬取知乎回答下的微信8.0状态视频

    python 爬取知乎回答下的微信8.0状态视频

    这篇文章主要介绍了python 爬取知乎的微信8.0状态视频的方法,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下
    2021-03-03

最新评论