python使用泛型
所谓的泛型, 就是将数据类型作为参数进行传递, 即在我们用的时候确定数据类型, 这是一种在面向对象语言中经常使用的特性
一般类使用
以SQLAlchemy举例
比如: 我们统一写个将数据保存到数据库的接口, 只有将数据库链接 表对象 数据传入即可, 返回的是表对象的实例, 为了让IDE可以识别返回对象, 我们可以使用泛型
这里需要用到:
typing的TypeVar和Type
TypeVar是类型变量, 主要用于泛型类型与泛型函数定义的参数, 第一个参数是名称,bound参数用于规定该类型为bound值的子类
Type[C]的形式为协变量, 表明C的所有子类都应 使用与C相同的 构造器签名 及 类方法签名, 假如我们需要返回泛型类型的话, 需要用到更多使用方法, 见: typing使用
使用了
pydantic规范要创建数据的类型关于
pydantic的一般使用, 见: Pydantic使用
from typing import TypeVar, Type
from sqlalchemy.orm import Session
from pydantic import BaseModel
from orm.models import Category
from orm.schemas import WriteCategoryModel
# 定义类型
ModelT = TypeVar("ModelT")
DataT = TypeVar("DataT", bound=BaseModel) # bound表明该类为BaseModel的子类
"""
为节省空间, 表结构和模型不展示
"""
def create_category(session: Session, data: WriteCategoryModel) -> Type[Category]:
cate_obj = save_one_to_db(session=session, model_class=Category, data=data)
return cate_obj
def save_one_to_db(session: Session, model_class: ModelT, data: DataT) -> ModelT:
"""
保存一条到数据库
:param session: SQLAlchemy Session
:param model_class: sqlalchemy模型类
:param data: pydantic模型对象
:return: 对应sqlalchemy模型类的对象
"""
try:
obj = model_class(**data.dict())
session.add(obj)
session.commit()
# 手动将 数据 刷新到数据库
session.refresh(obj)
return obj
except Exception as e:
# 别忘记发生错误时回滚
session.rollback()
raise e
pydantic使用
在使用pydantic时, 亦可以使用泛型
比如: 在FastAPI中返回统一返回格式为:
{
"status": true,
"msg": "success",
"data": ...
}
我们的data可能是列表或对象, 而且对应的pydantic模型也不一样, 这时我们就可以使用泛型了
代码:
from typing import List, Optional, Generic, TypeVar
from fastapi import APIRouter, status, HTTPException
from pydantic import BaseModel
from pydantic.generics import GenericModel
router = APIRouter(prefix="/test", tags=["测试泛型"])
# 为了方便, 在这里定义pydantic模型
DataT = TypeVar("DataT")
class GenericResponse(GenericModel, Generic[DataT]):
"""
通用返回数据
"""
status: bool
msg: str
data: Optional[DataT] = None # 可能连data都没有
# 设置response_model_exclude_unset=True即可
class BookModel(BaseModel):
id: int
name: str
# 伪数据
fake_book_data = [
{"id": 1, "name": "book1"},
{"id": 2, "name": "book2"},
{"id": 3, "name": "book3"},
{"id": 4, "name": "book4"},
{"id": 5, "name": "book5"},
]
@router.get("/books", response_model=GenericResponse[List[BookModel]])
def get_books():
return {
"status": True,
"msg": "获取成功",
"data": fake_book_data
}
@router.get("/books/{bid}", response_model=GenericResponse[BookModel])
def retrieve_book(bid: int):
for item in fake_book_data:
if item.get("id") == bid:
return {
"status": True,
"msg": "获取成功",
"data": item
}
# 不存在
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="该书不存在")
访问/docs页面, 成功通过测试

