高级类型
本节介绍 Python 类型系统的高级特性,帮助精确表达复杂的类型约束。
Literal:字面量类型
限制值必须是特定字面量:
python
from typing import Literal
def set_mode(mode: Literal["read", "write", "append"]) -> None:
print(f"Mode: {mode}")
set_mode("read") # OK
set_mode("write") # OK
# set_mode("delete") # 类型错误
# 数字字面量
def roll_dice() -> Literal[1, 2, 3, 4, 5, 6]:
import random
return random.randint(1, 6) # type: ignore用途:API 参数、状态机、配置选项。
TypedDict:结构化字典
为字典定义精确的键和值类型:
python
from typing import TypedDict
class User(TypedDict):
name: str
age: int
email: str
def create_user(user: User) -> None:
print(f"{user['name']}, {user['age']}")
# 正确
user: User = {"name": "Alice", "age": 30, "email": "alice@example.com"}
create_user(user)
# 错误
# bad_user: User = {"name": "Bob"} # 缺少 age 和 email
# bad_user: User = {"name": "Bob", "age": "30", "email": "..."} # age 类型错误可选字段:
python
from typing import TypedDict, NotRequired # Python 3.11+
class UserProfile(TypedDict):
name: str
age: int
bio: NotRequired[str] # 可选字段
# OK
user1: UserProfile = {"name": "Alice", "age": 30}
user2: UserProfile = {"name": "Bob", "age": 25, "bio": "Developer"}Python 3.10 及更早:
python
class UserProfile(TypedDict, total=False):
bio: str # total=False 使所有字段可选
class User(UserProfile):
name: str
age: intCallable:函数类型
表示可调用对象(函数、方法):
python
from typing import Callable
# Callable[[参数类型], 返回类型]
def apply(func: Callable[[int, int], int], a: int, b: int) -> int:
return func(a, b)
def add(x: int, y: int) -> int:
return x + y
def multiply(x: int, y: int) -> int:
return x * y
print(apply(add, 5, 3)) # 8
print(apply(multiply, 5, 3)) # 15
# 任意参数
def run(func: Callable[..., None]) -> None:
func()overload:函数重载
为不同参数类型提供不同返回类型:
python
from typing import overload
@overload
def process(value: int) -> str:
...
@overload
def process(value: str) -> int:
...
def process(value: int | str) -> int | str:
if isinstance(value, int):
return f"Number: {value}"
else:
return len(value)
result1 = process(42) # result1: str
result2 = process("hello") # result2: int注意:@overload 只用于类型检查,实际实现在最后一个函数。
Final:不可变
声明变量、属性或方法不可修改:
python
from typing import Final
# 常量
MAX_SIZE: Final = 100
# MAX_SIZE = 200 # 类型检查器报错
class Config:
# 不可变类变量
VERSION: Final = "1.0"
def __init__(self) -> None:
# 不可变实例变量
self.api_key: Final = "secret"
# 不可重写方法
from typing import final
class Base:
@final
def important_method(self) -> None:
pass
class Derived(Base):
# def important_method(self) -> None: # 类型错误
# pass
passClassVar:类变量
区分类变量和实例变量:
python
from typing import ClassVar
class Counter:
count: ClassVar[int] = 0 # 类变量
name: str # 实例变量
def __init__(self, name: str) -> None:
self.name = name
Counter.count += 1
c1 = Counter("A")
c2 = Counter("B")
print(Counter.count) # 2NewType:创建不同类型
为基本类型创建不兼容的新类型:
python
from typing import NewType
UserId = NewType('UserId', int)
OrderId = NewType('OrderId', int)
def get_user(user_id: UserId) -> str:
return f"User {user_id}"
def get_order(order_id: OrderId) -> str:
return f"Order {order_id}"
user_id = UserId(123)
order_id = OrderId(456)
print(get_user(user_id)) # OK
# print(get_user(order_id)) # 类型错误:OrderId 不是 UserId
# print(get_user(123)) # 类型错误:int 不是 UserIdTypeGuard:类型守卫(Python 3.10+)
帮助类型检查器缩小类型范围:
python
from typing import TypeGuard
def is_string_list(val: list[object]) -> TypeGuard[list[str]]:
return all(isinstance(item, str) for item in val)
def process(items: list[object]) -> None:
if is_string_list(items):
# 类型检查器知道 items 是 list[str]
for item in items:
print(item.upper()) # OK,item 是 str
process(["a", "b", "c"])Self 类型(Python 3.11+)
表示返回当前类的实例:
python
from typing import Self
class Builder:
def __init__(self) -> None:
self.value = 0
def add(self, n: int) -> Self:
self.value += n
return self
def multiply(self, n: int) -> Self:
self.value *= n
return self
result = Builder().add(5).multiply(2).add(3)
print(result.value) # 13实战案例:状态机
python
from typing import Literal, TypedDict
State = Literal["idle", "running", "paused", "stopped"]
class Event(TypedDict):
type: Literal["start", "pause", "resume", "stop"]
timestamp: float
class StateMachine:
def __init__(self) -> None:
self.state: State = "idle"
def handle(self, event: Event) -> None:
if event["type"] == "start" and self.state == "idle":
self.state = "running"
elif event["type"] == "pause" and self.state == "running":
self.state = "paused"
elif event["type"] == "resume" and self.state == "paused":
self.state = "running"
elif event["type"] == "stop":
self.state = "stopped"
def get_state(self) -> State:
return self.state
# 使用
sm = StateMachine()
sm.handle({"type": "start", "timestamp": 0.0})
print(sm.get_state()) # "running"小结
- Literal 限制值为特定字面量
- TypedDict 为字典定义精确结构
- Callable 表示函数类型
- overload 提供多个类型签名
- Final 声明不可变
- ClassVar 标记类变量
- NewType 创建不兼容的新类型
- TypeGuard 帮助类型缩小
- Self 表示当前类实例(Python 3.11+)
下一节学习 类型检查工具。
参考:
练习:答案