python型別註解

2022-06-20 19:54:11 字數 4432 閱讀 2087

使用->加型別代表返回值型別

python直譯器執行時並不會檢查型別,型別不對也不會拋異常,僅僅是註解而已。示例:

def plus(a: int, b: int = 2) -> int:

return a + b

python 解析器並不會在意型別註解,嚴格來說這是不對的,python 會把型別資訊放在__annotations__屬性中:

>>> def foo(a: str):

... print('hello', a)

...>>> foo.__annotations__

>>> class bar:

... a: str

... b: int

>>> bar.__annotations__

內建提供的型別:intstrfloat,typing模組提供的型別:dictlisttuble...

typing使用方括號dict[str, int]而不是圓括號dict(str, int)

dict

dict[str, int]: 表示乙個 keys 的型別為 str,values 的型別為 int 的字典,比如

from typing import dict

dict[str, dict[str, list[str]]]如下:

, '鴿子鎮':

}

list

list[int] 表示由整型組成的列表,比如[0, 1, 1, 2, 3]

list[list[int]] = [[1, 2], [2, 3]]
tuple

tuple[int, float, str] is a tuple of an int, a float and a string.

person: tuple[str, int, float] = ('mike', 22, 1.75)
set/abstractset

根據官方文件,set 推薦用於註解返回型別,abstractset 用於註解引數

def describe(s: abstractset[int]) -> set[int]:

return set(s)

sequence

sequence,是 collections.abc.sequence 的泛型,在某些情況下,我們可能並不需要嚴格區分乙個變數或引數到底是列表 list 型別還是元組 tuple 型別,我們可以使用乙個更為泛化的型別,叫做 sequence,其用法類似於 list

def square(elements: sequence[float]) -> list[float]:

return [x ** 2 for x in elements]

noreturn

noreturn,當乙個方法沒有返回結果時,為了註解它的返回型別,我們可以將其註解為noreturn

def hello() -> noreturn:

print('hello')

any

any,可以代表所有型別,所有的無引數型別註解和返回型別註解的都會預設使用 any 型別,以下兩個函式等價:

def add(a):

return a + 1

def add(a: any) -> any:

return a + 1

typevar

typevar,自定義相容特定型別的變數,比如有的變數宣告為 int、float、none 都是符合要求的,實際就是代表任意的數字或者空內容都可以,其他的型別則不可以,比如列表 list、字典 dict 等等,像這樣的情況,我們可以使用 typevar 來表示。

height = 1.75

height = typevar('height', int, float, none)

def get_height() -> height:

return height

newtype

newtype,宣告一些具有特殊含義的型別,像 tuple 的例子一樣,我們需要將它表示為 person,即乙個人的含義,但但從表面上宣告為 tuple 並不直觀,所以我們可以使用 newtype 為其宣告乙個型別,如:

person = newtype('person', tuple[str, int, float])

person = person(('mike', 22, 1.75))

實際上 person 就是乙個 tuple 型別,我們可以對其像 tuple 一樣正常操作。

callable

callable,可呼叫型別,通常用來註解乙個方法, 在宣告的時候需要使用callable[[arg1type, arg2type, ...], returntype]這樣的型別註解,將引數型別和返回值型別都要註解出來,例如:

def date(year: int, month: int, day: int) -> str:

return f'--'

def get_date_fn() -> callable[[int, int, int], str]:

return date

-> callable[[int, int, int], str]: 中括號內分別標記了返回的方法的引數型別和返回值型別。

union

union,聯合型別,union[x, y]代表要麼是 x 型別,要麼是 y 型別。

union[union[int, str], float] == union[int, str, float]

union[int] == int

union[int, str, int] == union[int, str]

# 無引數順序

union[int, str] == union[str, int]

在一些方法引數宣告的時候比較有用,比如乙個方法,要麼傳乙個字串表示的方法名,要麼直接把方法傳過來:

def process(fn: union[str, callable]):

if isinstance(fn, str):

# str2fn and process

pass

elif isinstance(fn, callable):

fn()

這樣的宣告在一些類庫方法定義的時候十分常見。

optional

optional,意思是說這個引數可以為空或已經宣告的型別,即optional[x]等價於union[x, none]

optional 並不等價於可選引數,當它作為引數型別註解的時候,不代表這個引數可以不傳遞,而是說這個引數可以傳none,不傳也會報錯。

當乙個方法執行結果,如果執行完畢就不返回錯誤資訊, 如果發生問題就返回錯誤資訊,則可以這麼宣告:

def judge(result: bool) -> optional[str]:

if result: return 'error occurred'

generator

generator,想代表乙個生成器型別,可以使用 generator,它的宣告比較特殊,其後的中括號緊跟著三個引數,分別代表 yieldtype、sendtype、returntype,如:

def echo_round() -> generator[int, float, str]:

sent = yield 0

while sent >= 0:

sent = yield round(sent)

return 'done'

在這裡 yield 關鍵字後面緊跟的變數的型別就是 yieldtype,yield 返回的結果的型別就是 sendtype,最後生成器 return 的內容就是 returntype。

當然很多情況下,生成器往往只需要 yield 內容就夠了,我們是不需要 sendtype 和 returntype 的,可以將其設定為空,如:

def infinite_stream(start: int) -> generator[int, none, none]:

while true:

yield start

start += 1

python學習 型別註解,inspect模組

函式定義的弊端 python是動態語言,變數隨時可以被賦值,且能賦值為不同的型別 python不是靜態編譯型語言,變數型別是在執行期決定的 動態語言很靈活,但是這種特性也是弊端 函式註解 python3.5引入 對函式的引數進行型別註解 對函式的返回值進行型別註解 只對函式引數做乙個輔助的說明,並不...

Python 3 型別註解

python 是一種動態語言,變數以及函式的引數是不區分型別。因此我們定義函式只需要這樣寫就可以了 def add x,y return x y用 型別 的形式指定函式的引數型別,用 型別 的形式指定函式的返回值型別。from typing import list def twosum self,n...

python 編碼中為什麼要寫型別註解?

我們先談談為什麼在python編碼過程中強烈推薦使用型別註解 python對於初學者來說是非常好上手,原因是在於對計算機底層原理的高度封裝和動態語言的特性使得python用起來非常的舒適。但這種 舒適 是有代價的,我們可能聽說過一句形容動態語言的話,動態一時爽,一直動態一直爽。為什麼會這麼說?動態的...