← 返回首页
🐍

类型注解与提示

📂 python ⏱ 3 min 492 words

类型注解基础

Python 3.5引入了类型注解(Type Hints),允许你在代码中指定变量和函数的类型。这有助于代码可读性和IDE支持。

# 基本类型注解
name: str = "Alice"
age: int = 25
height: float = 1.68
is_student: bool = True

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

# 多个参数
def calculate(x: int, y: int) -> int:
    return x + y

typing模块

Python的typing模块提供了更丰富的类型支持。

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

# 列表类型
numbers: List[int] = [1, 2, 3, 4, 5]
names: List[str] = ["Alice", "Bob", "Charlie"]

# 字典类型
scores: Dict[str, int] = {"Alice": 90, "Bob": 85}

# 元组类型
point: Tuple[int, int] = (10, 20)

# 集合类型
unique_numbers: Set[int] = {1, 2, 3, 4, 5}

# 可选类型(值可以是None)
def greet_optional(name: Optional[str] = None) -> str:
    if name is None:
        return "Hello, Stranger!"
    return f"Hello, {name}!"

# 联合类型
def process_value(value: Union[int, str]) -> str:
    if isinstance(value, int):
        return f"Processing integer: {value}"
    return f"Processing string: {value}"

TypeVar和泛型

TypeVar允许创建可重用的类型注解。

from typing import TypeVar, List, Dict

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

def first_element(lst: List[T]) -> T:
    return lst[0]

# 使用
numbers: List[int] = [1, 2, 3]
result: int = first_element(numbers)

names: List[str] = ["Alice", "Bob"]
result: str = first_element(names)

# 多个类型变量
K = TypeVar('K')
V = TypeVar('V')

def get_first_key(d: Dict[K, V]) -> K:
    return next(iter(d))

scores: Dict[str, int] = {"Alice": 90, "Bob": 85}
name: str = get_first_key(scores)

Callable类型

from typing import Callable, List

# 函数类型
def apply(func: Callable[[int, int], int], x: int, y: int) -> int:
    return func(x, y)

# 使用lambda
result = apply(lambda a, b: a + b, 3, 5)
print(result)  # 输出: 8

# 函数列表
def process_all(funcs: List[Callable[[int], int]], value: int) -> List[int]:
    return [f(value) for f in funcs]

# 使用
operations = [lambda x: x * 2, lambda x: x ** 2, lambda x: x + 10]
results = process_all(operations, 5)
print(results)  # 输出: [10, 25, 15]

高级类型注解

NamedTuple

from typing import NamedTuple

class Point(NamedTuple):
    x: int
    y: int
    z: int = 0  # 默认值

p = Point(1, 2)
print(p)  # 输出: Point(x=1, y=2, z=0)

# 访问字段
print(p.x, p.y, p.z)  # 输出: 1 2 0

TypedDict

from typing import TypedDict

class StudentDict(TypedDict):
    name: str
    age: int
    grades: List[float]

student: StudentDict = {
    "name": "Alice",
    "age": 20,
    "grades": [90.5, 85.0, 92.0]
}

Literal类型

from typing import Literal

def set_direction(direction: Literal["north", "south", "east", "west"]) -> None:
    print(f"Moving {direction}")

set_direction("north")  # 正确
# set_direction("up")  # 类型错误

Protocol(协议)

Protocol用于定义结构化类型,类似于其他语言的接口。

from typing import Protocol, runtime_checkable

@runtime_checkable
class Drawable(Protocol):
    def draw(self) -> str: ...

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

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

def draw_shape(shape: Drawable) -> str:
    return shape.draw()

# 使用
circle = Circle()
square = Square()

print(draw_shape(circle))  # 输出: Drawing circle
print(draw_shape(square))  # 输出: Drawing square

# 检查协议
print(isinstance(circle, Drawable))  # 输出: True

类型检查工具

mypy

# 安装mypy
pip install mypy

# 运行类型检查
mypy your_script.py

Pyright

# 安装pyright
pip install pyright

# 运行类型检查
pyright your_script.py

实际应用案例

from typing import List, Dict, Optional, Union

# 1. 数据验证
def validate_email(email: str) -> bool:
    return "@" in email and "." in email

# 2. 数据处理
def process_data(data: List[Dict[str, Union[str, int]]]) -> List[str]:
    return [str(item["name"]) for item in data if "name" in item]

# 3. 配置管理
class Config(TypedDict):
    database_url: str
    debug: bool
    port: int

def load_config(config: Config) -> None:
    print(f"Database: {config['database_url']}")
    print(f"Debug: {config['debug']}")
    print(f"Port: {config['port']}")

最佳实践

类型注解虽然不是强制性的,但能显著提高代码质量和开发效率。