跳到主要内容

typing

问题

Python 的类型注解系统有哪些核心概念?Generic、Protocol、TypeVar 怎么用?

答案

基础类型注解

# 基本类型(3.9+ 可直接用内置类型)
name: str = "Alice"
scores: list[int] = [90, 85, 92]
config: dict[str, int] = {"timeout": 30}
result: tuple[str, int] = ("ok", 200) # 固定长度

# 可选值
from typing import Optional
age: Optional[int] = None # 等价于 int | None(3.10+)

# 联合类型
from typing import Union
value: Union[int, str] = 42 # 3.10+ 可写 int | str

# 可调用
from typing import Callable
handler: Callable[[int, str], bool] = lambda x, s: True

TypeVar 和 Generic

from typing import TypeVar, Generic

T = TypeVar("T")

# 泛型函数
def first(items: list[T]) -> T:
return items[0]

# 泛型类
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()

stack: Stack[int] = Stack()
stack.push(42)

# Python 3.12+ 新语法
def first[T](items: list[T]) -> T: # 无需 TypeVar
return items[0]

Protocol — 结构化子类型

from typing import Protocol

class Drawable(Protocol):
def draw(self) -> None: ...

class Circle:
def draw(self) -> None:
print("画圆")

# Circle 没有显式继承 Drawable,但满足协议(鸭子类型的类型化)
def render(shape: Drawable) -> None:
shape.draw()

render(Circle()) # ✅ 类型检查通过

常用工具类型

类型用途示例
TypeAlias类型别名Vector: TypeAlias = list[float]
Literal字面量类型mode: Literal["r", "w"]
TypedDict字典结构约束class Config(TypedDict): ...
Final不可重新赋值MAX: Final = 100
Annotated附加元数据Age = Annotated[int, Gt(0)]
Self (3.11+)返回自身类型def copy(self) -> Self: ...
TypeGuard类型收窄def is_str(x) -> TypeGuard[str]

常见面试问题

Q1: 类型注解会影响运行时吗?

答案

不会。Python 的类型注解只是元数据,不影响运行时行为。它们服务于:

  • IDE 提示和自动补全
  • 静态类型检查器(mypy、Pyright)
  • 文档生成
  • 框架运行时使用(如 Pydantic、FastAPI 用注解做验证)

Q2: Protocol 和 ABC 的区别?

答案

对比ProtocolABC
子类型方式结构化(鸭子类型)名义化(显式继承)
需要继承
运行时检查❌(默认)✅(isinstance)
适用场景第三方代码自己的类体系

相关链接