Jacky's blog
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)

Jack Yang

编程; 随笔
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)
  • python 学习指南
  • python 中的设计模式
  • module

    • python modules
    • pandas
    • numpy
    • matplotlib
    • scipy
    • python typing 模块
      • 基础知识
        • 基本概念
      • 基础类型
        • 1. 基本类型注解
        • 2. 容器类型
        • 3. 可选类型 (Optional)
      • 联合类型 (Union)
        • 1. 基本用法
        • 2. Python 3.10+ 简写语法
      • 泛型类型
        • 1. 基本泛型
        • 2. 约束泛型
      • 函数类型
        • 1. Callable 类型
        • 2. 复杂函数签名
      • 高级类型
        • 1. Literal 类型
        • 2. TypedDict
        • 3. Protocol (结构化类型)
      • 特殊类型
        • 1. Any 类型
        • 2. NoReturn 类型
        • 3. Never 类型 (Python 3.11+)
      • 类型别名
        • 1. 基本类型别名
        • 2. 复杂类型别名
      • 运行时类型检查
        • 1. 使用 isinstance 和 issubclass
        • 2. 类型验证装饰器
      • 实际应用场景
        • 1. API 开发 (FastAPI)
        • 2. 数据处理管道
        • 3. 配置管理
      • 最佳实践
        • 1. 渐进式类型化
        • 2. 使用类型别名提高可读性
        • 3. 合理使用 Optional 和 Union
      • 常见陷阱和注意事项
        • 1. 运行时类型检查
        • 2. 循环导入问题
        • 3. 性能考虑
      • 工具和库
        • 1. 类型检查器
        • 2. IDE 支持
        • 3. 类型存根文件
    • inspect
    • beautysoup
    • scrapy
    • splash
    • pytorch
  • tool

  • other

  • 《python》
  • module
Jacky
2025-01-27
目录

python typing 模块

# 基础知识

Python的typing模块提供了类型提示(Type Hints)功能,用于在代码中标注变量、函数参数和返回值的类型。这些类型提示不会影响代码的运行时行为,但可以帮助IDE、类型检查器和开发者更好地理解代码。

# 基本概念

from typing import Any, Union, Optional, List, Dict, Tuple, Callable

# 基本类型注解
def greet(name: str) -> str:
    return f"Hello, {name}"

# 变量类型注解
age: int = 25
scores: List[float] = [95.5, 87.2, 92.1]
1
2
3
4
5
6
7
8
9

# 基础类型

# 1. 基本类型注解

# 基本数据类型
def process_data(
    text: str,
    number: int,
    decimal: float,
    flag: bool,
    data: bytes
) -> str:
    return f"{text}: {number + decimal} ({flag})"
1
2
3
4
5
6
7
8
9

# 2. 容器类型

from typing import List, Dict, Tuple, Set

# 列表类型
def process_list(items: List[str]) -> List[int]:
    return [len(item) for item in items]

# 字典类型
def process_dict(data: Dict[str, int]) -> Dict[int, str]:
    return {v: k for k, v in data.items()}

# 元组类型
def process_tuple(coords: Tuple[float, float]) -> Tuple[int, int]:
    return (int(coords[0]), int(coords[1]))

# 集合类型
def process_set(numbers: Set[int]) -> Set[str]:
    return {str(n) for n in numbers}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 3. 可选类型 (Optional)

from typing import Optional

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

# 带默认值的可选参数
def greet_user(name: Optional[str] = None) -> str:
    if name is None:
        return "Hello, Guest"
    return f"Hello, {name}"
1
2
3
4
5
6
7
8
9
10
11

# 联合类型 (Union)

聚合类型是指由多个其他类型组合而成的复合类型,它能够将多个不同类型的值组合成一个单一的数据结构。在不同的编程语言和上下文中,聚合类型有不同的表现形式

# 1. 基本用法

from typing import Union

# 接受多种类型的参数
def process_data(data: Union[str, bytes]) -> str:
    if isinstance(data, bytes):
        return data.decode('utf-8')
    return data

# 返回多种类型
def get_value(key: str) -> Union[str, int, None]:
    data = {"name": "Alice", "age": 30}
    return data.get(key)
1
2
3
4
5
6
7
8
9
10
11
12

# 2. Python 3.10+ 简写语法

# 使用 | 操作符(Python 3.10+)
def process_data(data: str | bytes) -> str:
    if isinstance(data, bytes):
        return data.decode('utf-8')
    return data

def get_value(key: str) -> str | int | None:
    data = {"name": "Alice", "age": 30}
    return data.get(key)
1
2
3
4
5
6
7
8
9

# 泛型类型

# 1. 基本泛型

from typing import TypeVar, Generic, List, Dict

# 定义类型变量
T = TypeVar('T')
K = TypeVar('K')
V = TypeVar('V')

# 泛型类
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()
    
    def peek(self) -> T:
        return self.items[-1]

# 使用泛型类
int_stack: Stack[int] = Stack()
str_stack: Stack[str] = Stack()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 2. 约束泛型

from typing import TypeVar, Union

# 约束类型变量
Number = TypeVar('Number', bound=Union[int, float])

def add_numbers(a: Number, b: Number) -> Number:
    return a + b

# 只能用于数字类型
result1 = add_numbers(5, 3)      # int
result2 = add_numbers(3.14, 2.86) # float
# result3 = add_numbers("5", "3")  # 类型错误
1
2
3
4
5
6
7
8
9
10
11
12

# 函数类型

# 1. Callable 类型

from typing import Callable, List

# 函数类型注解
def apply_func(func: Callable[[int], str], numbers: List[int]) -> List[str]:
    return [func(n) for n in numbers]

# 使用示例
def int_to_str(n: int) -> str:
    return str(n)

result = apply_func(int_to_str, [1, 2, 3, 4, 5])
1
2
3
4
5
6
7
8
9
10
11

# 2. 复杂函数签名

from typing import Callable, TypeVar, Union

T = TypeVar('T')

# 带泛型的函数类型
Processor = Callable[[T], str]
OptionalProcessor = Callable[[T], Union[str, None]]

def process_with_handler(
    data: T,
    handler: Processor[T]
) -> str:
    return handler(data)

# 使用示例
def format_number(n: int) -> str:
    return f"Number: {n}"

result = process_with_handler(42, format_number)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 高级类型

# 1. Literal 类型

from typing import Literal

# 字面量类型
def get_status(status: Literal["success", "error", "pending"]) -> str:
    return f"Status: {status}"

# 只能传入指定的字面量值
get_status("success")   # 正确
get_status("error")     # 正确
# get_status("unknown")  # 类型错误
1
2
3
4
5
6
7
8
9
10

# 2. TypedDict

from typing import TypedDict, Optional

# 定义类型化字典
class UserInfo(TypedDict):
    name: str
    age: int
    email: Optional[str]

# 使用类型化字典
def create_user(info: UserInfo) -> str:
    return f"User {info['name']} is {info['age']} years old"