python使用泛型的更多相关文章
- 【Java心得总结四】Java泛型下——万恶的擦除
一.万恶的擦除 我在自己总结的[Java心得总结三]Java泛型上——初识泛型这篇博文中提到了Java中对泛型擦除的问题,考虑下面代码: import java.util.*; public clas ...
- Python - typing 模块 —— TypeVar 泛型
前言 typing 是在 python 3.5 才有的模块 前置学习 Python 类型提示:https://www.cnblogs.com/poloyy/p/15145380.html 常用类型提示 ...
- 【Python五篇慢慢弹】快速上手学python
快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...
- 自发行python版本制作(一)
最近使用python开发一些小玩意,发现python实在很符合我的理念:轻量级,功能强大,开放. python是一种脚本语言,不像java那样需要沉重的编译过程.这使得python更显得轻巧灵便,可以 ...
- Python 基礎 - 文件的操作
在來我們來玩一下文件操作,這個在未來工作上,也是會很常用到的功能 Python2.7中,可以用file()來打開文件,而在Python3中,一律都是用open(),接下來在當前目錄下,先建立一個空文件 ...
- [python实现设计模式]-5.迭代器模式-一起撸串嗨皮啦
迭代器模式是一个我们经常使用但是出境不高的模式. 为啥捏?因为大部分的语言都帮我们实现了细节,我们不许关注他的实现就能用的很嗨皮了. 不管怎样.这也是个非常常用的模式. 俗话说得好,这个世界上没有事情 ...
- 【循序渐进学Python】14.数据库的支持
纯文本只能够实现一些简单有限的功能.如果想要实现自动序列化,也可以使用 shelve 模块和 pickle 模块来实现.但是,如果想要自动的实现数据并发访问,以及更标准,更通用的数据库(databas ...
- Python基础s14-day1
2016年7月23日"Python基础s14-Day1" Python是什么? Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/),是一种面向对象.直译式 ...
- Python简易聊天工具-基于异步Socket通信
继续学习Python中,最近看书<Python基础教程>中的虚拟茶话会项目,觉得很有意思,自己敲了一遍,受益匪浅,同时记录一下. 主要用到异步socket服务客户端和服务器模块asynco ...
随机推荐
- Nginx 防爬虫设置
在conf下 vi 一个文件agent_deny.conf 添加如下内容 #禁止Scrapy|curl等工具的抓取 if ($http_user_agent ~* (Scrapy|Curl|Http ...
- 聊聊docker那些端口问题
今天来系统聊一聊docker的端口,常见的有容器内程序端口.容器端口.主机端口.Dockerfile中EXPOSE端口.docker-compose和docker run中的port等. 貌似很多端口 ...
- Servlet初级学习加入数据库操作(一)
需要的源代码地址: https://url56.ctfile.com/f/34653256-527822631-2e255a(访问密码:7567) 将页面中的数据逐步替换为数据库管理 准备一个连接数据 ...
- UDP代码编写、操作系统发展史、多道技术、进程理论与代码层面创建、进程join方法与进程对象方法
昨日内容回顾 socket基本使用 # 内置的模块 import socket s = socket.socket() # 默认是TCP协议 也可以切换为UDP协议 s.bind((ip,port)) ...
- Web开发之Cookie and Session
会话 什么是会话? 简单说:用户开一个浏览器,点击多个超链接,访问服务器的多个web资源,然后关闭浏览器,整个过程就称之为一个会话. 会话过程要解决什么问题 每个用户在使用浏览器与服务器进行会话的过程 ...
- linux 安装mysql 可能遇到的小问题
问题一. ./mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No ...
- 《剑指offer》面试题57. 和为s的两个数字
问题描述 输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s.如果有多对数字的和等于s,则输出任意一对即可. 示例 1: 输入:nums = [2,7,11,15], tar ...
- office 下载(免费使用
https://otp.landian.vip/zh-cn/download.html
- MySQL的学习记录 DAY03~
小记:昨天打了新冠加强针,今天开始拉肚子,嗓子疼,超级难受~
- gin中如何记录日志和错误日志
package main import ( "github.com/gin-gonic/gin" "io" "os" ) func main ...