深入FastAPI:路径参数、查询参数及其检校

引言

大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年11月学习赛的FastAPI学习总结文档;本文主要讲解路径参数、查询参数及其检校机制。💕💕😊


介绍

FastAPI 是一个现代、快速(高性能)的 Web 框架,基于 Python 3.7+ 标准类型提示。它特别适合构建 API,因为它支持异步编程、自动生成文档,并且具有强大的数据验证功能。本文将深入探讨 FastAPI 中的路径参数、查询参数及其检校机制,并通过实际代码示例帮助你更好地理解和应用这些概念


一、FastAPI 基础

1. FastAPI 简介

FastAPI 是一个基于 Python 的 Web 框架,旨在提供高性能、易于使用和快速开发的特性。它利用 Python 的类型提示来进行数据验证和自动生成文档,使得开发 API 变得更加简单和高效。

2. 安装 FastAPI

首先,你需要安装 FastAPI 和 Uvicorn(一个 ASGI 服务器)。你可以通过以下命令进行安装:

pip install fastapi uvicorn

3. 创建第一个 FastAPI 应用

创建一个简单的 FastAPI 应用,启动一个基本的 Web 服务:

from fastapi import FastAPIapp = FastAPI()@app.get("/")
def read_root():return {"Hello": "World"}if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)


二、路径参数

1. 常见 HTTP 请求方法

在 FastAPI 中,常见的 HTTP 请求方法包括:

① GET:用于获取资源
  • 幂等性:是
  • 缓存:GET 请求可以被缓存,这意味着如果相同的请求多次发出,浏览器可能会使用缓存的响应而不是重新发送请求。
  • 安全性:GET 请求是安全的,因为它只用于读取数据,不会对服务器上的资源进行修改。
  • URL 参数:GET 请求的参数通常通过 URL 传递,这使得它们容易被记录在服务器日志、浏览器历史记录中,并且可以被收藏为书签。
  • 使用场景:适用于获取数据、查询资源、获取资源列表等场景。
② POST:用于创建资源
  • 幂等性:否
  • 缓存:POST 请求不会被缓存,每次请求都会导致服务器处理请求并生成新的资源。
  • 安全性:POST 请求不是安全的,因为它会修改服务器上的资源。
  • 请求体:POST 请求的数据通常放在请求体中,这使得它可以传递更复杂的数据结构,如 JSON、XML 等。
  • 使用场景:适用于提交表单数据、上传文件、创建新资源等场景。
③ PUT:用于更新资源
  • 幂等性:是
  • 缓存:PUT 请求不会被缓存。
  • 安全性:PUT 请求不是安全的,因为它会修改服务器上的资源。
  • 请求体:PUT 请求的数据通常放在请求体中,用于更新指定的资源。如果资源不存在,PUT 请求可以用于创建资源。
  • 使用场景:适用于更新现有资源、替换资源内容等场景。
④ DELETE:用于删除资源
  • 幂等性:是
  • 缓存:DELETE 请求不会被缓存。
  • 安全性:DELETE 请求不是安全的,因为它会删除服务器上的资源。
  • 使用场景:适用于删除指定资源、清理资源等场景。
⑤ 补充知识
  • 幂等性与安全性:幂等性和安全性是 HTTP 方法的两个重要特性。幂等性意味着多次执行相同的操作不会产生不同的结果,而安全性意味着操作不会修改服务器上的资源。
  • URL 确定性:在使用 PUT 和 POST 时,URL 的确定性是一个关键因素。如果 URL 可以在客户端确定(例如,资源的唯一标识符已知),则使用 PUT;如果 URL 需要在服务端确定(例如,使用数据库自增主键),则使用 POST。
  • 状态码:在 FastAPI 中,不同的 HTTP 方法通常会返回不同的状态码。例如,GET 请求成功时通常返回 200 OK,POST 请求成功时通常返回 201 Created,PUT 请求成功时通常返回 200 OK 或 204 No Content,DELETE 请求成功时通常返回 204 No Content。

2. 路径参数的基本概念

