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

2022-09-25 23:30:15 字數 3202 閱讀 4609

我們先談談為什麼在python編碼過程中強烈推薦使用型別註解 ?

python對於初學者來說是非常好上手,原因是在於對計算機底層原理的高度封裝和動態語言的特性使得python用起來非常的舒適。但這種「舒適」是有代價的,我們可能聽說過一句形容動態語言的話,動態一時爽,一直動態一直爽。為什麼會這麼說?動態的確會賦予我們在編碼時更多的靈活性與能力,但是動態帶來的是更多的不確定性及混亂,導致了後來的維護者甚至作者自己都會產生很大的維護壓力(可以想象乙個經過幾年迭代的複雜系統,如果大部分都使用動態的方式來編寫**的樣子),正所謂能力越大責任越大,需要進行克制;

而型別註解能很好的幫我們在維護與開發時,理清變數型別降低不確定性和混亂度,並且從容的使用變數。在這裡廢話了這麼多,主要是為了能讓讀者能深刻意識到動態帶來的正反方向帶來的「爽」。後面進入正題;

內建註解肯能大家都接觸過,但總感覺很麻程式設計客棧煩,導致後面很容易就放棄寫註解,這是因為得到不正反饋,看如下示例:

a: str = "aa"

b: int = 1

# 引數和返回標註了型別,那麼接下來呼叫時就能進行提示

def example(a: str) -> str:

return f"hello "

pirnt(example("world"))

# # 一些簡單的標註,看起來起不到效果,但如果換個有含義的名字呢

user = str

age = int

answer = str

def say_hello(u: user) -> answer:

return f"hello "

print(say_hello("shadow"))

上面簡單演示了內建的型別註解是如何使用的,但是其實這麼簡單的型別註解並不能幫助我們很好的標註變數;下面介紹乙個typing模組

typing 模組是型別註解的主角,python執行時不強制執行函式和變數型別註解,但這些註解可用於型別檢查器、ide、靜態檢查器等第三方工具。這些第三方工具會在我們編碼時進行提示與糾錯;

下面提供一些日常使用到的方法與用例給大家參考:

import typing

# 自定義型別註解

user = str

age = int

# 定義有多種型別註解的型別

anystr = typing.typevar('anystr', str, bytes)

a_str: anystr = "a"

a_bytes: anystr = b"a"

# 通用型別, 接收通用的型別,盡量少的去使用

def example_1(a: typing.any):

print(a)

"""typing 模組是允許使用下標來輔助標記型別

"""# 列表, 下標為列表的屬性

def example_2(a_list: typing.list[user]) -> typing.list[str]:

pass

# 字典,下標第乙個為key,第二個為value

def example_3(a_dict: typing.dict[user, age]) -> typing.dict[str, int]:

pass

# 元祖,下標為元祖的屬性

def example_4(a_tuple: typing.tuple[user] = none) -> typing.tuple[user]:

pass

# union, 在一些場景下我們某些引數或返回值是不確定,至少給定乙個引數型別

def example_5(a_b: typing.union[str, int]) -> typing.union[str, int]:

pass

# optional, 與union 有點類似,但預設多帶乙個none,至少給定乙個引數型別

# 如:optional[str] 等價於 union[str, none]

def example_6(a: str) -> typing.optional[str]:

pass

# tuple, 返回值有多個的時候, 如需要返回str, int, bool, float

def e程式設計客棧xample_7() -> typing.tuple[str, int, bool, float]:

pass

# class, 類本身也是一種型別

class action:

up: str = "up"

down: str = "down"

# 指定需求乙個action物件的引數

def example_8(action_obj: action) -> action:

pass

# 這樣在一些列舉引數的場景下,我們也可以使用類作為我們列舉引數的歸類

def example_9(action_cls: action) -> action:

pass

# 如果上面的列舉引數你覺得並不能很好的實現,那麼還是可以使用自定義型別註解的方式去實現

action = str

up: action = "up"

down: action = "down"

# 在python3.9 中對列舉引數型別有更好的支援

mode = type.literal['r', 'rb', 'w', 'wb']

def open_file(file: str, mode: mode) -> str:

pass

open_file('/some/path', 'r') # 正常

open_file('/other/path', 'typo') # 會提示該型別不合法

# type, 在一些多型類的場景下標註同乙個型別的不同的形態

class user: ...

class basicuser(user): ...

class prouser(user): ...

class teamuser(user): ...

# 相當於 typing.union[user, basicuser, prouser, teamuser]

def make_new_user(user_class: typing.type[user]) -> user:

return user_class()

以上十幾個用例場景基本能覆蓋大部分日常編碼,如果還有一些別的需求可參考官方的文件,上面有明確的說明;

docs: docs.pytho程式設計客棧n.org/zh-cn/3/lib…

為什麼要寫部落格?

一直想堅持寫部落格,但是總是以各種理由推脫,今天下決心果斷邁出第一步,下決心以後堅持寫,希望大家監督!為什麼開始寫部落格?1.對自己所學的知識進行歸納整理,可以促進思考,有益於加深對知識點的理解記憶,也便於以後快速複習掌握 2.積累下自己的經驗的同時分享給有需要的人,幫助後來者少走彎路 3.寫作是記...

為什麼要寫部落格

以前在學校階段就開始記錄使用包括 為知筆記 有道雲筆記 evernote 等記錄技術要點,目前主要使用evernote,也就是國際版的 印象筆記 使用什麼工具記錄技術要點到還是其次,這個作為技術積累來說並不要緊。要緊的是記錄什麼內容。記錄什麼內容反映了乙個技術人員的胸懷和關注點的大小。最初記錄技術要...

為什麼要寫作?

從 2018 年 10 月 21 日開始寫一些東西,至今 216 天,寫一篇關於寫作的體會。對我來說,寫作的一開始是為了打卡完成 arts 極客時間 左耳聽風 專欄作業 每週分享一些技術或是其他方面的思考,這也是我正在做的事。對於現在的我來說,賺錢 並不是我的首要目的,而且現在水平還相差甚遠。總的來...