Python3.7預計在今年夏天發布,讓我們一起偷瞄一眼它帶來的新功能吧。如果你經常一個人在家用Pycharm擼代碼,請確保將你的Pycharm升級到2018.1版本。(等你讀完本文再升級也來得及)。
Python3.7版本包含了眾多新特性:比如對各種字元集的升級,推後了對注釋的評價等等。其中最受期待的新特性是對資料類裝飾器的支援。
什麼是資料類
絕大多數的python開發人員都寫過許多類,比如下圖這樣的。
資料類可以自動地給你定義的執行個體產生“魔術”方法。例如:__init__可以接收參數,並把參數分配給self。上圖中的小例子也可以這樣寫:
其中關鍵的不同點在於,資料類實際上是要求類型提示的。如果你以前從未用到過類型提示:類型提示允許你標記代碼中某一個變數應該是哪種資料類型的。在運行時,變數的資料類型不會被檢查,但你可以用Pycharm或者命令列工具比如mypy來靜態檢查你的代碼。
那麼,讓我們看看如何使用這個新特性。
星球大戰API
你一定知道當一個電影粉絲用自己最愛的電影的資料建立了一個組REST API會讓這個電影的粉絲團熱情響應。一個星戰粉絲就是這麼乾的,建立了星球大戰API。實際上他做的更完善,直接為這個API建立了一個python庫。
讓我們暫時忘記這個封裝庫的存在,並探究一下如何建立我們自己的庫。
我們可以用request庫從星球大戰API中擷取資源。
這個終端(和所有終端一樣)用JSON格式的資訊進行響應。Request庫還提供JSON解析。
此時我們把資料存入到了一個字典中,讓我們來看一下。
封裝這個API
為了正確封裝這個API,我們應該建立一個讓使用者可以在自己的應用使用的對象。所以讓我們用Python3.6定義一個對象來存放對/films/終端請求的響應。
細心的讀者可能已經注意到了上面的代碼有一些冗餘,不太細心的讀者可以參考一下完整的Python3.6實現(可不短呦)。
這是一個資料類裝飾器幫你擺脫困境的經典案例。我們建立了一個用來儲存資料,只進行少量驗證的類。接下來一起看看有哪些地方需要修改。
首先,資料類自動的產生一些個魔術方法。如果我們沒有指定任何資料類裝飾器的選項,則自動產生的魔術方法為:__init__,__eq__,以及__repr__.如果你以及定義了__repr__,而不是__str__,那麼python會預設地實現__str__以返回__repr__的輸出結果。進而,你只要將代碼如下圖這樣修改一下就得到了四種魔術方法:
在這裡我們去掉了__init__方法來確保資料類裝飾器可以添加它的子集。不幸的是在這一步中,我們還缺少了一個功能。我們的Python3.6建構函式不僅定義了所有的值,同時它還應該會嘗試去解析資料。我們應該如何用資料類來實現這個功能呢。
如果我們重寫__init__方法,那麼就失去了用資料類的好處。因此,為了實現這些額外的處理,一個新的魔術方法__post_init__就誕生了。一起看下這個方法在我們要封裝的對象中長什麼樣子:
大功告成,在資料類裝飾器的協助下,我們僅用了原先1/3行數的代碼就實現了我們的類。
更多的好處
通過使用裝飾器的選項,你可以進一步為自己的執行個體定製資料類。預設的選項是這樣的:
init選項決定是否產生__init__方法。
repr選項決定是否產生__repr__方法。
eq選項同上,其中__eq__方法定義了檢查是否相等的操作。
order選項實際上產生了四個用來定義檢查大於、小於、and、or操作的魔術方法,設定此項為True,你就可以對對象進行排序。
最後的兩個選項決定了你的對象是否能被雜湊。這是非常必要的,比如在你想用類的對象作為字典鍵時。雜湊函數應該在對象的生命週期內一直生效,否則儲存資料的字典就再也找不到你的對象了。資料類中的__hash__函數將會預設地返回資料類中所有對象的雜湊值。因此,只有在你設定對象為唯讀時(令frozen=True)才會預設地產生__hash__函數。
一旦使用frozen=True設定了唯讀屬性,任何對你的對象進行寫入的操作都會報錯。如果你覺得這樣太苛刻,並且還是想要確保對象永遠不會被改變,那麼可以設定unsafe_hash=True來代替frozen=True。資料類裝飾器的開發人員們不建議這樣做。
如果你想更加深入的瞭解資料類,可以查閱PEP或者直接開始使用資料類玩耍啦。請在評論中告訴我們你都用資料類做了什麼。
∞∞∞∞∞
IT派 - {技術青年圈} 持續關注互連網、區塊鏈、人工智慧領域
公眾號回複“Python”,
邀你加入{ IT派Python技術群 }