路径参数是 URL 中的一部分,用于标识特定的资源。它们通常用于动态地指定资源的位置或标识符。路径参数在 FastAPI 中非常重要,因为它们允许你根据 URL 中的不同部分来处理不同的资源。

假设我们有一个 API,用于管理用户和他们的订单。我们可以使用路径参数来标识特定的用户和订单。

示例 1:获取特定用户的信息
from fastapi import FastAPIapp = FastAPI()@app.get("/users/{user_id}")
def get_user(user_id: int):# 假设我们从数据库中获取用户信息user_info = {"user_id": user_id, "name": "John Doe", "email": "john.doe@example.com"}return user_info

在这个例子中,/users/{user_id} 中的 {user_id} 是一个路径参数。当客户端请求 /users/123 时,user_id 将被解析为 123,并且 get_user 函数将返回用户 ID 为 123 的用户信息。如下图:

示例 2:获取特定用户的订单
@app.get("/users/{user_id}/orders/{order_id}")
def get_order(user_id: int, order_id: int):# 假设我们从数据库中获取订单信息order_info = {"user_id": user_id, "order_id": order_id, "product": "Laptop", "price": 1200}return order_info

在这个例子中,/users/{user_id}/orders/{order_id} 中的 {user_id}{order_id} 是两个路径参数。当客户端请求 /users/123/orders/456 时,user_id 将被解析为 123order_id 将被解析为 456,并且 get_order 函数将返回用户 ID 为 123 的订单 ID 为 456 的订单信息。

示例 3:更新特定用户的订单
from fastapi import FastAPI, HTTPExceptionapp = FastAPI()@app.put("/users/{user_id}/orders/{order_id}")
def update_order(user_id: int, order_id: int, new_product: str, new_price: float):# 假设我们更新数据库中的订单信息if not order_exists(user_id, order_id):raise HTTPException(status_code=404, detail="Order not found")# 更新订单信息update_order_in_db(user_id, order_id, new_product, new_price)return {"message": "Order updated successfully"}def order_exists(user_id: int, order_id: int) -> bool:# 假设我们检查订单是否存在return True  # 示例中假设订单总是存在def update_order_in_db(user_id: int, order_id: int, new_product: str, new_price: float):# 假设我们更新数据库中的订单信息pass

在这个例子中,/users/{user_id}/orders/{order_id} 中的 {user_id}{order_id} 是两个路径参数。当客户端请求 /users/123/orders/456 并附带新的产品名称和价格时,update_order 函数将更新用户 ID 为 123 的订单 ID 为 456 的订单信息。

完整代码
from fastapi import FastAPI, HTTPExceptionapp = FastAPI()# 示例 1:获取特定用户的信息
@app.get("/users/{user_id}")
def get_user(user_id: int):# 假设我们从数据库中获取用户信息user_info = {"user_id": user_id, "name": "John Doe", "email": "john.doe@example.com"}return user_info# 示例 2:获取特定用户的订单
@app.get("/users/{user_id}/orders/{order_id}")
def get_order(user_id: int, order_id: int):# 假设我们从数据库中获取订单信息order_info = {"user_id": user_id, "order_id": order_id, "product": "Laptop", "price": 1200}return order_info# 示例 3:更新特定用户的订单
@app.put("/users/{user_id}/orders/{order_id}")
def update_order(user_id: int, order_id: int, new_product: str, new_price: float):# 假设我们更新数据库中的订单信息if not order_exists(user_id, order_id):raise HTTPException(status_code=404, detail="Order not found")# 更新订单信息update_order_in_db(user_id, order_id, new_product, new_price)return {"message": "Order updated successfully"}def order_exists(user_id: int, order_id: int) -> bool:# 假设我们检查订单是否存在return True  # 示例中假设订单总是存在def update_order_in_db(user_id: int, order_id: int, new_product: str, new_price: float):# 假设我们更新数据库中的订单信息pass# 启动 FastAPI 应用程序的指令
if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)

路径参数在 FastAPI 中用于动态地指定资源的位置或标识符。通过在 URL 中使用路径参数,你可以根据不同的参数值来处理不同的资源。路径参数的使用使得 API 更加灵活和强大,能够处理各种复杂的资源请求。

