FastAPI官檔精編003 - Python類型提示

呆鳥云:發(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,希望大家多多參與惩歉。

以下為正文等脂。


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_namelast_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盅视、settuple 等數(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)支持芝发。

元組和集合

聲明 tupleset 的方法也一樣:

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绪商,分別是 intint辅鲸、str
  • 變量 items_sset格郁,其中每個元素的類型都是 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)

即:

  • 變量 pricesdict
    • 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 就能完成很多工作清女。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钱烟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嫡丙,更是在濱河造成了極大的恐慌忠售,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件迄沫,死亡現(xiàn)場離奇詭異稻扬,居然都是意外死亡,警方通過查閱死者的電腦和手機羊瘩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門泰佳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人尘吗,你說我怎么就攤上這事逝她。” “怎么了睬捶?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵黔宛,是天一觀的道長。 經(jīng)常有香客問我擒贸,道長臀晃,這世上最難降的妖魔是什么觉渴? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮徽惋,結(jié)果婚禮上案淋,老公的妹妹穿的比我還像新娘。我一直安慰自己险绘,他們只是感情好踢京,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宦棺,像睡著了一般瓣距。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上代咸,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天旨涝,我揣著相機與錄音,去河邊找鬼侣背。 笑死白华,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贩耐。 我是一名探鬼主播弧腥,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼潮太!你這毒婦竟也來了管搪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤铡买,失蹤者是張志新(化名)和其女友劉穎更鲁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奇钞,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡澡为,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了景埃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媒至。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谷徙,靈堂內(nèi)的尸體忽然破棺而出拒啰,到底是詐尸還是另有隱情,我是刑警寧澤完慧,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布谋旦,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏册着。R本人自食惡果不足惜拴孤,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望指蚜。 院中可真熱鬧,春花似錦涨椒、人聲如沸摊鸡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽免猾。三九已至,卻和暖如春囤热,著一層夾襖步出監(jiān)牢的瞬間猎提,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工旁蔼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锨苏,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓棺聊,卻偏偏與公主長得像伞租,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子限佩,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容