如何在Python中声明不可变/可变TypeVar?泛型协议场景实现
在Python中区分可变/不可变TypeVar并实现泛型协议
1. 定义区分可变/不可变的TypeVar
你可以通过TypeVar的bound参数,将其绑定到对应的抽象基类,以此明确区分可变和不可变类型:
- 不可变类型绑定到只读抽象基类(如
Sequence) - 可变类型绑定到可写抽象基类(如
MutableSequence)
示例代码:
from typing import TypeVar, Protocol, Generic, Sequence, MutableSequence # 绑定到不可变序列的TypeVar,仅用于只读操作场景 TImmutable = TypeVar('TImmutable', bound=Sequence) # 绑定到可变序列的TypeVar,支持修改操作场景 TMutable = TypeVar('TMutable', bound=MutableSequence)
2. 实现泛型Protocol
结合Protocol和Generic,在协议中分别为只读方法、修改方法指定对应的TypeVar参数,静态类型检查工具(如mypy)会自动约束方法对参数的操作:
class DataHandlerProtocol(Protocol, Generic[TImmutable, TMutable]): # 只读方法:参数为不可变TypeVar,禁止修改操作 def process_read_only(self, data: TImmutable) -> None: # 合法操作:遍历、取值 for item in data: print(f"Processing: {item}") # 非法操作(会被类型检查工具报错):data.append("new_item") # 修改方法:参数为可变TypeVar,允许修改操作 def process_modifiable(self, data: TMutable) -> None: # 合法操作:添加元素、排序 data.append("new_element") data.sort()
3. 实现协议的具体类
当实现该协议时,你可以指定具体的可变/不可变类型:
class ConcreteDataHandler(DataHandlerProtocol[Sequence[str], list[str]]): def process_read_only(self, data: Sequence[str]) -> None: for s in data: print(f"Reading: {s}") def process_modifiable(self, data: list[str]) -> None: data.append("hello") data.sort()
额外说明
- 如果需要支持非序列的可变/不可变类型(比如映射),可以将
bound改为Mapping(只读)和MutableMapping(可变)。 - 自定义的可变/不可变类型,只需继承对应的抽象基类(如
Sequence/MutableSequence),就能被对应的TypeVar接受。 - 静态类型检查工具会严格约束:在只读方法中尝试修改参数会触发错误,确保代码符合设计意图。
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