3. 构建一个 TodoList 的 CRUD 示例

我们以一个简单的 TodoList 应用为例,展示如何使用 FastAPI 进行增删改查操作:

from fastapi import FastAPI
from pydantic import BaseModel
from typing import Listapp = FastAPI()class Todo(BaseModel):id: inttask: strtodos = [{"id": 1,"task": "Learn FastAPI"
}]@app.post("/todos/", response_model=Todo)
def create_todo(todo: Todo):todos.append(todo)return todo@app.get("/todos/", response_model=List[Todo])
def read_todos():return todos@app.get("/todos/{todo_id}", response_model=Todo)
def read_todo(todo_id: int):for todo in todos:print(todo),"todo"if todo["id"] == todo_id:return todoreturn {"error": "Todo not found"}@app.put("/todos/{todo_id}", response_model=Todo)
def update_todo(todo_id: int, updated_todo: Todo):for i, todo in enumerate(todos):if todo["id"] == todo_id:todos[i] = updated_todoreturn updated_todoreturn {"error": "Todo not found"}@app.delete("/todos/{todo_id}")
def delete_todo(todo_id: int):for i, todo in enumerate(todos):if todo["id"]== todo_id:del todos[i]return {"message": "Todo deleted"}return {"error": "Todo not found"}# 启动 FastAPI 应用程序的指令
if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)

这里我们可以使用FastAPI自带的文档http://127.0.0.1:8000/docs进行查看:

  • GET请求

  • POST请求

  • PUT请求

  • DELETE请求

4. 路径参数的类型限制

在 FastAPI 中,路径参数可以指定类型,例如 intstr 等。FastAPI 会自动进行类型转换和验证。

@app.get("/items/{item_id}")
def read_item(item_id: int):return {"item_id": item_id}

如果使用了不同的类型,则会报错

5. 数据检校与 Pydantic

Pydantic 是 FastAPI 中用于数据验证和解析的库。它通过 Python 的类型提示来定义数据模型,并自动进行验证。Pydantic 的主要作用是确保传入的数据符合预期的格式和类型,从而减少手动验证的复杂性和错误。

from pydantic import BaseModelclass Item(BaseModel):name: strprice: floatis_offer: bool = None

在这个案例中,我们定义了一个 Item 类,它继承自 BaseModel。这个类有三个字段:

  • name: 类型为 str,表示商品的名称。
  • price: 类型为 float,表示商品的价格。
  • is_offer: 类型为 bool,表示商品是否为特价商品。这个字段有一个默认值 None,表示它是可选的。

使用 Pydantic 进行数据检校的一般流程如下:

  1. 定义数据模型:首先,你需要定义一个继承自 BaseModel 的类,并在类中定义字段及其类型。
  2. 实例化数据模型:当你接收到数据时,将数据传递给数据模型的构造函数,Pydantic 会自动验证数据是否符合定义的类型和格式。
  3. 处理验证结果:如果数据验证通过,你可以继续处理数据;如果验证失败,Pydantic 会抛出一个 ValidationError 异常,并提供详细的错误信息。

下面案例代码中,展示了如何使用 Pydantic 进行数据验证和解析。

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, ValidationErrorapp = FastAPI()# 定义数据模型
class Item(BaseModel):name: strprice: floatis_offer: bool = None# 示例 1:创建新商品
@app.post("/items/")
def create_item(item: Item):# 数据已经通过 Pydantic 验证return {"message": "Item created successfully", "item": item}# 示例 2:更新商品信息
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):# 假设我们更新数据库中的商品信息if not item_exists(item_id):raise HTTPException(status_code=404, detail="Item not found")# 更新商品信息update_item_in_db(item_id, item)return {"message": "Item updated successfully", "item": item}def item_exists(item_id: int) -> bool:# 假设我们检查商品是否存在return True  # 示例中假设商品总是存在def update_item_in_db(item_id: int, item: Item):# 假设我们更新数据库中的商品信息pass# 启动 FastAPI 应用程序的指令
if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)
  • 如果传入的数据符合 Item 模型的定义,Pydantic 会自动解析并验证数据。
  • 如果数据不符合定义,Pydantic 会抛出一个 ValidationError 异常,并返回详细的错误信息。