# 创建符合类型的字典
user_data: UserInfo = {
    "name": "Alice",
    "age": 30,
    "email": "[email protected]"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3. Protocol (结构化类型)

from typing import Protocol

# 定义协议(接口)
class Drawable(Protocol):
    def draw(self) -> str: ...

class Circle:
    def draw(self) -> str:
        return "Drawing a circle"

class Square:
    def draw(self) -> str:
        return "Drawing a square"

# 接受任何实现了draw方法的对象
def render_shape(shape: Drawable) -> str:
    return shape.draw()

# 使用示例
circle = Circle()
square = Square()
print(render_shape(circle))  # "Drawing a circle"
print(render_shape(square))  # "Drawing a square"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 特殊类型

# 1. Any 类型

from typing import Any

# Any 表示任意类型
def process_anything(data: Any) -> Any:
    return data

# 通常用于与动态代码交互
def legacy_function(data: Any) -> str:
    return str(data)
1
2
3
4
5
6
7
8
9

# 2. NoReturn 类型

from typing import NoReturn

# 表示函数永远不会返回(总是抛出异常)
def raise_error(message: str) -> NoReturn:
    raise ValueError(message)

def infinite_loop() -> NoReturn:
    while True:
        pass
1
2
3
4
5
6
7
8
9

# 3. Never 类型 (Python 3.11+)

from typing import Never

# Never 表示不可能的类型
def impossible_function() -> Never:
    raise Exception("This function should never be called")

# 用于表示不可能的情况
def process_data(data: str | int) -> str:
    if isinstance(data, str):
        return data.upper()
    elif isinstance(data, int):
        return str(data)
    else:
        # 这里 data 的类型是 Never,因为前面的条件已经覆盖了所有可能
        return impossible_function()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 类型别名

# 1. 基本类型别名

from typing import List, Dict, Union

# 创建类型别名
UserId = int
UserName = str
UserData = Dict[UserId, UserName]
UserList = List[UserData]

# 使用类型别名
def process_users(users: UserList) -> List[UserName]:
    return [user_data[user_id] for user_data in users for user_id in user_data]
1
2
3
4
5
6
7
8
9
10
11

# 2. 复杂类型别名

from typing import Callable, List, Union

# 复杂的类型别名
Number = Union[int, float]
NumberProcessor = Callable[[Number], Number]
NumberList = List[Number]

# 使用复杂类型别名
def apply_operations(
    numbers: NumberList,
    operations: List[NumberProcessor]
) -> NumberList:
    result = numbers
    for op in operations:
        result = [op(n) for n in result]
    return result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 运行时类型检查

# 1. 使用 isinstance 和 issubclass

from typing import Union, get_args, get_origin

def check_type(obj: Any, expected_type: Any) -> bool:
    """检查对象是否符合预期类型"""
    if expected_type is Any:
        return True
    
    # 处理 Union 类型
    if get_origin(expected_type) is Union:
        return any(isinstance(obj, t) for t in get_args(expected_type))
    
    return isinstance(obj, expected_type)

# 使用示例
def process_data(data: Union[str, int]) -> str:
    if not check_type(data, Union[str, int]):
        raise TypeError(f"Expected str or int, got {type(data)}")
    return str(data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 2. 类型验证装饰器

from typing import Callable, Any, get_type_hints
from functools import wraps

def validate_types(func: Callable) -> Callable:
    """类型验证装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        hints = get_type_hints(func)
        
        # 验证参数类型
        for (name, value), expected_type in zip(
            list(zip(func.__code__.co_varnames, args)) + list(kwargs.items()),
            list(hints.values())[:-1]  # 排除返回类型
        ):
            if not check_type(value, expected_type):
                raise TypeError(f"Parameter {name} should be {expected_type}, got {type(value)}")
        
        result = func(*args, **kwargs)
        
        # 验证返回类型
        return_type = hints.get('return')
        if return_type and not check_type(result, return_type):
            raise TypeError(f"Return value should be {return_type}, got {type(result)}")
        
        return result
    
    return wrapper

# 使用装饰器
@validate_types
def add_numbers(a: int, b: int) -> int:
    return a + b

# 这会正常工作
result = add_numbers(5, 3)

# 这会抛出类型错误
# result = add_numbers("5", 3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 实际应用场景

# 1. API 开发 (FastAPI)

from typing import List, Optional
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: Optional[str] = None
    tags: List[str] = []

class UserResponse(BaseModel):
    user: User
    status: str

def create_user(user_data: User) -> UserResponse:
    # 处理用户创建逻辑
    return UserResponse(user=user_data, status="created")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 2. 数据处理管道

from typing import TypeVar, Callable, List, Union
from dataclasses import dataclass

T = TypeVar('T')
U = TypeVar('U')

@dataclass
class DataProcessor(Generic[T, U]):
    transform: Callable[[T], U]
    validate: Callable[[U], bool]
    
    def process(self, data: List[T]) -> List[U]:
        results = []
        for item in data:
            transformed = self.transform(item)
            if self.validate(transformed):
                results.append(transformed)
        return results

# 使用示例
def transform_string(s: str) -> int:
    return len(s)

def validate_length(n: int) -> bool:
    return 0 <= n <= 100

processor = DataProcessor(transform_string, validate_length)
result = processor.process(["hello", "world", "python"])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 3. 配置管理

from typing import TypedDict, Optional, Union

class DatabaseConfig(TypedDict):
    host: str
    port: int
    username: str
    password: str
    database: str

class CacheConfig(TypedDict):
    enabled: bool
    host: Optional[str]
    port: Optional[int]
    ttl: int

class AppConfig(TypedDict):
    debug: bool
    database: DatabaseConfig
    cache: CacheConfig
    log_level: Union[str, int]

def load_config() -> AppConfig:
    return {
        "debug": True,
        "database": {
            "host": "localhost",
            "port": 5432,
            "username": "user",
            "password": "pass",
            "database": "mydb"
        },
        "cache": {
            "enabled": True,
            "host": "localhost",
            "port": 6379,
            "ttl": 3600
        },
        "log_level": "INFO"
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 最佳实践

# 1. 渐进式类型化

# 从简单开始,逐步添加类型
def simple_function(x, y):
    return x + y

# 添加基本类型
def typed_function(x: int, y: int) -> int:
    return x + y

# 添加更复杂的类型
def advanced_function(
    x: Union[int, float],
    y: Union[int, float],
    operation: Callable[[Union[int, float]], str]
) -> str:
    result = x + y
    return operation(result)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 2. 使用类型别名提高可读性

from typing import List, Dict, Union

# 定义有意义的类型别名
UserId = int
UserName = str
UserEmail = str
UserProfile = Dict[str, Union[str, int, bool]]

# 使用类型别名
def get_user_profile(user_id: UserId) -> UserProfile:
    # 实现逻辑
    pass

def update_user_name(user_id: UserId, name: UserName) -> bool:
    # 实现逻辑
    pass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 3. 合理使用 Optional 和 Union

from typing import Optional, Union

# 好的做法:明确表示可能为None
def find_user(user_id: int) -> Optional[str]:
    users = {1: "Alice", 2: "Bob"}
    return users.get(user_id)

# 好的做法:明确表示多种可能类型
def process_data(data: Union[str, bytes]) -> str:
    if isinstance(data, bytes):
        return data.decode('utf-8')
    return data

# 避免过度使用Any
def bad_function(data: Any) -> Any:  # 太宽泛
    return data

def good_function(data: Union[str, int]) -> str:  # 更具体
    return str(data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 常见陷阱和注意事项

# 1. 运行时类型检查

from typing import Union

# 错误:不能在运行时直接使用Union
def bad_check(data):
    # 这会失败
    return isinstance(data, Union[str, int])

# 正确:使用元组进行运行时检查
def good_check(data):
    return isinstance(data, (str, int))

# 或者使用类型检查库
from typing import get_args, get_origin

def advanced_check(data, expected_type):
    if get_origin(expected_type) is Union:
        return any(isinstance(data, t) for t in get_args(expected_type))
    return isinstance(data, expected_type)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 2. 循环导入问题

# 使用字符串类型注解避免循环导入
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .models import User

def process_user(user: "User") -> str:
    return user.name
1
2
3
4
5
6
7
8

# 3. 性能考虑

# 类型注解对运行时性能没有影响
# 但过多的类型检查可能影响性能

# 好的做法:在开发时使用类型检查,生产环境关闭
import os

if os.getenv("ENVIRONMENT") == "development":
    # 启用类型检查
    pass
1
2
3
4
5
6
7
8
9

# 工具和库

# 1. 类型检查器

# 安装 mypy
pip install mypy

# 运行类型检查
mypy your_file.py

# 配置 mypy
# mypy.ini
[mypy]
python_version = 3.8
warn_return_any = True
warn_unused_configs = True
1
2
3
4
5
6
7
8
9
10
11
12

# 2. IDE 支持

# 大多数现代IDE都支持类型提示
# PyCharm, VS Code, Vim/Neovim 等

# 类型存根文件 (.pyi)
# 用于为第三方库提供类型信息
1
2
3
4
5

# 3. 类型存根文件

# example.pyi
from typing import List, Optional

def process_data(data: List[str]) -> Optional[str]: ...
def get_config() -> dict: ...
1
2
3
4
5

这个文档涵盖了Python typing模块的主要功能和使用方法。你可以根据具体需求深入学习特定的部分。

#module#Python
上次更新: 2025/10/09, 21:06:25
scipy
inspect

← scipy inspect→

最近更新
01
npx 使用指南
10-12
02
cursor
09-28
03
inspect
07-20
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Jacky | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式