1、類型注解簡介
python是一種動態類型化的語言,不會強制使用類型提示,但為了更明確形參類型,自python3.5開始,pep484為python引入了類型注解(type hints)
示例如下:
2、常見的數據類型
- int,long,float: 整型,長整形,浮點型
- bool,str: 布爾型,字符串類型
- list, tuple, dict, set: 列表,元組,字典, 集合
- iterable,iterator: 可迭代類型,迭代器類型
- generator:生成器類型
- sequence: 序列
3、基本的類型指定
1
2
3
4
5
6
7
|
def test(a: int , b: str ) - > str : print (a, b) return 200 if __name__ = = '__main__' : test( 'test' , 'abc' ) |
函數test,a:int 指定了輸入參數a為int類型,b:str b為str類型,-> str 返回值為srt類型。可以看到,在方法中,我們最終返回了一個int,此時pycharm就會有警告;
當調用這個方法時,參數a 輸入的是字符串,此時也會有警告;
but…,pycharm這玩意兒 只是
提出了警告
,但實際上運行是不會報錯,畢竟python的本質還是動態語言
。
4、復雜的類型指定
指定列表
1
2
3
4
5
6
7
8
9
10
11
|
from typing import list vector = list [ float ] def scale(scalar: float , vector: vector) - > vector: return [scalar * num for num in vector] # type checks; a list of floats qualifies as a vector. new_vector = scale( 2.0 , [ 1.0 , - 4.2 , 5.4 ]) print (new_vector) |
指定 字典、元組 類型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
from typing import dict , tuple , sequence connectionoptions = dict [ str , str ] address = tuple [ str , int ] server = tuple [address, connectionoptions] def broadcast_message(message: str , servers: sequence[server]) - > none: print (message) print (servers) # the static type checker will treat the previous type signature as # being exactly equivalent to this one. if __name__ = = '__main__' : broadcast_message( 'ok' , [(( '127.0.0.1' , 8080 ), { "method" : "get" })]) |
這里需要注意,元組這個類型是比較特殊的,因為它是不可變的。
所以,當我們指定tuple[str, str]時,就只能傳入長度為2
,并且元組中的所有元素
都是str類型
5、創建變量時的類型指定
對于常量或者變量添加注釋
1
2
3
4
5
6
7
8
9
10
11
12
|
from typing import namedtuple class employee(namedtuple): name: str id : int = 3 employee = employee( 'guido' ) # assert employee.id == 3 # 當類型一致時,不會輸出內容,反之報錯 assert employee. id = = '3' # 當類型一致時,不會輸出內容,反之報錯 # assertionerror |
指定一個變量odd,顯式的聲明了它應該是整數列表。如果使用mypy來執行這個腳本,將不會收到任何提示輸出,因為已經正確地傳遞了期望的參數去執行所有操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from typing import list def odd_numbers(numbers: list ) - > list : odd: list [ int ] = [] for number in numbers: if number % 2 : odd.append(number) return odd if __name__ = = '__main__' : numbers = list ( range ( 10 )) print (odd_numbers(numbers)) |
mypy 安裝
1
|
pip install mypy |
執行 mypy file,正常情況下不會報錯
c:\users\sunny_future\appdata\roaming\python\python36\scripts\mypy.exe tests.py
# 指定 環境變量或者 linux 下可以直接執行 mypy
# mypy tests.py
success: no issues found in 1 source file
接下來,嘗試更改一下代碼,試圖去添加整形之外的其他類型內容!那么執行則會檢查報錯
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
from typing import list def odd_numbers(numbers: list ) - > list : odd: list [ int ] = [] for number in numbers: if number % 2 : odd.append(number) odd.append( 'foo' ) return odd if __name__ = = '__main__' : numbers = list ( range ( 10 )) print (odd_numbers(numbers)) |
代碼中添加一個行新代碼,將一個字符串foo
附加到整數列表中。現在,如果我們針對這個版本的代碼來運行mypy
1
|
c:\users\sunny_future\appdata\roaming\python\python36\scripts\mypy.exe tests.py |
tests.py:114: error: argument 1 to “append” of “list” has incompatible type “str”; expected “int”
found 1 error in 1 file (checked 1 source file)
6、 泛型指定
1
2
3
4
5
6
7
8
9
10
11
12
|
from typing import sequence, typevar, union t = typevar( 't' ) # declare type variable def first(l: sequence[t]) - > t: # generic function return l[ 0 ] t = typevar( 't' ) # can be anything a = typevar( 'a' , str , bytes) # must be str or bytes a = union[ str , none] # must be str or none |
7、再次重申
在python 3.5中,你需要做變量聲明,但是必須將聲明放在注釋中:
1
2
3
4
5
|
# python 3.6 odd: list [ int ] = [] # python 3.5 odd = [] # type: list[int] |
如果使用python 3.5的變量注釋語法,mypy仍將正確標記該錯誤。你必須在
#
井號之后指定type:。如果你刪除它,那么它就不再是變量注釋了。基本上pep 526增加的所有內容都為了使語言更加統一。
8、不足之處
雖然指定了 list[int] 即由 int 組成的列表,但是,實際中,只要這個列表中存在 int(其他的可以為任何類型),pycharm就不會出現警告,使用 mypy 才能檢測出警告!
1
2
3
4
5
6
7
8
9
10
|
from typing import list def test(b: list [ int ]) - > str : print (b) return 'test' if __name__ = = '__main__' : test([ 1 , 'a' ]) |
pycharm 并沒有檢測出類型錯誤,沒有告警
mypy
工具 檢測到 類型異常,并進行了報錯
9、demo
1
2
|
# py2 引用 from__future__import annotations |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class starship: captain: str = 'picard' damage: int stats: classvar[ dict [ str , int ]] = {} def __init__( self , damage: int , captain: str = none): self .damage = damage if captain: self .captain = captain # else keep the default def hit( self ): starship.stats[ 'hits' ] = starship.stats.get( 'hits' , 0 ) + 1 enterprise_d = starship( 3000 ) enterprise_d.stats = {} # flagged as error by a type checker starship.stats = {} # this is ok |
1
2
3
4
5
6
7
8
9
|
from typing import dict class player: ... players: dict [ str , player] __points: int print (__annotations__) # prints: {'players': typing.dict[str, __main__.player], # '_player__points': <class 'int'>} |
1
2
3
|
class c: __annotations__ = 42 x: int = 5 # raises typeerror |
到此這篇關于詳解python3類型注釋annotations實用案例的文章就介紹到這了,更多相關python3類型注釋annotations內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/Sunny_Future/article/details/112795269