Pydantic 是 FastAPI 中用于数据验证和解析的强大工具。通过定义数据模型并使用 Pydantic 进行验证,开发者可以确保传入的数据符合预期的格式和类型,从而减少手动验证的复杂性和错误。Pydantic 还提供了详细的错误信息,辅助快速定位和修复问题。

6. 预设值与枚举值

你可以为路径参数设置预设值或使用枚举值进行限制:

from enum import Enumclass ModelName(str, Enum):alexnet = "alexnet"resnet = "resnet"lenet = "lenet"@app.get("/models/{model_name}")
def get_model(model_name: ModelName):if model_name == ModelName.alexnet:return {"model_name": model_name, "message": "Deep Learning FTW!"}if model_name.value == "lenet":return {"model_name": model_name, "message": "LeCNN all the images"}return {"model_name": model_name, "message": "Have some residuals"}

7. 包含路径的路径参数

路径参数可以包含路径,例如 /files/{file_path:path},其中 file_path 可以是一个文件路径。

@app.get("/files/{file_path:path}")
def read_file(file_path: str):return {"file_path": file_path}

三、查询参数

1. 查询参数的基本概念

查询参数是 URL 中 ? 后面的部分,用于传递额外的信息。例如,/items/?skip=0&limit=10 中的 skiplimit 就是查询参数。

2. 默认查询参数

你可以为查询参数设置默认值:

@app.get("/items/")
def read_items(skip: int = 0, limit: int = 10):return {"skip": skip, "limit": limit}

这里的skip: int = 0就指代默认的skip参数是0,如果用户不指定该值,则会默认这个参数为0;

3. 必需查询参数

某些查询参数是必需的,如果没有提供,FastAPI 会返回错误:

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str):return {"item_id": item_id, "q": q}

这里我们没有为其设置默认值,如果不输入该值,其会报错

4. 可选查询参数

你可以将查询参数设置为可选的,并提供默认值:

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):return {"item_id": item_id, "q": q}

可有可没有的参数,如果有需要你就传入,如果不需要,函数也不会报错;注意区分可选查询参数和默认查询参数

5. 多个路径参数与多个查询参数

在 FastAPI 中,用户可以同时使用多个路径参数和多个查询参数:

@app.get("/items/{item_id}/users/{user_id}")
def read_item_user(item_id: int, user_id: int, q: str = None, short: bool = False):item = {"item_id": item_id, "user_id": user_id}if q:item.update({"q": q})if not short:item.update({"description": "This is an amazing item that has a long description"})return item
  • 路径参数用以简单参数传递;
  • 查询参数通过get或post请求中使用较多;

四、路径参数检校

在 FastAPI 中,路径参数校验是一个非常重要的功能,它允许开发者为路径参数添加类型检查、数值范围限制以及元数据声明。通过使用 Path 库可以轻松地实现这些功能。

1. 概念理解

① 导入 Path

首先,你需要从 fastapi 中导入 Path

from fastapi import FastAPI, Path
② 声明元数据

声明元数据是为了提供更多的信息,帮助开发者和其他使用者更好地理解 API 的设计意图。元数据可以包括标题、描述等。

from typing import Annotated
from fastapi import FastAPI, Pathapp = FastAPI()@app.get("/items/{item_id}")
async def read_items(item_id: Annotated[int, Path(title="The ID of the item to get")]
):results = {"item_id": item_id}return results

在这个例子中,item_id 是一个路径参数,并且我们为其添加了一个标题 "The ID of the item to get"。这个标题可以帮助其他开发者理解这个参数的用途。

③ 数值校验

数值校验是为了确保路径参数的值在合理的范围内。FastAPI 提供了以下几种数值校验参数:

  • gt: 大于(greater than)
  • ge: 大于等于(greater than or equal)
  • lt: 小于(less than)
  • le: 小于等于(less than or equal)

2.案例

