呆鳥云:發(fā)布本系列旨在推廣 FastAPI 以及推進 FastAPI 中文官檔翻譯,目前,F(xiàn)astAPI 官檔已完成 98% 的中文翻譯,如果您對 FastAPI 有興趣,可以為這個很贊的開源項目做些貢獻装畅,比如校譯、翻譯沧烈、審閱等掠兄。
開源項目的發(fā)展離不開大家的支持。當(dāng)然最簡單的就是在 Github 上點 Star 了锌雀。
如果您覺得 FastAPI 不錯蚂夕,也可以轉(zhuǎn)發(fā)、轉(zhuǎn)載本文腋逆,讓更多人知道 Python 還有這么簡單的后端支持庫婿牍。
FastAPI 官檔地址:https://fastapi.tiangolo.com/zh/
下面先列出幾個需要 Review 的 PR,希望大家多多參與惩歉。
- https://github.com/tiangolo/fastapi/pull/3826
- https://github.com/tiangolo/fastapi/pull/3827
- https://github.com/tiangolo/fastapi/pull/3828
- https://github.com/tiangolo/fastapi/pull/3829
- https://github.com/tiangolo/fastapi/pull/3830
- https://github.com/tiangolo/fastapi/pull/3832
- https://github.com/tiangolo/fastapi/pull/3793
- https://github.com/tiangolo/fastapi/pull/3795
- https://github.com/tiangolo/fastapi/pull/3796
以下為正文等脂。
Python 的 類型提示是聲明變量類型的語法。
聲明了變量類型撑蚌,編輯器和開發(fā)工具就能提供更好的支持上遥。
本章只是 Python 類型提示的快速入門,僅介紹了 FastAPI 中與類型提示相關(guān)的內(nèi)容……真的很少争涌。
FastAPI 是基于類型提示開發(fā)的粉楚,寫代碼的體驗非常不錯。
就算不使用 FastAPI亮垫,了解一下類型提示也會讓您獲益匪淺模软。
!!! note "筆記"
如果您是 Python 專家,已經(jīng)熟知類型提示饮潦,就直接跳到下一章吧燃异。
動機
先介紹一個簡單的例子:
def get_full_name(first_name, last_name):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
這段代碼輸出如下內(nèi)容:
John Doe
該函數(shù)執(zhí)行以下操作:
- 接收
first_name
和last_name
參數(shù) - 使用
title()
把參數(shù)的首字母轉(zhuǎn)換為大寫 - 使用空格<abbr title="按順序把多個內(nèi)容組合成一個整體。">拼接</abbr>兩個參數(shù)的值
def get_full_name(first_name, last_name):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
編輯示例
這是個非常簡單的程序害晦。
現(xiàn)在特铝,假設(shè)您要從頭編寫這段程序暑中。
在某一時刻壹瘟,開始定義函數(shù),并且準備好了參數(shù)……
此時鳄逾,需要調(diào)用把首字母轉(zhuǎn)換為大寫的方法稻轨。
等等,那個方法是什么來著雕凹?upper
殴俱? uppercase
政冻?first_uppercase
?還是capitalize
线欲?
然后明场,您嘗試向程序員老手的朋友——編輯器自動補全尋求幫助。
輸入函數(shù)的第一個參數(shù) first_name
李丰,輸入點號(.
)苦锨,然后敲下 Ctrl+Space
觸發(fā)代碼補全。
可惜趴泌,這沒有什么用:
添加類型
接下來舟舒,修改上例中的一行代碼。
把下面這行代碼中的函數(shù)參數(shù)從:
first_name, last_name
改成:
first_name: str, last_name: str
就是這樣嗜憔。
這就是類型提示:
def get_full_name(first_name: str, last_name: str): # 看這行
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
與聲明默認值不同秃励,例如:
first_name="john", last_name="doe"
這兩者不一樣。
類型提示用的是冒號(:
)吉捶,不是等號(=
)夺鲜。
而且類型提示一般不會改變原有的運行結(jié)果。
再次創(chuàng)建這個函數(shù)帚稠,這次添加了類型提示谣旁。
在同一個位置,使用 Ctrl+Space
觸發(fā)自動補全滋早,就會發(fā)現(xiàn):
這樣榄审,就可以滾動查看選項,找到需要的功能:
更多動機
下面是個使用類型提示的函數(shù):
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + age
return name_with_age
因為編輯器已經(jīng)知道了變量的類型杆麸,所以不僅能對代碼進行補全搁进,還能檢查代碼錯誤:
現(xiàn)在,必須先修復(fù)這個問題昔头,使用 str(age)
把 age
轉(zhuǎn)換成字符串:
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + str(age) # 看這行
return name_with_age
聲明類型
您剛剛看到的就是類型提示常見的場景 ~ 用于函數(shù)的參數(shù)饼问。
這也是在 FastAPI 中類型提示的常用場景。
簡單類型
類型提示不只使用 str
揭斧,還能聲明所有 Python 標準類型莱革。
比如,以下類型:
int
float
bool
bytes
def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
return item_a, item_b, item_c, item_d, item_d, item_e
通用類型的類型參數(shù)
dict
讹开、list
盅视、set
、tuple
等數(shù)據(jù)結(jié)構(gòu)可以包含其它值旦万,而且其內(nèi)部的值也有自己的類型闹击。
Python 的 typing
標準庫可以聲明這些類型及其子類型。
這個標準庫專門用來支持類型提示成艘。
列表
例如赏半,定義由 str
組成的 list
變量贺归。
從 typing
模塊導(dǎo)入 List
(注意 L
要大寫):
from typing import List
def process_items(items: List[str]):
for item in items:
print(item)
同樣用冒號(:
)聲明變量。
類型是 List
断箫。
由于列表是包含子類型的類型拂酣,所以要把子類型放在方括號里:
from typing import List
def process_items(items: List[str]): # 看這行
for item in items:
print(item)
!!! tip "提示"
方括號里的內(nèi)部類型叫做**類型參數(shù)**。
此時仲义,`str` 是傳遞給 `List` 的類型參數(shù)踱葛。
即:變量 items
的類型是 list
,并且列表里的每個元素的類型都是 str
光坝。
這樣尸诽,即使在處理列表里的元素時,編輯器也能提供支持:
沒有類型盯另,這種支持幾乎不可能實現(xiàn)性含。
注意,變量 item
是列表 items
里的元素鸳惯。
而且商蕴,編輯器仍然把它識別為 str
,并提供相關(guān)支持芝发。
元組和集合
聲明 tuple
和 set
的方法也一樣:
from typing import Set, Tuple # 看這行
def process_items(items_t: Tuple[int, int, str], items_s: Set[bytes]): # 看這行
return items_t, items_s
即:
- 變量
items_t
是包含 3 個元素的tuple
绪商,分別是int
、int
辅鲸、str
- 變量
items_s
是set
格郁,其中每個元素的類型都是bytes
字典
定義 dict
要傳入 2 個用逗號分隔的子類型。
第一個子類型聲明 dict
的所有鍵独悴。
第二個子類型聲明 dict
的所有值:
from typing import Dict
def process_items(prices: Dict[str, float]): # 看這行
for item_name, item_price in prices.items():
print(item_name)
print(item_price)
即:
- 變量
prices
是dict
:-
dict
的鍵的類型是str
(元素名稱) -
dict
的值的類型是float
(元素價格)
-
Optional
使用 Optional
把變量聲明為 str
等類型例书,但該類型是可選的,因此也可以是 None
:
from typing import Optional
def say_hi(name: Optional[str] = None): # 看這行
if name is not None:
print(f"Hey {name}!")
else:
print("Hello World")
使用 Optional[str]
替代簡單的 str
可以讓編輯器檢測值的類型應(yīng)為 str
刻炒,但也可能為 None
的錯誤决采。
通用類型
以下類型使用方括號中的類型參數(shù):
List
Tuple
Set
Dict
Optional
- 等……
這些類型就是通用類型,也叫作 Generics坟奥。
類作為類型
類也可以聲明為變量的類型树瞭。
假設(shè)有一個包含 name
屬性的類 Person
:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
下面,把變量的類型聲明為 Person
:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person): # 看這行
return one_person.name
再一次爱谁,獲得了所有的編輯器支持:
Pydantic 模型
Pydantic 是執(zhí)行數(shù)據(jù)校驗的 Python 庫晒喷,可以把數(shù)據(jù)結(jié)構(gòu)聲明為包含屬性的類。
每個屬性都有自己的類型管行。
接下來厨埋,用一些值創(chuàng)建類實例邪媳,F(xiàn)astAPI 會校驗這些值捐顷,(在需要的情況下)把值轉(zhuǎn)換為適當(dāng)?shù)念愋偷聪荩⒎祷匕袛?shù)據(jù)的對象。
然后迅涮,這個對象就可以獲得編輯器支持废赞。
下面是 Pydantic 官方文檔中的示例:
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel
class User(BaseModel):
id: int
name = "John Doe"
signup_ts: Optional[datetime] = None
friends: List[int] = []
external_data = {
"id": "123",
"signup_ts": "2017-06-01 12:22",
"friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123
!!! info "說明"
FastAPI 就是基于 Pydantic 開發(fā)的。
用戶指南中列出了很多示例叮姑。
FastAPI 中的類型提示
FastAPI 充分利用了類型提示的優(yōu)勢唉地。
FastAPI 使用類型提示聲明參數(shù)可以獲得:
- 編輯器支持
- 類型檢查
……FastAPI 還使用類型聲明:
- 定義參數(shù)需求:聲明對請求路徑參數(shù)、查詢參數(shù)传透、請求頭耘沼、請求體、依賴項等的需求
- 轉(zhuǎn)換數(shù)據(jù):把請求中的數(shù)據(jù)轉(zhuǎn)換為需要的類型
-
校驗數(shù)據(jù): 對于每一個請求:
- 數(shù)據(jù)校驗失敗時朱盐,自動生成錯誤信息群嗤,并返回給客戶端
- 使用 OpenAPI 存檔 API:
- 并在 API 文檔中顯示
聽上去有點抽象,不過不用擔(dān)心兵琳。用戶指南中詳細介紹了上述所有內(nèi)容狂秘。
最重要的是,使用 Python 標準類型躯肌,只要在一個地方聲明(不用添加更多的類者春、裝飾器等),FastAPI 就能完成很多工作清女。