TypeVar、泛型类与 Protocol
定义可复用的泛型类型,并使用 Protocol 实现结构化子类型。
TypeVar、泛型类与 Protocol 是 CoddyKit 上的免费 Python Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。
什么是 TypeVar
TypeVar 声明类型变量——一种可以代表任意类型的占位符,也可以根据需要加以限制。它用于泛型函数和类。
from typing import TypeVar
T = TypeVar("T")
def identity(value: T) -> T:
return value
print(identity(42)) # int
print(identity("hello")) # str泛型函数
在参数类型和返回类型中同时使用 TypeVar 的函数,可以让 mypy 根据参数类型推断返回类型。
from typing import TypeVar
T = TypeVar("T")
def first(items: list[T]) -> T:
return items[0]
x: int = first([1, 2, 3]) # mypy knows x is int
s: str = first(["a","b","c"]) # mypy knows s is str受约束的 TypeVar
将类型约束传给 TypeVar,即可限制可接受的类型。
from typing import TypeVar
Numeric = TypeVar("Numeric", int, float)
def double(n: Numeric) -> Numeric:
return n * 2
print(double(5)) # 10
print(double(2.5)) # 5.0
# double("x") # mypy error泛型类
继承 Generic[T],即可创建由类型变量参数化的类。
from typing import Generic, TypeVar
T = TypeVar("T")
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(1)
print(stack.pop()) # 1多个 TypeVar
使用多个 TypeVar,可以让类或函数接受两个相互独立的类型参数。
from typing import Generic, TypeVar
K = TypeVar("K")
V = TypeVar("V")
class Pair(Generic[K, V]):
def __init__(self, key: K, value: V) -> None:
self.key = key
self.value = value
p: Pair[str, int] = Pair("age", 30)
print(p.key, p.value) # age 30Protocol——结构化子类型
Protocol 根据类必须具备的方法和属性定义接口,而不要求显式继承(“鸭子类型,经过类型检查”)。
from typing import Protocol
class Drawable(Protocol):
def draw(self) -> None: ...
def render(obj: Drawable) -> None:
obj.draw()
class Circle:
def draw(self) -> None:
print("Drawing circle")
render(Circle()) # works — Circle satisfies Drawable带有 runtime_checkable 的 Protocol
将 @runtime_checkable 添加到 Protocol,即可在运行时启用 isinstance() 检查。
from typing import Protocol, runtime_checkable
@runtime_checkable
class Closeable(Protocol):
def close(self) -> None: ...
class File:
def close(self) -> None: print("closed")
print(isinstance(File(), Closeable)) # TrueProtocol 与 ABC
ABC 要求显式继承(class Dog(Animal))。Protocol 通过结构匹配工作——只要类具有正确的方法,无论是否继承,都满足该协议。
from typing import Protocol
from abc import ABC, abstractmethod
# ABC: nominal typing
class Printable(ABC):
@abstractmethod
def display(self) -> None: ...
# Protocol: structural typing
class Displayable(Protocol):
def display(self) -> None: ...带 bound 的 TypeVar
TypeVar("T", bound=BaseClass) 将 T 限制为 BaseClass 或其任意子类。
from typing import TypeVar
class Animal:
def speak(self) -> str: return "..."
A = TypeVar("A", bound=Animal)
def make_speak(animal: A) -> str:
return animal.speak()泛型别名——Python 3.12
Python 3.12 引入了 type 语句,用于简洁地创建类型别名;还引入了 class Foo[T] 语法,使创建泛型时无需导入 TypeVar。
# Python 3.12+
type Vector = list[float]
type Matrix = list[Vector]
class Stack[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()Self 类型
Self(3.11+ 中来自 typing)用于注解返回当前类的函数方法,在流式接口和子类中非常有用。
from typing import Self
class Builder:
def __init__(self) -> None:
self.parts: list[str] = []
def add(self, part: str) -> Self:
self.parts.append(part)
return self
b = Builder().add("a").add("b")
print(b.parts) # ["a", "b"]快速检查
在 Python 类型标注中,Protocol 与 ABC 的关键区别是什么?
回顾
TypeVar 为泛型函数和类创建类型占位符。Generic[T] 用于参数化类。Protocol 无需继承即可实现结构化子类型。使用 bound= 或 TypeVar 上的类型约束来限制可接受的类型。
常见问题解答
「TypeVar、泛型类与 Protocol」课时是免费的吗?
是的 — 「TypeVar、泛型类与 Protocol」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。
「TypeVar、泛型类与 Protocol」这节课中我会学到什么?
定义可复用的泛型类型,并使用 Protocol 实现结构化子类型。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Python Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「TypeVar、泛型类与 Protocol」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Python Academy 课中编写并运行代码吗?
能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 类型注解基础
- 复杂类型:List、Dict、Optional、Union
- TypeVar、泛型类与 Protocol
- 运行 mypy 与修复类型错误