① 大于等于校验

下面代码中展示了如何使用 Path 库进行数值校验:

import uvicorn
from typing import Annotated
from fastapi import FastAPI, Pathapp = FastAPI()@app.get("/items/{item_id}")
async def read_items(item_id: Annotated[int, Path(title="The ID of the item to get", ge=5)]
):results = {"item_id": item_id}return resultsif __name__ == '__main__':uvicorn.run(app, host='127.0.0.1', port=8009)

在这里,item_id 必须是一个大于或等于 5 的整数。如果请求的路径参数不满足这个条件,FastAPI 会返回一个 422 错误。

  • 测试

我们在http//127.0.0.1:8009/docs进行测试:

  • 访问 http://127.0.0.1:8009/items/6,你会看到 {"item_id": 6}

  • 访问 http://127.0.0.1:8009/items/4,你会看到一个错误信息,提示 item_id 必须大于或等于 5。

② 浮点数校验

数值校验同样适用于浮点数。以下是一个示例,展示了如何对浮点数进行校验:

import uvicorn
from typing import Annotated
from fastapi import FastAPI, Pathapp = FastAPI()@app.get("/items-float/{item_id}")
async def read_items(item_id: Annotated[float, Path(title="The ID of the item to get", ge=5.5)]
):results = {"item_id": item_id}return resultsif __name__ == '__main__':uvicorn.run(app, host='127.0.0.1', port=8009)

在这个例子中,item_id 必须是一个大于或等于 5.5 的浮点数。

  • 访问 http://127.0.0.1:8009/items/5.6,你会看到 {"item_id": 5.6}

  • 访问 http://127.0.0.1:8009/items/5.4,你会看到一个错误信息,提示 item_id 必须大于或等于 5.5。

这里你或许会尝试输入6来验证错误,但是在python中,整数是可以被自动转换为浮点型的,因此输入6并不会报类型错误;


五、查询参数检校

我们依旧在http://127.0.0.1:8000/docs#/中进行测试:

1. 字符串参数限制

你可以对查询参数进行字符串长度限制:

from fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
def read_items(q: str = Query(None, max_length=50)):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

这里如果传入的字符串长度超过50,就会报错!

2. 增加额外的约束条件

你可以为查询参数增加更多的约束条件,例如最小长度、正则表达式等:

