python中的顯式聲明類(lèi)型參數(shù)使用方式
背景
筆者在用fastapi編寫(xiě)ai rest service的時(shí)候發(fā)現(xiàn)官方的sample code函數(shù)參數(shù)都帶上了類(lèi)型參數(shù). 以往筆者做python開(kāi)發(fā)都不習(xí)慣帶類(lèi)型參數(shù),認(rèn)為它是一門(mén)弱類(lèi)型語(yǔ)言,不強(qiáng)制帶類(lèi)型參數(shù)本質(zhì)上是為了開(kāi)發(fā)效率.fastapi的官方文檔卻強(qiáng)調(diào)函數(shù)定義是要顯式帶參數(shù)類(lèi)型,于是筆者就詳細(xì)研究了python顯式聲明參數(shù)類(lèi)型的語(yǔ)法以及其帶來(lái)的好處.
python函數(shù)顯式聲明的類(lèi)型匯總
顯示類(lèi)型語(yǔ)法要分版本,筆者這里選擇3.10+版本,是現(xiàn)在主流的版本.
基本類(lèi)型
str,int,float等python基本類(lèi)型,最常見(jiàn)的顯式參數(shù)類(lèi)型
def test1(a: int, b: str, c: float):
print("a is: " + str(a) + " b is: " + str(b) + " c is: " + str(c))
集合類(lèi)型
list,dict,set,tuple. 集合類(lèi)型都有內(nèi)部參數(shù)類(lèi)型,這個(gè)等價(jià)于我們熟悉的java語(yǔ)言里面的泛型
def test2(a: list[str], b: set[float], c: dict[str, int], d: tuple[str, str]):
print(f"a is: {a} ")
print(f"b is ")
print(f"c is {c}")
print(f"d is wppm3vysvbp")
if __name__ == '__main__':
test2([1,2], {3,4}, {'a':1,'b':2}, ('a','b'))
這個(gè)也比較簡(jiǎn)單,即便平時(shí)編碼不習(xí)慣顯示添加類(lèi)型參數(shù),此類(lèi)聲明語(yǔ)法也很直觀.
Optional and Union(python3.10版本之前)
Optional和Union需要詳細(xì)講解一下,這兩個(gè)類(lèi)型在python 3,10版本之前使用比較多. 首先是union 表示當(dāng)前入?yún)⒖梢允?code>Union后面方括號(hào)指定的多類(lèi)型中的一種,表示此參數(shù)可以支持多種類(lèi)型,比如下例子:
from typing import Union
def test_union(a: Union[str, int]):
if isinstance(a, str):
print(f'a is str {a}')
elif isinstance(a, int):
print(f'a is int {str(a)}')
if __name__ == '__main__':
test_union('abc')
test_union(1)
輸出:
a is str abc a is int 1
表示參數(shù)a可以是str類(lèi)型或者int類(lèi)型
另一種情況,當(dāng)union只有兩個(gè)類(lèi)型,且其中一個(gè)類(lèi)型為None
def test_union2(a: Union[str, None]):
if a is None:
print("a is none")
else:
print(a.upper())
if __name__ == '__main__':
test_union2(a = None)
這種情況表明入?yún) 要么是str類(lèi)型,要么可以為None,而且這種特殊情況下Union[str, None]就可以被Optional[str]替代.
from typing import Optional def test_optional(a: Optional[str]): print(a) if __name__ == '__main__': test_optional(a=None)
我們可以看作Optional是Union的一個(gè)特例.在3.10+版本后其實(shí)都可以不用從typing包引入Optional和Union兩種類(lèi)型,在3.10+版本用一個(gè)|操作符就可以代替Union,比如下面這個(gè)例子:
def test_310(a: str|None): print(a) print(type(a)) if __name__ == '__main__': test_310(a='10') test_310(a=None) test_310(20)
可見(jiàn)在vscode里面這里即便聲明了類(lèi)型參數(shù)可能是str,但是int類(lèi)型也可以傳遞進(jìn)來(lái).
來(lái)看下面一個(gè)有意思的case.
這里定義一個(gè)可以為None類(lèi)型的參數(shù),調(diào)用的時(shí)候不賦值
def test_default(a: str|None): print(a) if __name__ == '__main__': test_default()
結(jié)果運(yùn)行報(bào)錯(cuò)
test_default() missing 1 required positional argument: 'a'
注意語(yǔ)法a: str|None 以及 a: Optional[str] 或者 Union[str,None] 只是代表參數(shù)可以為None但是并不代表參數(shù)有默認(rèn)值
所以此類(lèi)語(yǔ)法只是表示當(dāng)前參數(shù)類(lèi)型可以是None,但并不表示存在None的默認(rèn)值.如果需要調(diào)用函數(shù)時(shí)不傳遞參數(shù),那么無(wú)論采用什么語(yǔ)法,在函數(shù)定義的時(shí)候還是需要給定默認(rèn)值None.
自定義類(lèi)類(lèi)型
類(lèi)型參數(shù)還可以是自定義類(lèi),或者自定義類(lèi)的集合類(lèi)型
class A:
def __init__(self, val):
self.val = val
def test(self):
print(self.val)
def test_a(a: A):
a.test()
if __name__ == '__main__':
a = A('123')
test_a(a)
自定義類(lèi)型作為集合中元素類(lèi)型
def test_a_list(a: list[A]):
for item in a:
item.test()
if __name__ == '__main__':
a = [A('123'), A('234')]
test_a_list(a)
顯示聲明類(lèi)型的好處
python是弱類(lèi)型語(yǔ)言,本質(zhì)上是不需要去定義其變量類(lèi)型或者參數(shù)的類(lèi)型的.但是有些框架的源碼里面都有類(lèi)型參數(shù)的聲明,不禁讓人思考這樣做帶來(lái)了什么好處.
看如下的例子:
無(wú)顯式聲明vscode沒(méi)有方法提示:

