我們先談談為什麼在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 極客時間 左耳聽風 專欄作業 每週分享一些技術或是其他方面的思考,這也是我正在做的事。對於現在的我來說,賺錢 並不是我的首要目的,而且現在水平還相差甚遠。總的來...