這些"類型提示"是一種新的語法(在 Python 3.6 版本加入)用來聲明一個(gè)變量的類型。
通過聲明變量的類型,編輯器和一些工具能給你提供更好的支持。
這只是一個(gè)關(guān)于 Python 類型提示的快速入門 / 復(fù)習(xí)。它僅涵蓋與 FastAPI 一起使用所需的最少部分...實(shí)際上只有很少一點(diǎn)。
整個(gè) FastAPI 都基于這些類型提示構(gòu)建,它們帶來了許多優(yōu)點(diǎn)和好處。
但即使你不會(huì)用到 FastAPI,了解一下類型提示也會(huì)讓你從中受益。
Note
如果你已經(jīng)精通 Python,并且了解關(guān)于類型提示的一切知識(shí),直接跳到下一章節(jié)吧。
讓我們從一個(gè)簡(jiǎn)單的例子開始:
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"))
運(yùn)行這段程序?qū)⑤敵觯?/p>
John Doe
這個(gè)函數(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"))
這是一個(gè)非常簡(jiǎn)單的程序。
現(xiàn)在假設(shè)你將從頭開始編寫這段程序。
在某一時(shí)刻,你開始定義函數(shù),并且準(zhǔn)備好了參數(shù)...。
現(xiàn)在你需要調(diào)用一個(gè)"將第一個(gè)字母轉(zhuǎn)換為大寫形式的方法"。
等等,那個(gè)方法是什么來著?upper?還是 uppercase?first_uppercase?capitalize?
然后你嘗試向程序員老手的朋友——編輯器自動(dòng)補(bǔ)全尋求幫助。
輸入函數(shù)的第一個(gè)參數(shù) first_name,輸入點(diǎn)號(hào)(.)然后敲下 Ctrl+Space 來觸發(fā)代碼補(bǔ)全。
但遺憾的是并沒有起什么作用:
讓我們來修改上面例子的一行代碼。
我們將把下面這段代碼中的函數(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"))
這和聲明默認(rèn)值是不同的,例如:
first_name="john", last_name="doe"
這兩者不一樣。
我們用的是冒號(hào)(:),不是等號(hào)(=)。
而且添加類型提示一般不會(huì)改變?cè)瓉淼倪\(yùn)行結(jié)果。
現(xiàn)在假設(shè)我們又一次正在創(chuàng)建這個(gè)函數(shù),這次添加了類型提示。
在同樣的地方,通過 Ctrl+Space 觸發(fā)自動(dòng)補(bǔ)全,你會(huì)發(fā)現(xiàn):
這樣,你可以滾動(dòng)查看選項(xiàng),直到你找到看起來眼熟的那個(gè):
下面是一個(gè)已經(jīng)有類型提示的函數(shù):
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + age
return name_with_age
因?yàn)榫庉嬈饕呀?jīng)知道了這些變量的類型,所以不僅能對(duì)代碼進(jìn)行補(bǔ)全,還能檢查其中的錯(cuò)誤:
現(xiàn)在你知道了必須先修復(fù)這個(gè)問題,通過 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
你剛剛看到的就是聲明類型提示的主要場(chǎng)景。用于函數(shù)的參數(shù)。
這也是你將在 FastAPI 中使用它們的主要場(chǎng)景。
不只是 str,你能夠聲明所有的標(biāo)準(zhǔn) Python 類型。
比如以下類型:
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ù)據(jù)結(jié)構(gòu)可以包含其他的值,比如 dict、list、set 和 tuple。它們內(nèi)部的值也會(huì)擁有自己的類型。
你可以使用 Python 的 typing 標(biāo)準(zhǔn)庫來聲明這些類型以及子類型。
它專門用來支持這些類型提示。
例如,讓我們來定義一個(gè)由 str 組成的 list 變量。
從 typing 模塊導(dǎo)入 List(注意是大寫的 L):
from typing import List
def process_items(items: List[str]):
for item in items:
print(item)
同樣以冒號(hào)(:)來聲明這個(gè)變量。
輸入 List 作為類型。
由于列表是帶有"子類型"的類型,所以我們把子類型放在方括號(hào)中:
from typing import List
def process_items(items: List[str]):
for item in items:
print(item)
這表示:"變量 items 是一個(gè) list,并且這個(gè)列表里的每一個(gè)元素都是 str"。
這樣,即使在處理列表中的元素時(shí),你的編輯器也可以提供支持。
沒有類型,幾乎是不可能實(shí)現(xiàn)下面這樣:
注意,變量 item 是列表 items 中的元素之一。
而且,編輯器仍然知道它是一個(gè) str,并為此提供了支持。
聲明 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
這表示:
定義 dict 時(shí),需要傳入兩個(gè)子類型,用逗號(hào)進(jìn)行分隔。
第一個(gè)子類型聲明 dict 的所有鍵。
第二個(gè)子類型聲明 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)
這表示:
你也可以將類聲明為變量的類型。
假設(shè)你有一個(gè)名為 Person 的類,擁有 name 屬性:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
接下來,你可以將一個(gè)變量聲明為 Person 類型:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
然后,你將再次獲得所有的編輯器支持:
Pydantic 是一個(gè)用來用來執(zhí)行數(shù)據(jù)校驗(yàn)的 Python 庫。
你可以將數(shù)據(jù)的"結(jié)構(gòu)"聲明為具有屬性的類。
每個(gè)屬性都擁有類型。
接著你用一些值來創(chuàng)建這個(gè)類的實(shí)例,這些值會(huì)被校驗(yàn),并被轉(zhuǎn)換為適當(dāng)?shù)念愋停ㄔ谛枰那闆r下),返回一個(gè)包含所有數(shù)據(jù)的對(duì)象。
然后,你將獲得這個(gè)對(duì)象的所有編輯器支持。
下面的例子來自 Pydantic 官方文檔:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
Info
想進(jìn)一步了解 Pydantic,請(qǐng)閱讀其文檔.
整個(gè) FastAPI 建立在 Pydantic 的基礎(chǔ)之上。
實(shí)際上你將在 教程 - 用戶指南 看到很多這種情況。
FastAPI 利用這些類型提示來做下面幾件事。
使用 FastAPI 時(shí)用類型提示聲明參數(shù)可以獲得:
...并且 FastAPI 還會(huì)用這些類型聲明來:
聽上去有點(diǎn)抽象。不過不用擔(dān)心。你將在 教程 - 用戶指南 中看到所有的實(shí)戰(zhàn)。
最重要的是,通過使用標(biāo)準(zhǔn)的 Python 類型,只需要在一個(gè)地方聲明(而不是添加更多的類、裝飾器等),F(xiàn)astAPI 會(huì)為你完成很多的工作。
Info
如果你已經(jīng)閱讀了所有教程,回過頭來想了解有關(guān)類型的更多信息,來自 mypy 的"速查表"是不錯(cuò)的資源。
更多建議: