Skip to content

高级类型 ​

本节介绍 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: int

Callable:函数类型 ​

表示可调用对象(函数、方法):

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
    pass

ClassVar:类变量 ​

区分类变量和实例变量:

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)  # 2

NewType:创建不同类型 ​

为基本类型创建不兼容的新类型:

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 不是 UserId

TypeGuard:类型守卫(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+)

下一节学习 类型检查工具。


参考:

练习:答案

用心记录每一步成长