有顯式聲明vscode存在方法提示:

在vscode里面如果顯式聲明參數(shù)類(lèi)型,當(dāng)?shù)粲么藚?shù)則可以提示此類(lèi)型具備的方法,如果沒(méi)有顯式聲明參數(shù)類(lèi)型則不會(huì)提示此類(lèi)型具備的方法.
其次,顯示聲明參數(shù)類(lèi)型是一種更規(guī)范的做法,它可以避免一些潛在的因?yàn)轭?lèi)型沒(méi)顯式聲明而帶來(lái)的編碼問(wèn)題,這也能理解為什么fastapi的官方doc會(huì)提及到python的類(lèi)型,且在官方的sample code里面都有顯示聲明參數(shù)類(lèi)型.所以將此作為一個(gè)最佳實(shí)踐也不為過(guò).
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用PyQt5+Pandas打造一個(gè)表格(Excel/CSV)讀取與處理工具
在日常辦公和數(shù)據(jù)分析中,我們經(jīng)常需要處理各種?Excel?和?CSV?文件,為了提高工作效率,今天我們將手把手教大家使用?PyQt5?和?Pandas?開(kāi)發(fā)一款圖形化的表格讀取與處理工具,需要的朋友可以參考下2026-03-03
Python函數(shù)中的函數(shù)(閉包)用法實(shí)例
這篇文章主要介紹了Python函數(shù)中的函數(shù)(閉包)用法,結(jié)合實(shí)例形式分析了Python閉包的定義與使用技巧,需要的朋友可以參考下2016-03-03
PyQt6/PySide6中QTableView類(lèi)的實(shí)現(xiàn)
本文主要介紹了PyQt6/PySide6中QTableView類(lèi)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
基于python實(shí)現(xiàn)刪除指定文件類(lèi)型
這篇文章主要介紹了基于python實(shí)現(xiàn)刪除指定文件類(lèi)型,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
Python實(shí)現(xiàn)獲取命令行輸出結(jié)果的方法
這篇文章主要介紹了Python實(shí)現(xiàn)獲取命令行輸出結(jié)果的方法,涉及Python命令執(zhí)行及文件讀寫(xiě)等相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
Python正則表達(dá)式急速入門(mén)(小結(jié))
這篇文章主要介紹了Python正則表達(dá)式急速入門(mén)(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12

