Python从3.5版本引入类型提示系统后,逐步完善了泛型相关的支持,泛型类可以让我们定义能够适配多种类型的类,同时保留类型检查的能力,避免运行时出现类型不匹配的问题。

泛型类的基础定义
定义泛型类需要先从typing模块导入TypeVar和Generic,TypeVar用来声明一个类型变量,Generic是泛型类的基类,自定义的类需要继承Generic并指定类型变量。
下面是一个最简单的泛型类示例,实现一个可以存储任意类型单个值的容器类:
from typing import TypeVar, Generic
# 声明一个类型变量T,代表任意类型
T = TypeVar('T')
# 定义泛型类,继承Generic[T]
class Container(Generic[T]):
def __init__(self, value: T):
self.value = value
def get_value(self) -> T:
return self.value
# 使用泛型类,指定类型为int
int_container = Container[int](10)
print(int_container.get_value()) # 输出10
# 指定类型为str
str_container = Container[str]("hello")
print(str_container.get_value()) # 输出hello
带类型约束的泛型类
有时候我们希望泛型类只支持某几类特定类型,这时候可以给TypeVar添加约束,约束可以是多个类型的联合,类型变量只能被替换为这些约束类型或其子类。
比如我们定义一个只支持数值类型的计算器类:
from typing import TypeVar, Generic, Union
# 约束T只能是int或float类型
T = TypeVar('T', int, float)
class NumberCalculator(Generic[T]):
def __init__(self, num1: T, num2: T):
self.num1 = num1
self.num2 = num2
def add(self) -> T:
return self.num1 + self.num2
# 正确使用,int类型
int_calc = NumberCalculator[int](1, 2)
print(int_calc.add()) # 输出3
# 正确使用,float类型
float_calc = NumberCalculator[float](1.5, 2.5)
print(float_calc.add()) # 输出4.0
# 错误用法,str类型不符合约束,类型检查会报错
# str_calc = NumberCalculator[str]("a", "b")
多类型参数的泛型类
泛型类也支持同时定义多个类型变量,用来处理需要多种不同类型参数的场景,多个类型变量之间用逗号分隔即可。
下面是一个键值对容器的示例,键和值可以是不同的类型:
from typing import TypeVar, Generic, Dict
# 声明两个类型变量,K代表键类型,V代表值类型
K = TypeVar('K')
V = TypeVar('V')
class PairContainer(Generic[K, V]):
def __init__(self, key: K, value: V):
self.pair = {key: value}
def get_pair(self) -> Dict[K, V]:
return self.pair
# 键为str,值为int
str_int_pair = PairContainer[str, int]("age", 20)
print(str_int_pair.get_pair()) # 输出{'age': 20}
# 键为int,值为str
int_str_pair = PairContainer[int, str](1, "one")
print(int_str_pair.get_pair()) # 输出{1: 'one'}
泛型类的实际应用场景
泛型类在实际开发中有很多实用场景,最常见的就是通用数据容器、工具类封装、接口返回封装等。
比如封装一个通用的接口返回类,支持不同返回数据类型:
from typing import TypeVar, Generic, Optional
T = TypeVar('T')
class ApiResponse(Generic[T]):
def __init__(self, code: int, message: str, data: Optional[T] = None):
self.code = code
self.message = message
self.data = data
def is_success(self) -> bool:
return self.code == 200
# 返回用户数据,data类型为dict
user_response = ApiResponse[dict](200, "success", {"name": "张三", "age": 25})
print(user_response.is_success()) # 输出True
# 返回列表数据,data类型为list
list_response = ApiResponse[list](200, "success", [1, 2, 3])
print(list_response.data) # 输出[1, 2, 3]
注意事项
- Python的泛型是运行时类型提示,不会在运行时强制约束类型,主要作用是给类型检查工具(如mypy)和IDE提供类型信息,提升开发体验。
- 如果不需要类型约束,使用
TypeVar('T')即可,如果需要约束,在TypeVar的参数中传入允许的类型。 - 泛型类继承时,如果子类需要固定父类的部分类型参数,可以直接指定,比如
class IntContainer(Container[int]): pass,这样IntContainer就只能处理int类型。
合理使用泛型类可以大幅提升代码的复用性,同时让代码的类型逻辑更清晰,建议在需要通用类型处理的场景下优先使用泛型类。