Python 類型注解


前言

類型注解讓 Python 代碼開起來丑不可言,但隨着用它的人越來越多,有時候會不可避免看到或是寫出來這樣的代碼:

def get_age(name: str) -> int:
    ...

雖然直觀上理解起來很方便,但是也有很多比較復雜的,不熟悉的人看起來可能不是很理解。比如:

class Thread:
    name: str
    ident: Optional[int]
    daemon: bool
    def __init__(self, group: None = ...,
                 target: Optional[Callable[..., Any]] = ...,
                 name: Optional[str] = ...,
                 args: Iterable = ...,
                 kwargs: Mapping[str, Any] = ...,
                 *, daemon: Optional[bool] = ...) -> None: ...

對類型注解有簡單的了解,可以方便我們看別人的代碼或是在自己的代碼中使用它。

簡單使用

Python 運行時不強制執行函數和變量類型注解,但這些注解可用於類型檢查器、IDE、靜態檢查器等第三方工具。有了類型注解,IDE 解析代碼也會更方便,提示也會更智能。簡單使用非常易於理解,比如下面的例子:

def greeting(name: str) -> str:
    return 'Hello ' + name

這表示:greeting 函數中,參數 name 的類型是 str,返回類型也是 str。子類型也可以當作參數。

注解列表、集合等可迭代對象

GenericAlias 對象是通過對類(通常是容器類)作下標來創建的,如 list[int] 用來表示元素類型為 int 的列表。

通常,容器對象的抽取操作會調用該對象的 __getitem__() 方法。 但是,對某些容器類執行抽取操作可能會改去調用該類的 __class_getitem__() 類方法。 __class_getitem__() 類方法應當會返回一個 GenericAlias 對象。

如果元素的類型不是固定的,那么可以使用 Union| 來表示,比如要注解一個元素類型可能為 strint 的列表,可以這樣寫:

from typing import Union, List

my_li: List[Union[str, int]]
# 或
my_li: List[str|int]

集合、元組或是自定義的可迭代對應同理。

如果要注解字典呢?

可以用如下方法:

from typing import Dict

my_dict: Dict[int, str]

這表示 my_dict 是一個鍵類型為 int,值類型為 str 的字典。

注解可調用對象

預期特定簽名回調函數的框架可以用 Callable[[Arg1Type, Arg2Type], ReturnType] 實現類型提示。

比如,要注解一個可調用對象,它接收兩個參數,類型分別是 int, str,返回的類型是 list,那么可以這樣寫:

from typing import Callable

func: Callable[[int, str], list]

另外,無需指定調用簽名,用省略號字面量替換類型提示里的參數列表: Callable[..., ReturnType],就可以聲明可調對象的返回類型。比如上面的例子也可以寫為:

from typing import Callable

func: Callable[..., list]

如果要注解沒有返回值的對象,可以使用 typing.NoReturn

from typing import Callable, NoReturn

func: Callable[..., NoReturn]

typing.NoReturn 同樣可以對函數返回注解,如:

def stop() -> NoReturn:
    pass

注解常量

常量可以使用 Final 注解,比如:

from typing import Final

NAME: Final = 'Spartan'

對於不可被覆蓋的方法,可以用 final 裝飾器,例如:

from typing import final

class Foo:

    @final
    def finish(self):
        pass
    

注解可選參數

使用 Optinal 可以注解可選參數,比如,注解名為 name 的可選參數:

from typing import Optional


def check(name: Optional[str]=None):
    pass

泛型

有的類型實在難以描述?沒關系,可以使用 TypeVar 定義一個泛型,比如,要注解一個難以描述的類型(暫且稱之為 Puzzle),那么可以這樣定義它:

from typing import TypeVar

Puzzle = TypeVar('Puzzle')

然后就可以用它來注解了:

name: Puzzle = ...

Any

Typing.Any 可以表示任意類型,此外,未指定返回值與參數類型的函數,都隱式地默認使用 Any

類型別名

把類型賦給別名,就可以定義類型別名。比如:

Vector = list[float]

def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]

參考

1. [typing --- 類型提示支持 — Python 3.10.1 文檔] (https://docs.python.org/zh-cn/3/library/typing.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM