Python中的類(lèi)型提示(Type Hints)總結(jié)
Python3.5 版本引入了類(lèi)型提示(Type Hints),它允許開(kāi)發(fā)者在代碼中顯式地聲明變量、函數(shù)、方法等的類(lèi)型信息。這種類(lèi)型聲明不會(huì)影響 Python 解釋器的運(yùn)行,但可以讓 IDE 和靜態(tài)分析工具更好地理解代碼,同時(shí)提高代碼的可讀性和可維護(hù)性。然而,由于 Python 支持動(dòng)態(tài)類(lèi)型,類(lèi)型提示并不能完全確保代碼的正確性。本文僅介紹 Python 類(lèi)型提示的初步使用。如果需要更詳細(xì)的使用說(shuō)明,請(qǐng)參考以下文章:typing、Python 類(lèi)型提示簡(jiǎn)介和Type Hints 入門(mén)教程。
類(lèi)型提示的語(yǔ)法格式為:
- 對(duì)于變量:{變量名}:{類(lèi)型名} =
- 對(duì)于函數(shù)參數(shù):{參數(shù)名}:{類(lèi)型名} =
- 對(duì)于函數(shù)返回值:->
1.類(lèi)型提升
類(lèi)型提示的引入主要有以下幾個(gè)方面的用途:
1.提高代碼可讀性
類(lèi)型提示可以幫助其他開(kāi)發(fā)人員更好地理解代碼,特別是在處理大型代碼庫(kù)時(shí)。通過(guò)清晰地指定變量、函數(shù)參數(shù)和返回值的數(shù)據(jù)類(lèi)型,開(kāi)發(fā)人員可以更快地理解代碼的含義和用途,從而更容易維護(hù)和修改代碼。
如下所示。我們有一個(gè)名為 add 的函數(shù),用于將兩個(gè)數(shù)字相加并返回結(jié)果。以下是該函數(shù)的原始代碼:
def add(a, b): return a + b
我們發(fā)現(xiàn),該函數(shù)沒(méi)有任何類(lèi)型提示,因此在調(diào)用該函數(shù)時(shí),我們必須自己去了解和檢查每個(gè)參數(shù)的類(lèi)型。這樣會(huì)導(dǎo)致代碼的可讀性和可維護(hù)性變差,特別是在代碼規(guī)模較大、涉及多個(gè)文件的情況下。為了改善這種情況,我們可以使用類(lèi)型提示來(lái)明確指定每個(gè)參數(shù)的類(lèi)型。以下是添加類(lèi)型提示后的 add 函數(shù)的代碼:
def add(a: int, b: int) -> int: return a + b
現(xiàn)在,我們可以清楚地看到函數(shù) add 的參數(shù)和返回值都是整數(shù)類(lèi)型。這使得代碼更易于理解,也提高了代碼的可靠性。
2.檢測(cè)類(lèi)型錯(cuò)誤
Python 是一種動(dòng)態(tài)語(yǔ)言,因此變量和函數(shù)參數(shù)的類(lèi)型可以在運(yùn)行時(shí)進(jìn)行更改。但是,這也意味著開(kāi)發(fā)人員容易在代碼中引入類(lèi)型錯(cuò)誤。通過(guò)使用類(lèi)型提示,開(kāi)發(fā)人員可以在編譯時(shí)檢測(cè)到這些類(lèi)型錯(cuò)誤,并更早地發(fā)現(xiàn)和修復(fù)它們,從而減少代碼錯(cuò)誤和調(diào)試時(shí)間。
mypy是一個(gè)用于檢查Python類(lèi)型的靜態(tài)類(lèi)型檢查器。它可以檢測(cè)類(lèi)型注釋中的錯(cuò)誤以及其他類(lèi)型的錯(cuò)誤。mypy使用說(shuō)明可以參考:mypy簡(jiǎn)易教程。mypy需要首先輸入以下命令安裝:
pip install mypy
然后,在代碼中標(biāo)注變量、函數(shù)參數(shù)和返回值的類(lèi)型。運(yùn)行以下命令:
mypy your_script.py
在上面的示例中,your_script.py是要檢查的Python腳本。運(yùn)行mypy工具后,它將檢查Python腳本中的類(lèi)型錯(cuò)誤,并輸出錯(cuò)誤信息。
3.提供自動(dòng)補(bǔ)全和文檔
許多集成開(kāi)發(fā)環(huán)境(IDE)和編輯器都可以使用類(lèi)型提示來(lái)提供自動(dòng)補(bǔ)全和代碼文檔。這可以幫助開(kāi)發(fā)人員更快地編寫(xiě)代碼,并提供關(guān)于函數(shù)參數(shù)和返回值的信息,以便更好地理解代碼。要使用Python類(lèi)型提示提供自動(dòng)補(bǔ)全和文檔,需要使用一個(gè)支持該功能的Python編輯器。比如一些流行的Python編輯器包括vscode、PyCharm和Sublime Text等。
以vscode為例,考慮一個(gè)整數(shù)相加函數(shù),將結(jié)果保存在變量c中。如果加上類(lèi)型提示,vscode插件將推斷變量c的類(lèi)型為 int,并提供代碼補(bǔ)全和代碼提示等功能。
此外,還可以使用vscode的autoDocstring生成帶有類(lèi)型提示的文檔和注釋。
autoDocstring注釋代碼使用方法如下所示:
按照以上方法,對(duì)于有無(wú)類(lèi)型提示的注釋結(jié)果如下:
def add(a, b): """_summary_ Args: a (_type_): _description_ b (_type_): _description_ Returns: _type_: _description_ """ c = a + b return c def add(a: int, b: int) -> int: """_summary_ Args: a (int): _description_ b (int): _description_ Returns: int: _description_ """ c = a + b return c
2.類(lèi)型聲明
2.1基本類(lèi)型
對(duì)于Python的內(nèi)置基本類(lèi)型 int、float、str 和 byte等,可以直接使用類(lèi)型本身進(jìn)行類(lèi)型提示。如下所示:
# 直接定義 age: int = 1 # 聲明后定義 num: float num = 2.0 def greet(name: str) -> str: return f"Hello, {name}!" def is_even(x: int) -> bool: return x % 2 == 0 def encode_data(data: str) -> bytes: return data.encode('utf-8')
2.2嵌套類(lèi)型
對(duì)于容器數(shù)據(jù)結(jié)構(gòu),例如 list、tuple、dict 等,也可以直接使用類(lèi)型本身進(jìn)行類(lèi)型提示。如下所示:
items: list = [1, 4.0, "3"] info: dict = {"name":"john", "age":24}
在Python的容器數(shù)據(jù)結(jié)構(gòu)中,每個(gè)元素都具有其自己的類(lèi)型。雖然這種方法提供了靈活性,但是內(nèi)部元素的類(lèi)型無(wú)法受到限制,因此內(nèi)部元素可以是任何類(lèi)型(Any)??梢酝ㄟ^(guò)Python的typing標(biāo)準(zhǔn)庫(kù)來(lái)聲明這些類(lèi)型及其元素類(lèi)型。
from typing import List, Tuple, Dict, Set # 指定my_list變量是一個(gè)整數(shù)列表 my_list: List[int] = [1, 2, 3, 4] # 指定my_tuple變量應(yīng)該是一個(gè)按順序包含整數(shù)、字符串和布爾值的元組 my_tuple: Tuple[int, str, bool] = (1, "hello", True) # 指定了my_dict變量是一個(gè)所有鍵為str類(lèi)型,所有值為int類(lèi)型的字典 my_dict: Dict[str, int] = {"apple": 1, "banana": 2, "orange": 3} # 指定了my_set變量應(yīng)該是一個(gè)浮點(diǎn)數(shù)集合 my_set: Set[float] = {1.0, 2.0, 3.0}
2.3自定義類(lèi)型
Python也支持對(duì)自定義類(lèi)進(jìn)行類(lèi)型提示。下面是一個(gè)自定義類(lèi)的類(lèi)型提示示例:
class Person: def __init__(self, name: str, age: int): self.name = name self.age = age def say_hello(person: Person) -> str: return f"Hello, {person.name}!"
在上面的代碼中,我們定義了一個(gè) Person 類(lèi),它有兩個(gè)屬性:name 和 age。在初始函數(shù)中,我們使用類(lèi)型提示指定了這兩個(gè)屬性的類(lèi)型。接下來(lái),我們定義了一個(gè) say_hello 函數(shù),這個(gè)函數(shù)的參數(shù)是一個(gè) Person 類(lèi)型的對(duì)象,并且返回值是一個(gè)字符串。
對(duì)于numpy和pandas這種第三方庫(kù),也可以通過(guò)同樣的方法進(jìn)行類(lèi)型提示:
import numpy as np import pandas as pd import cv2 # numpy def add_arrays(a: np.ndarray, b: np.ndarray) -> np.ndarray: return np.add(a, b) # pandas def filter_dataframe(df: pd.DataFrame, column: str, value: float) -> pd.DataFrame: return df[df[column] > value] # opencv,opencv圖像本身就是一個(gè)numpy數(shù)組結(jié)構(gòu) def resize_image(img: np.ndarray, height: int, width: int) -> np.ndarray: return cv2.resize(img, (width, height))
2.4復(fù)合類(lèi)型
2.4.1 Union和Optional
Python的typing庫(kù)也提供了Union類(lèi)型用于表示多種類(lèi)型中的一種,Optional類(lèi)型用于表示可選類(lèi)型。它們可以結(jié)合使用,以便更好地表示變量的類(lèi)型。
例如,如果一個(gè)變量可以是整數(shù)或字符串類(lèi)型,那么可以這樣定義它的類(lèi)型:
from typing import Union def func(x: Union[int, str]) -> None: pass
上面的代碼中,x的類(lèi)型為Union[int, str],表示x可以是整數(shù)或字符串類(lèi)型。
如果一個(gè)變量可以是整數(shù)類(lèi)型或None類(lèi)型,那么可以這樣定義它的類(lèi)型:
from typing import Optional def func(x: Optional[int] = None) -> None: pass
Union和Optional類(lèi)型可以結(jié)合使用。例如,如果一個(gè)變量可以是整數(shù)類(lèi)型、字符串類(lèi)型或None類(lèi)型,那么可以這樣定義它的類(lèi)型:
from typing import Optional, Union def func(x: Optional[Union[int, str]]) -> None: pass
上面的代碼中,x的類(lèi)型為Optional[Union[int, str]],表示x可以是整數(shù)類(lèi)型、字符串類(lèi)型或None類(lèi)型。
此外,在Python中,Union[X, Y] 表示變量的類(lèi)型可以是 X 或 Y。因此,Optional[X] 實(shí)際上是 Union[X, None] 的簡(jiǎn)寫(xiě)形式。這種語(yǔ)法的好處是它可以使代碼更簡(jiǎn)潔,因?yàn)槲覀冎恍枰獙?xiě)一個(gè)類(lèi)型而不是兩個(gè)。
from typing import Optional, Union def greet(name: Optional[str]) -> str: if name is None: return "Hello, stranger!" else: return f"Hello, {name}!" def greet2(name: Union[str, None]) -> str: if name is None: return "Hello, stranger!" else: return f"Hello, {name}!"
在上面代碼中,greet和greets函數(shù)是等價(jià)的。在第一個(gè)函數(shù)中,我們使用了 Optional[str] 來(lái)表示 name 可以是一個(gè)字符串或者是 None。在第二個(gè)函數(shù)中,我們使用了 Union[str, None] 來(lái)達(dá)到相同的效果。
2.4.2 Generator和Iterator
在Python中,Generator和Iterator是非常常見(jiàn)的數(shù)據(jù)類(lèi)型。Generator是一種函數(shù),可以通過(guò)yield語(yǔ)句生成一個(gè)迭代器,而Iterator是一種對(duì)象,可以用于迭代元素序列。為了提高代碼的可讀性和可維護(hù)性,我們可以使用類(lèi)型提示來(lái)指定Generator和Iterator的類(lèi)型。
Generator類(lèi)型提示使用Generator[ReturnType, SendType, ReturnType]語(yǔ)法,其中ReturnType指定返回值類(lèi)型,SendType指定發(fā)送值類(lèi)型,ReturnType指定生成器的類(lèi)型。例如,下面是一個(gè)簡(jiǎn)單的Generator類(lèi)型提示示例:
from typing import Generator def even_numbers(n: int) -> Generator[int, None, None]: for i in range(n): if i % 2 == 0: yield i
上面的代碼中,even_numbers是一個(gè)Generator函數(shù),返回類(lèi)型是Generator[int, None, None],該函數(shù)生成一個(gè)整數(shù)序列,其中每個(gè)偶數(shù)都是通過(guò)yield語(yǔ)句生成的。
Iterator類(lèi)型提示使用Iterator[ElementType]語(yǔ)法,其中ElementType指定迭代器元素類(lèi)型。例如,下面是一個(gè)簡(jiǎn)單的Iterator類(lèi)型提示示例:
from typing import Iterator class MyIterator: def __init__(self): self.current: int = 0 self.max: int = 5 def __iter__(self) -> Iterator[int]: return self def __next__(self) -> int: if self.current >= self.max: raise StopIteration else: self.current += 1 return self.current
在上面的代碼中,我們對(duì)MyIterator類(lèi)進(jìn)行了注釋。使用了typing模塊中的Iterator類(lèi)來(lái)注釋__iter__()方法的返回值類(lèi)型。同時(shí),我們對(duì)current和max屬性也進(jìn)行了注釋?zhuān)付怂鼈兊念?lèi)型為int。在__next__()方法中,我們指定了返回值類(lèi)型為int。
2.4.3 Callable
Callable類(lèi)型提示用于表示一個(gè)可調(diào)用對(duì)象,例如函數(shù)、類(lèi)或?qū)ο蟮取男问缴蟻?lái)看,Callable類(lèi)型提示接受兩個(gè)或三個(gè)類(lèi)型提示參數(shù):第一個(gè)參數(shù)表示函數(shù)的參數(shù)類(lèi)型,第二個(gè)參數(shù)表示函數(shù)的返回類(lèi)型。下面是一個(gè)Callable類(lèi)型提示的例子:
from typing import Callable def apply(func: Callable[[int, int], int], a: int, b: int) -> int: return func(a, b) def add(a: int, b: int) -> int: return a + b result = apply(add, 3, 4) print(result) # 輸出7
在上面的例子中,apply函數(shù)接受一個(gè)名為func的參數(shù),該參數(shù)是一個(gè)Callable類(lèi)型,它指定了函數(shù)的兩個(gè)整數(shù)參數(shù)和一個(gè)整數(shù)返回值。add函數(shù)滿(mǎn)足這個(gè)條件,因此可以傳遞給apply函數(shù),它會(huì)返回add(3, 4)的結(jié)果7。
2.4.4 Any和NoReturn
Any類(lèi)型表示一個(gè)任意類(lèi)型,它可以用于函數(shù)參數(shù)、函數(shù)返回值和變量等。使用Any類(lèi)型時(shí),我們可以省略類(lèi)型注釋?zhuān)棺兞款?lèi)型更加靈活。下面是一個(gè)使用Any類(lèi)型的例子:
from typing import Any def print_value(value: Any) -> None: print(value) print_value("Hello World") # 輸出 "Hello World" print_value(123) # 輸出 123
在上面的例子中,我們定義了一個(gè)print_value函數(shù),它接受一個(gè)任意類(lèi)型的參數(shù)value,并將其打印出來(lái)。我們可以看到,我們可以將任何類(lèi)型的值傳遞給print_value函數(shù),包括字符串和整數(shù)。這使得我們的代碼更加靈活。
NoReturn類(lèi)型表示函數(shù)不會(huì)返回任何值。這個(gè)類(lèi)型通常用于標(biāo)識(shí)那些沒(méi)有返回值的函數(shù)。下面是一個(gè)使用NoReturn類(lèi)型的例子:
from typing import NoReturn def print_message(message: str) -> NoReturn: print(message) raise Exception("Error occurred") print_message("Hello World") # 輸出 "Hello World",然后拋出異常
在上面的例子中,我們定義了一個(gè)print_message函數(shù),它接受一個(gè)字符串類(lèi)型的參數(shù)message,并將其打印出來(lái)。然后,我們手動(dòng)拋出了一個(gè)異常,這意味著函數(shù)不會(huì)返回任何值。我們可以使用NoReturn類(lèi)型來(lái)明確地表示這一點(diǎn)。
2.4.5 其他
Python還支持更高級(jí)的類(lèi)型提示。例如,可以使用Sequence來(lái)指定一個(gè)列表,使用TypedDict來(lái)指定一個(gè)帶有特定鍵和值類(lèi)型的字典。此外,Python還支持Literal類(lèi)型提示,可以限制變量只能取特定的常量值。最近,Python3.8版本還增加了Protocol類(lèi)型提示,允許指定類(lèi)需要實(shí)現(xiàn)哪些方法和屬性。這些類(lèi)型提示用的不多,但是如果需要更精細(xì)的類(lèi)型控制,可以參考官方文檔:typing。
2.5類(lèi)型提示的別名
在類(lèi)型提示中使用了過(guò)于復(fù)雜的類(lèi)型,可以考慮將其定義為一個(gè)類(lèi)型別名,然后在函數(shù)參數(shù)、返回值等處使用該類(lèi)型別名。例如,如果你需要傳遞一個(gè)包含多個(gè)字段的字典作為函數(shù)參數(shù),你可以使用Dict[str, Union[int, str, List[int]]]來(lái)表示該字典的類(lèi)型。但是,這個(gè)類(lèi)型過(guò)于復(fù)雜,不易于理解。你可以將其定義為一個(gè)類(lèi)型別名,如下所示:
from typing import Dict, Union, List MyDict = Dict[str, Union[int, str, List[int]]] def my_function(my_dict: MyDict) -> int: # Function body return 1
這樣,你就可以在函數(shù)參數(shù)、返回值等處使用MyDict這個(gè)類(lèi)型別名,使代碼更加易讀、易懂。
到此這篇關(guān)于Python中的類(lèi)型提示(Type Hints)總結(jié)的文章就介紹到這了,更多相關(guān)Python類(lèi)型提示內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
幾個(gè)提升Python運(yùn)行效率的方法之間的對(duì)比
這篇文章主要介紹了幾個(gè)提升Python運(yùn)行效率的方法之間的對(duì)比,包括使用Cython和PyPy等這些熱門(mén)方法,需要的朋友可以參考下2015-04-04Java爬蟲(chóng)技術(shù)框架之Heritrix框架詳解
這篇文章主要介紹了爬蟲(chóng)技術(shù)框架之Heritrix框架詳解,文中通過(guò)示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07PyCharm鼠標(biāo)右鍵不顯示Run unittest的解決方法
今天小編就為大家分享一篇PyCharm鼠標(biāo)右鍵不顯示Run unittest的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11Python實(shí)戰(zhàn)快速上手BeautifulSoup庫(kù)爬取專(zhuān)欄標(biāo)題和地址
BeautifulSoup是爬蟲(chóng)必學(xué)的技能,BeautifulSoup最主要的功能是從網(wǎng)頁(yè)抓取數(shù)據(jù),Beautiful Soup自動(dòng)將輸入文檔轉(zhuǎn)換為Unicode編碼,輸出文檔轉(zhuǎn)換為utf-8編碼2021-10-10Python?itertools中accumulate函數(shù)用法及使用運(yùn)用詳細(xì)講解
這篇文章主要介紹了Python的itertools庫(kù)中的accumulate函數(shù),該函數(shù)可以計(jì)算累積和或通過(guò)指定函數(shù)進(jìn)行累積運(yùn)算,文中通過(guò)代碼將用法介紹的非常詳細(xì),需要的朋友可以參考下2025-02-02win10下tensorflow和matplotlib安裝教程
這篇文章主要為大家詳細(xì)介紹了win10下tensorflow和matplotlib安裝教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)讓字典保持有序的方法
這篇文章主要介紹了Python讓字典保持有序的方法,涉及Python基于collections模塊中的OrderedDict類(lèi)實(shí)現(xiàn)控制字典順序的相關(guān)操作技巧,需要的朋友可以參考下2018-02-02Python實(shí)用技巧之列表、字典、集合中根據(jù)條件篩選數(shù)據(jù)詳解
這篇文章主要給大家介紹了關(guān)于Python技巧之在列表、字典、集合中根據(jù)條件篩選數(shù)據(jù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧2018-07-07