使用->
加型別代表返回值型別
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__
內建提供的型別:int
、str
、float
,typing模組提供的型別:dict
、list
、tuble
...
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用起來非常的舒適。但這種 舒適 是有代價的,我們可能聽說過一句形容動態語言的話,動態一時爽,一直動態一直爽。為什麼會這麼說?動態的...