@app.get("/items_with_constraints/")
def read_items_with_constraints(q: str = Query(None, min_length=3, max_length=50, regex="^[a-z]+$")
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

这里要求我们最小长度为3,最大为50;q只能包含小写字幕并且至少有一个字符;这里如果我们填写不规范,都会报错422;

3. 最短字符长度与正则表达式

你可以使用 min_lengthregex 来进一步限制查询参数:

@app.get("/items_with_regex/")
def read_items_with_regex(q: str = Query(None, min_length=3, max_length=50, regex="^[a-z]+$")
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

4. 声明必需参数与省略号

你可以使用 ... 来声明必需的查询参数:

@app.get("/items_required/")
def read_items_required(q: str = Query(..., min_length=3)):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

使用 <font style="color:rgb(64, 64, 64);">...</font> 来声明必需的查询参数是一种明确的方式,表示该参数是必需的,不能省略

5. 声明更多元数据

你可以为查询参数声明更多的元数据,例如标题、描述等:

@app.get("/items_with_metadata/")
def read_items_with_metadata(q: str = Query(None,title="Query string",description="Query string for the items to search in the database that have a good match",min_length=3,)
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

声明详细的元数据可以帮助开发者更好的理解接口!

6.完整代码

代码如下,各位仔细测试就好!

from fastapi import FastAPI, Queryapp = FastAPI()# 1. 字符串参数限制
@app.get("/items/")
def read_items(q: str = Query(None, max_length=50)):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results# 2. 增加额外的约束条件
@app.get("/items_with_constraints/")
def read_items_with_constraints(q: str = Query(None, min_length=3, max_length=50, regex="^[a-z]+$")
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results# 3. 最短字符长度与正则表达式
@app.get("/items_with_regex/")
def read_items_with_regex(q: str = Query(None, min_length=3, max_length=50, regex="^[a-z]+$")
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results# 4. 声明必需参数与省略号
@app.get("/items_required/")
def read_items_required(q: str = Query(..., min_length=3)):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results# 5. 声明更多元数据
@app.get("/items_with_metadata/")
def read_items_with_metadata(q: str = Query(None,title="Query string",description="Query string for the items to search in the database that have a good match",min_length=3,)
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results# 运行 FastAPI 应用
if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)

总结

通过本文,我们深入探讨了 FastAPI 中的路径参数、查询参数及其检校机制。作者通过实际代码示例展示了如何使用 FastAPI 构建一个简单的 TodoList 应用,并详细介绍了路径参数和查询参数的各种用法和限制。希望本文能帮助你更好地理解和应用 FastAPI,提升各位入门者的 Python Web 开发技能。

OK!今天就学习到这里了!😎


相关链接

  • 项目地址:FastAPI-CookBook
  • 相关文档:专栏地址
  • 作者主页:GISer Liu-CSDN博客

thank_watch

如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/13300.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

图数据库 | 5、图数据库三大组件之一 之 图计算 (下)

书接上文&#xff1a;图数据库 | 4、图数据库三大组件之一 ——图计算 &#xff08;上&#xff09;-CSDN博客 结合计算效率来评估与设计图计算所需的数据结构。 存储低效性或许是相邻矩阵或关联矩阵等数据结构的最大缺点&#xff0c;尽管它有着O(1)的访问时间复杂度。例如通过…

由播客转向个人定制的音频频道(1)平台搭建

项目的背景 最近开始听喜马拉雅播客的内容&#xff0c;但是发现许多不方便的地方。 休息的时候收听喜马拉雅&#xff0c;但是还需要不断地选择喜马拉雅的内容&#xff0c;比较麻烦&#xff0c;而且黑灯操作反而伤眼睛。 喜马拉雅为代表的播客平台都是VOD 形式的&#xff0…

被抛弃的八股文之keep-alive

还记得在我毕业面试时&#xff0c;经常看到碰到的面试题中都有着TCP中的keep-alive和Http中的keep-alive有什么区别。但是现在的八股文中已经再也见不到了&#xff08;燕子&#xff0c;我们还会再见吗&#xff09; 话说回来&#xff0c;这两个不同的协议中&#xff0c;keep-ali…

衡石分析平台系统分析人员手册-指标管理

指标管理​ 指标平台通过业务主题管理指标&#xff0c;对指标进行授权使用。在指标管理中业务管理员根据业务情况创建相关的主题&#xff0c;将与业务相关的指标添加到主题中&#xff0c;对指标进行上下线管理&#xff0c;将主题及其下面的指标授权给平台内其他用户使用。 本…

【万码优才,等你到来】一款针对程序员求职的平台

hello&#xff0c;大家好我是万码优才推荐官→Aic山鱼&#xff0c;在面对广大程序员找工作的前期我为大家推荐一款超牛的求职平台 ——万码优才 针对当前的求职情况山鱼君也做了一写总结与分析&#xff0c;也结合了其他求职平台给出了“为什么要使用万码优才 这个平台”的原因 …

echarts bar3D画出圆角立方体模拟建筑

结果展示 重点 bar3D中圆角属性&#xff1a;roundCap: true //开启圆角&#xff08;echarts官方文档中没有&#xff09;bevelSize: .6 //圆角程度barSize: 12.5 //立方体大小半球形使用 surface 类型,曲线方程如下 parametricEquation: {u: {min: 0,max: Math.PI,step: Ma…

从建立TRUST到实现FAIR:可持续海洋经济的数据管理

1. 引言 随着我们对信息管理方式的信任&#xff0c;我们的社会对数字化数据的以来呈指数级增长。为了跟上大数据的需求&#xff0c;通过不断的努力和持续实践&#xff0c;对“good”数据管理方式的共识也在不断发展和演变。 加拿大正在建设国家基础设施和服务以及研究数据管理…

CTF-RE 从0到N: perl 逆向

WMCTF2020 easy_re 1.寻找字符串Script 2.通过下一个call 3.将rax的值解析为字符串

RecyclerView详解——(二)优劣,ItemDecoration,SnapHelper

本文主要讲述RecyclerView和ListView的区别&#xff0c;ItemDecoration实现分割线&#xff0c;边距和背景&#xff0c;以及SnapHelper的使用。 一、RecyclerView和ListView 1. 性能和视图重用 ListView 使用的是 ViewHolder 模式来实现视图的重用&#xff0c;但需要手动配置…

[运维][Nginx]Nginx学习(2/5)-Nginx高级

Nginx服务器基础配置实例 前面我们已经对Nginx服务器默认配置文件的结构和涉及的基本指令做了详细的阐述。通过这些指令的合理配置&#xff0c;我们就可以让一台Nginx服务器正常工作&#xff0c;并且提供基本的web服务器功能。 接下来我们将通过一个比较完整和最简单的基础配…

动态规划习题其四【力扣】【算法学习day.26】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

candence : 原理图如何导出原理库?

原理图如何导出原理库&#xff1f; 1、打开要需要导出原理图库的工程文件&#xff0c;新建一个原理图库&#xff1a; 2、copy 需要导出的原理图的库文件 3、粘贴到 刚刚新建的原理图库文件中即可 完成 可以一个一个复制&#xff0c;也可以多可一起复制。

二叉树的遍历

普通二叉树的遍历 前序遍历:根 左子树 右子树 中序遍历:左子树 根 右子树 后序遍历:左子树 右子树 根 一颗普通二叉树的实现 #include<stdlib.h> //树的定义 typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType data;struct BinaryTreeNode* left;s…

WebStorm 如何调试 Vue 项目

前言 在日常开发和各种教程中&#xff0c;最常见的 debug 方式就是在代码中插入 console.log 语句&#xff0c;然后在 Chrome 控制台中查看日志。显而易见&#xff0c;插入console.log 的效率不高&#xff0c;那是否有更高效的 debug 方式呢&#xff1f;断点调试允许开发者在代…

timedatectl status显示系统时间相关信息

timedatectl status命令用于显示当前系统的时间和日期相关信息。 下面是每行含义&#xff1a; Local time: 当前系统的本地时间Universal time: 当前系统的协调世界时&#xff08;UTC&#xff09;RTC time: 硬件时钟&#xff08;Real Time Clock&#xff09;的时间Time zone:…

【网页设计】HTML5 和 CSS3 提高

目标 能够说出 3~5 个 HTML5 新增布局和表单标签能够说出 CSS3 的新增特性有哪些 1. HTML5 的新特性 注&#xff1a;该部分所有内容可参考菜鸟教程菜鸟教程 - 学的不仅是技术&#xff0c;更是梦想&#xff01; (runoob.com) HTML5 的新增特性主要是针对于以前的不足&#xf…

09C++结构体

/*结构体属于用户自定义的数据类型&#xff0c; 允许用户存储不同的数据类型, 语法:struct 结构体名{结构体成员列表} ;*/ //struct 结构体名 变量名 #include <iostream> #include <string> using namespace std; struct student { string name; int age;int s…

软件测试之白盒测试(超详细总结)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 白盒测试 白盒测试&#xff08;White Box Testing&#xff09;又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试只测试软件产品的内部结…

【入门篇】数字统计——多语言版

题目跳转&#xff1a;数字统计 题目解析&#xff1a; 这道题目要求统计在给定范围 [L, R] 内所有整数中数字 2 出现的次数。例如&#xff0c;在范围 [2, 22] 中&#xff0c;数字 2 分别在数 2、12、20、21、22 中出现的次数&#xff0c;最终出现了6次。 题目的输入为两个正…

C++初阶——list

一、什么是list list是一个可以在序列的任意位置进行插入和删除的容器&#xff0c;并且可以进行双向迭代。list的底层是一个双向链表&#xff0c;双向链表可以将它们包含的每个元素存储在不同且不相关的存储位置。通过将每个元素与前一个元素的链接和后一个元素的链接关联起来&…