

【个人主页:】
大语言模型(LLM)开发工程师|中国传媒大学·数字媒体技术(智能交互与游戏设计) 深耕领域:大语言模型开发 / RAG知识库 / AI Agent落地 / 模型微调 技术栈:Python / LangChain/RAG(Dify+Redis+Milvus)| SQL/NumPy | FastAPI+Docker ️ 工程能力:专注模型工程化部署、知识库构建与优化,擅长全流程解决方案 专栏传送门:LLM大模型开发 项目实战指南、Python 从真零基础到纯文本 LLM 全栈实战、从零学 SQL + 大模型应用落地、大模型开发小白专属:从 0 入门 Linux&Shell 「让AI交互更智能,让技术落地更高效」 欢迎技术探讨/项目合作! 关注我,解锁大模型与智能交互的无限可能!
你是不是写 Python 代码时,处理不同类型的列表、字典、函数参数时,只能用Any类型导致代码可读性差、类型检查失败?这篇详解 Python 3.8 + 的泛型语法,包括 TypeVar 定义类型变量、Generic [T] 实现泛型类、Callable 和 Tuple 的高级用法,结合学生管理系统的 API 接口、ORM 查询、工具函数场景演示,让你彻底搞懂泛型的底层逻辑和应用场景。
在 Python 的入门阶段,很多开发者会用Any类型处理不同类型的数据,比如写一个处理列表的函数时,参数类型注解为list[Any]。这种做法会导致以下问题:
泛型的出现解决了这些问题,它允许我们在定义函数、类、类型注解时,使用类型变量来表示任意类型,提高代码的可读性、可维护性和可测试性。
TypeVar 是 Python 的泛型类型变量,它允许我们在定义函数、类、类型注解时,使用类型变量来表示任意类型。
语法:
from typing import TypeVar
T = TypeVar("T") # 任意类型
U = TypeVar("U", int, float) # 只能是int或float类型
V = TypeVar("V", bound=str) # 只能是str类型或str的子类Generic 是 Python 的泛型基类,它允许我们在定义类时,使用类型变量来表示类的属性、方法参数、方法返回值的类型。
语法:
from typing import Generic, TypeVar
T = TypeVar("T")
class MyClass(Generic[T]):
def __init__(self, value: T):
self.value = value
def get_value(self) -> T:
return self.value
def set_value(self, value: T):
self.value = valueTypeVar 的bound参数允许我们对类型变量进行约束,限制类型变量的取值范围。
语法:
from typing import TypeVar
V = TypeVar("V", bound=str) # 只能是str类型或str的子类TypeVar 的covariant=True参数允许我们对类型变量进行协变约束,限制类型变量的取值范围为子类。TypeVar 的contravariant=True参数允许我们对类型变量进行逆变约束,限制类型变量的取值范围为父类。
语法:
from typing import TypeVar
# 协变约束:只能是str类型或str的子类
T = TypeVar("T", bound=str, covariant=True)
# 逆变约束:只能是str类型或str的父类
U = TypeVar("U", bound=str, contravariant=True)泛型函数允许我们在定义函数时,使用类型变量来表示函数参数和返回值的类型。
代码示例(学生管理系统):
from typing import TypeVar, List
T = TypeVar("T")
def filter_list(data: List[T], condition) -> List[T]:
"""
根据条件过滤列表中的数据
:param data: 待过滤的数据列表
:param condition: 过滤条件(函数)
:return: 过滤后的数据列表
"""
return [item for item in data if condition(item)]
# 测试代码(过滤学生列表中年龄大于等于18岁的学生)
if __name__ == "__main__":
from app.schemas.students import StudentInfo
students: List[StudentInfo] = [
StudentInfo(
id=101,
student_no="20250001",
name="张三",
gender="男",
birthdate="2005-01-01",
phone="13800138001",
email="zhangsan@example.com",
address="北京市海淀区"
),
StudentInfo(
id=102,
student_no="20250002",
name="李四",
gender="女",
birthdate="2008-01-01",
phone="13800138002",
email="lisi@example.com",
address="北京市朝阳区"
)
]
def age_ge_18(student: StudentInfo) -> bool:
"""判断学生年龄是否大于等于18岁"""
birthdate = student.birthdate.split("-")
birth_year = int(birthdate[0])
current_year = 2025
return current_year - birth_year >= 18
filtered_students = filter_list(students, age_ge_18)
for student in filtered_students:
print(student.name)测试:运行测试代码,输出结果为张三。
泛型类允许我们在定义类时,使用类型变量来表示类的属性、方法参数、方法返回值的类型。
代码示例(学生管理系统):
from typing import TypeVar, Generic, List
T = TypeVar("T")
class Repository(Generic[T]):
"""
通用的Repository类,用于处理数据的CRUD操作
"""
def __init__(self, data: List[T] = None):
self.data = data or []
def get_all(self) -> List[T]:
"""获取所有数据"""
return self.data
def get_by_id(self, id: int) -> T:
"""根据ID获取单个数据"""
for item in self.data:
if item.id == id:
return item
raise Exception("数据不存在")
def create(self, item: T) -> T:
"""创建新数据"""
self.data.append(item)
return item
def update(self, id: int, item: T) -> T:
"""更新数据"""
for index, existing_item in enumerate(self.data):
if existing_item.id == id:
self.data[index] = item
return item
raise Exception("数据不存在")
def delete(self, id: int):
"""删除数据"""
for index, existing_item in enumerate(self.data):
if existing_item.id == id:
del self.data[index]
return
raise Exception("数据不存在")
# 测试代码(使用学生Repository)
if __name__ == "__main__":
from app.schemas.students import StudentInfo
student_repository = Repository[StudentInfo]()
student1 = StudentInfo(
id=101,
student_no="20250001",
name="张三",
gender="男",
birthdate="2005-01-01",
phone="13800138001",
email="zhangsan@example.com",
address="北京市海淀区"
)
student_repository.create(student1)
print(student_repository.get_all())测试:运行测试代码,输出结果为[StudentInfo(id=101, student_no='20250001', name='张三', gender='男', birthdate='2005-01-01', phone='13800138001', email='zhangsan@example.com', address='北京市海淀区')]。
泛型类型注解允许我们在使用类型注解时,使用类型变量来表示任意类型。
代码示例(学生管理系统):
from typing import TypeVar, Generic, List, Dict, Union, Tuple
T = TypeVar("T")
U = TypeVar("U")
# 泛型列表类型注解
GenericList = List[T]
# 泛型字典类型注解
GenericDict = Dict[T, U]
# 泛型元组类型注解
GenericTuple = Tuple[T, U]
# 泛型联合类型注解
GenericUnion = Union[T, U]
# 测试代码
if __name__ == "__main__":
from app.schemas.students import StudentInfo
student_list: GenericList[StudentInfo] = [
StudentInfo(
id=101,
student_no="20250001",
name="张三",
gender="男",
birthdate="2005-01-01",
phone="13800138001",
email="zhangsan@example.com",
address="北京市海淀区"
)
]
student_dict: GenericDict[int, StudentInfo] = {101: student_list[0]}
student_tuple: GenericTuple[int, StudentInfo] = (101, student_list[0])
student_union: GenericUnion[int, StudentInfo] = 101
print(student_list)
print(student_dict)
print(student_tuple)
print(student_union)测试:运行测试代码,输出结果为:
[StudentInfo(id=101, student_no='20250001', name='张三', gender='男', birthdate='2005-01-01', phone='13800138001', email='zhangsan@example.com', address='北京市海淀区')]
{101: StudentInfo(id=101, student_no='20250001', name='张三', gender='男', birthdate='2005-01-01', phone='13800138001', email='zhangsan@example.com', address='北京市海淀区')}
(101, StudentInfo(id=101, student_no='20250001', name='张三', gender='男', birthdate='2005-01-01', phone='13800138001', email='zhangsan@example.com', address='北京市海淀区'))
101FastAPI 支持泛型类型注解,可以用于 API 接口的请求体参数和响应体参数。
代码示例(学生管理系统):
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.models.students import Student
from app.schemas.students import StudentInfo, StudentCreate
from app.schemas.common import ApiResponse
from app.services.students_service import create_student, get_students_info, get_student_info
router = APIRouter(prefix="/students", tags=["Students"])
@router.post("/", response_model=ApiResponse[StudentInfo])
def create_student_info(student: StudentCreate, db: Session = Depends(get_db)):
"""创建学生信息"""
new_student = create_student(db, student)
return ApiResponse[StudentInfo](data=new_student)
@router.get("/", response_model=ApiResponse[list[StudentInfo]])
def get_students(page: int = 1, page_size: int = 10, db: Session = Depends(get_db)):
"""获取学生列表"""
students = get_students_info(db, page, page_size)
return ApiResponse[list[StudentInfo]](data=students)
@router.get("/{student_id}", response_model=ApiResponse[StudentInfo])
def get_student(student_id: int, db: Session = Depends(get_db)):
"""获取单个学生信息"""
student = get_student_info(db, student_id)
return ApiResponse[StudentInfo](data=student)说明:ApiResponse是一个泛型类,用于统一 API 接口的响应格式。
SQLAlchemy 1.4/2.0 支持泛型类型注解,可以用于 ORM 查询的返回值类型注解。
代码示例(学生管理系统):
from typing import TypeVar, Generic, List
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.models.students import Student
T = TypeVar("T")
class BaseRepository(Generic[T]):
"""
通用的BaseRepository类,用于处理数据的CRUD操作
"""
def __init__(self, db: Session, model: T):
self.db = db
self.model = model
def get_all(self) -> List[T]:
"""获取所有数据"""
return self.db.query(self.model).all()
def get_by_id(self, id: int) -> T:
"""根据ID获取单个数据"""
return self.db.query(self.model).filter(self.model.id == id).first()
def create(self, item: T) -> T:
"""创建新数据"""
self.db.add(item)
self.db.commit()
self.db.refresh(item)
return item
def update(self, id: int, item: T) -> T:
"""更新数据"""
existing_item = self.get_by_id(id)
if not existing_item:
raise Exception("数据不存在")
for key, value in item.__dict__.items():
if key != "_sa_instance_state":
setattr(existing_item, key, value)
self.db.commit()
self.db.refresh(existing_item)
return existing_item
def delete(self, id: int):
"""删除数据"""
existing_item = self.get_by_id(id)
if existing_item:
self.db.delete(existing_item)
self.db.commit()
# 学生Repository
class StudentRepository(BaseRepository[Student]):
"""
学生Repository类,用于处理学生数据的CRUD操作
"""
def __init__(self, db: Session):
super().__init__(db, Student)
def get_by_student_no(self, student_no: str) -> Student:
"""根据学号获取单个学生信息"""
return self.db.query(Student).filter(Student.student_no == student_no).first()
# 测试代码
if __name__ == "__main__":
db = next(get_db())
student_repository = StudentRepository(db)
students = student_repository.get_all()
print(students)测试:运行测试代码,输出结果为学生列表。
问题:类型变量定义错误,如没有使用 TypeVar 函数定义类型变量。
解决方案:使用 TypeVar 函数定义类型变量。
问题:泛型基类继承错误,如没有继承 Generic [T] 基类。
解决方案:继承 Generic [T] 基类。
问题:类型约束错误,如使用了不兼容的类型约束。
解决方案:使用兼容的类型约束。
问题:类型注解错误,如没有使用类型变量作为类型注解。
解决方案:使用类型变量作为类型注解。
通过以上步骤,我们详解了 Python 3.8 + 的泛型语法,包括 TypeVar 定义类型变量、Generic [T] 实现泛型类、类型约束、类型协变与逆变,结合学生管理系统的 API 接口、ORM 查询、工具函数场景演示,让你彻底搞懂泛型的底层逻辑和应用场景。
未来,我们可以对 Python 泛型进行以下优化: