aop在項目中的實際運用_mypy在實際項目中的應用

110454e0fa53a31c27be99191664d6cc.png

我認為靜態類型似乎被吹捧過高了。

盡管如此,mypy極低的侵入性能帶來許多好處。關于如何在現有的Python項目中添加類型,以下是我的一些想法,大致按重要性排序。

首先確保mypy成功運行?

Mypy上手時兩個很常見的問題有:

1.Mypy沒有作為構建的一部分運行

2.mypy 雖然正在運行,但它沒有找到任何源文件或只找到了一部分源文件

Mypy的“默認允許”特性使兩者都極易出現。無論出現哪種情況,都會非常痛苦,因為最后人們應用的類型,其實并未被檢查,因而問題會慢慢暴露出來,讓人非常困惑。

要手動添加類型的地方

Mypy 可進行類型推斷,即通過檢查有關值的代碼,基于上下文區分值的類型。但事實上,由于mypy“漸進式推斷”的特點,(如果不確定,它將推斷成Any類型),比起像Haskell等其他推斷性的語言,在python中更需要手動提供類型。

我目前的想法是:你應該力求為所有函數實參和返回值1 (以及其他任何mypy需要幫助的地方)提供類型。

一般來說,變量不需要應用類型,盡管這可能有助于使你的代碼更清晰,或者幫助處理你不理解的類型錯誤。

Opitional會被頻繁使用

在實踐中最重要的一種類型就是 Optional. Optional 被用于可為空的值. 舉個例子:

287a2661e8a9293c08b8afb9d4241752.png

大量的代碼會使用Optional配合其他類型使用。有了Optional,mypy就能夠檢查空值,無論該值被用在哪里。

Optional是一種簡單的類型但它卻能夠查出大量的缺陷,它可能是整個類型檢查體系中最好的部分。

考慮是否要包含你的測試

關于是否在類型檢查中包含測試(即也對測試進行類型檢查),我不知道有沒有統一答案。有些項目確實能在 tests/? 目錄上運行mypy,有些則不能。

在類型檢查2中包含測試的主要優點是:你能迅速發現應用類型和預期用法不一致,或mypy推斷的類型與預期用法不符。

這在新的或沒有太多類型應用的代碼庫中尤其有用。另外,測試也能用來改善IDE的 tab-completion

然而不利的一面就是,通常出于Mock(模擬)和Fake(偽造)的目的,測試有時會對你的代碼進行一些古怪操作,而且,某些測試模式通過類型檢查器可能有點困難 這雖然不是什么大問題,但似乎有點浪費時間,并且會削弱類型的優勢。

有選擇性地使用第三方stub(存根)

一些庫包含大量運行時的元編程技巧. 因而這些庫通常不會提供太多類型信息。

在程序中心使用了這些庫,卻不能獲取類型信息,這會十分惱人。一些庫有第三方Stub文件,例如sqlalchemy有sqlalchemy-stubs ,它會提供一些有用但不完全的類型。

這些庫并非都有有用的第三方Stub。在撰寫本文時,我對boto的任何第三方Stub都不信服。最好的方法似乎是在調用AWS / Openstack API時學會與Any一起使用(但要用moto進行徹底測試)。

偶爾需要應急措施

你偶爾會遇到這樣的情況:代碼正確但mypy無法分辨。這里有幾種解決方法:

第一種(可能是最好的方法)就是用typing.cast,它會告訴? mypy 你知道的比它知道的更多。這將在整個代碼中保持類型檢查,除非通知 mypy做一個特定的更正。

第二種選擇就是值顯式設置為Any。這將禁用檢查該特定值。如果所討論的值是沒有簡單類型的復雜對象,則可以使用此方法。

第三種就是使用?# type: ignore 語法. 如果問題不在于確定特定類型,而在于mypy誤認為被破壞了的某些不變類型,用這個會很方便。

考慮加一個注釋去解釋原因

優先選擇一些嚴格性選項

Mypy的 mypy.ini 文件允許進行廣泛的配置。我還沒見過哪個實操項目避免使用mypy配置的。以下是我的首選:

  • ?check_untyped_defs 使mypy嘗試檢查沒有類型注釋的函數內部。否則,對于類型注釋級別較低的項目mypy很少檢查。

  • no_implicit_optional 當你設定參數不是空值,但實際上它們可為空時,它將提示類型錯誤。

  • ignore_missing_imports ?這個應謹慎使用,不要將其應用于整個mypy 中,否則會極大地增加由于錯誤導致重要代碼檢查失敗的風險。用此配置選項來標記特定模塊(或名稱空間)即可。

一個可行的例子:

91fa03ceb1cfa34b0823ab49da9cbd82.png

一旦你的項目深度耦合了mypy,我建議最好去查看mypy提供的所有其他嚴格選項。從低嚴格度級別開始,朝著高嚴格度級別推進是一個好的策略。

如何調試類型問題

對于難懂的類型問題,這里給出兩個策略來調試。

第一種:你可以將類型應用于出錯類型周圍,如變量、函數參數、循環迭代變量等。這樣有助于將錯誤從難懂的那行代碼中移動到更容易看出問題的地方。

第二:使用魔法般的mypy內置函數。reveal_type(expr)能使 mypy 打印出給定表達式類型的意見;reveal_locals()?則會讓mypy打印出范圍內所有變量的類型. 這兩者中,我用 reveal_locals()??更多一些。

抽象,具體,可變和不變

Mypy 有具體的類型,如 List 和 Dict;也有抽象的類型,如 Sequence 和Mapping

一些抽象的類型還分可變和不可變的版本,例如Set 和 MutableSet ,Mapping 和 MutableMapping

因此我們需要去選擇應用哪種類型及何時應用。

我的朋友Oli Russell提出以下策略:

  1. 讓參數類型盡可能抽象

  • 這樣能使調用者盡可能自由地傳遞他們想要的

? 2.讓返回類型(更)具體

  • 同樣也是為了讓調用者盡可能自由地使用返回值

以上與我的經驗相符。如果你過于苛刻, 比如,你返回 Sequence 而不是 List, 那么別人之后還要去編輯你的返回類型才能達到他們的目的。

同樣的, 太具體的參數類型也很麻煩。你會發現無法將自定義的類似dict的對象傳遞給函數。有的對象只定義了__getitem__,但它確實可以當成一個Dict來使用。

你可以查閱 collections.abc 的標準庫文檔,去找每種抽象類型中包含的方法。以下是最常用的:

  • Iterable

  • Sequence 和 MutableSequence

  • Mapping 和 MutableMapping

  • Set 和 MutableSet

另外還有其他考慮。也許你想要阻止調用者修改你要返回的東西 (可能是因為你正在內部使用它3)。在這種情況下,最好返回 Mapping 而不是Dict。

Typed dataclasses(類型化的數據類)

Python 3.7 引入了 dataclasses. 下面是一個可能的類定義,如果你的類主要包含數據 (而不是行為)。它能為你提供一個更簡潔的語法。

726e7df0bf88c5a2fd1d4bce293929c0.png

類型系統也支持這樣的類,來作為其值的類型。

但缺點就是,大量更改其數據表示形式的代碼往往不是快速代碼。如果一個不可變的 Mapping作用于程序中的大部分,那它會比有一系列中間數據類要更快。

TypedDict

在 mypy 的擴展庫中還有一個typed dictionary ?。自3.8版本起它在標準庫里。

c478f73886debfc7edba3901acc74168.png

TypedDict 能讓你通過類型系統來控制存在哪些鍵以及它們的鍵值是什么,這一點勝過平常用的Mapping[str, str]。

它能成為Typed dataclasses的一個有效替代方案,且通常速度更快。

泛型和類型變量

mypy包括對類型變量和泛型類型的支持. 似乎大多數人發現如List等使用起來簡單自然,但當有新的類型被創建出來之后,代碼往往傾向于將類型限制定義為基類。

但是不是所有的泛型都不符合規則 , 在各式各樣的Python 代碼中,泛型偶爾也有使用價值。

泛型允許變量的類型更靈活 ,但它會保持檢查 ,舉個例子:

2222495f720706508921bbe515f5bea0.png

另一個例子:

398d0a5b6afd694c8621904156275c37.png

泛型能讓你定義專門作用于某種類型變量的類。下面這個例子中,我們將D綁定到一個特定的抽象基類。

de4065bacdd1f0409e05917d6ea4264f.png

我相信接下來幾年這個將被廣泛使用

ABCs vs Protocols

有時,需要將抽象類型應用于具有各種具體選項的事物(此處在實踐中和使用泛型類型有交叉)。有兩種方法可以做到這一點。

第一種:通過下面的方法命名父基類,子類將從該基類繼承。

078dd9d50d3fb0072dffa00a235e335c.png

這里的 feed_animal 標記為采用Animal (一種抽象基類)。

第一種方法稱為名義子類型化,作為在面向對象的語言中使用抽象類型的傳統方式,大多數人應該熟悉。

還有第二種(相對于Python)較新的方法,在該方法中,您無需命名父類,而是命名一個有你所需方法的“協議”。

7313e1de66487c874f012df0313660d8.png

這里的feed_animal 被標記使用 Carnivore (一種協議)。注意,我不必將任何animal類標記為成員:如果它們具有相同類型的eat_meat方法,則它們將自動作為Carnivore的一部分

協議是“開放的”,因此任何具有匹配eat_meat方法的類都將被算作成員。這種方法叫做結構子類型化。有許多 built in protocols(內置協議),例如Sized,SupportsBytes,Container等。

如果你能控制足夠多的類層次結構,則可以選擇名義子類型,但是如果不能,則必須使用結構子類型。

與泛型類型一樣,這個最好謹慎使用。希望絕大多數情況下,具體類型就夠用了,這樣就不必在代碼庫中填充大量協議和抽象基類了。

最后的提示

一些人太過于執迷類型了,我目睹了大量Haskell社區的人一頭扎進自己的創作中無法自拔,變得癡癡傻傻,實在有點看不下去。

要小心變成類型狂!不要忽略這樣一個事實:類型檢查是修正錯誤的一種輔助,而勿滿足于類型檢查本身。

另請參閱

  • Dropbox是最早將mypy應用于其代碼庫的公司之一。對此他們也寫了經驗,讀來十分有趣。"The Tangle"在許多Python項目中出現過。

注釋:

  1. 強制執行此操作的相關配置選項是disallow_untyped_defs,但對現有項目立即啟用它通常只會貪多嚼不爛。

  2. 請注意,你必須在與主代碼庫相同的mypy中運行測試。將測試分開各自運行是得不到任何好處的。

  3. 正如我在本文提到過的,避免在任何地方創建新集合的一個很好的理由是速度。用不可變的抽象類型標記返回類型有助于對此進行靜態分析。

英文原文:http://calpaterson.com/mypy-hints.html
譯者:?

e6eb955c900726c6fe4a8309e2b1c60f.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259043.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259043.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259043.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

face alignment by 3000 fps系列學習總結(三)

訓練 我們主要以3000fps matlab實現為敘述主體。 總體目標 我們需要為68個特征點的每一個特征點訓練5棵隨機樹,每棵樹4層深,即為所謂的隨機森林。 開始訓練 分配樣本 事實上,對于每個特征點,要訓練隨機森林,我們需…

HDU 2049 不容易系列之(4)——考新郎( 錯排 )

鏈接:傳送門思路:錯排水題,從N個人中選出M個人進行錯排,即 C(n,m)*d[m]補充:組合數C(n,m)能用double計算嗎?第二部分有解釋 Part 1. 分別求出來組合數的分子和分母然后相除/******************************…

級聯sql

select ID, PID, NAME,KEY from HS_DICT start with KEY HS_EXP_WORK_LOCATIONconnect by prior ID PID order by DISPLAYORDER轉載于:https://www.cnblogs.com/dazhaxie/p/3483532.html

獲取母版中的控件

1 通過findcontrol找控件ID需要在此事件中~因為Page_load中時是先內容頁加載然后才是母版頁加載 protected void Page_LoadComplete(object sender, EventArgs e) { Label2.Text "現在時間是" (Master.FindControl("Label1") as Label).Text; if (Reques…

linux服務器選ubantu或centos_如何通過SSH連接阿里云上的Linux系統

首先SSH是啥,維基一下:Secure Shell(安全外殼協議,簡稱SSH)是一種加密的網絡傳輸協議,可在不安全的網絡中為網絡服務提供安全的傳輸環境[1]。SSH通過在網絡中創建安全隧道來實現SSH客戶端與服務器之間的連接…

face alignment by 3000 fps系列學習總結

我們主要講一講Github上給出的matlab開源代碼《jwyang/face-alignment》的配置。 首先聲明:本人第一次配置的時候也是參考了csdn一個作者和github給出的說明配置成功的。其實后來想想很簡單的,但是可能對于初學者,還是有一定的困難。為此&am…

paypal之nodejs 框架 Kraken-js 源碼分析

本文是基于 kraken-js 0.6.1 版本的 關于如何使用kraken-js 可以去看看官網的使用文檔 點擊這里 。kraken-js 是基于express之上的,目的在于讓工程師更多的去關注代碼邏輯,少關注自身的開發環境,所以他將express所有的一些公用的配置都寫在了…

go build 參數_Go語言 通過go bulid -tags 實現編譯控制

Go語言提供的build tag 條件編譯特性,顧名思義,只有在特定條件下才會構建對應的代碼。比如下面的源文件只有在設置debug構建標志時才會被構建:// build debugpackage mainvar buildMode "debug"可以用以下命令構建:go …

selinux 的管理

第十單元selinux 的管理一 顯示及更改 SELINUX 模式getenforce ###顯示selinux模式setenforce 0|1 ##0指permissive警告,1 表示 enforcing強制###vim /etc/sysconfig/selinux ###修改selinux開機狀態###注:disable表示關閉&…

ubuntu15.10下安裝opencv2.4.9python上調用opencv庫

對于centos,可以參考:Install OpenCV-Python in Fedora 如果IPP難以下載可以在cmake時禁掉它,只需:cmake -DWITH_IPPOFF OpenCV3.3CUDA9.0 安裝過程中遇到的問題,解析: https://blog.csdn.net/u014613745/a…

【轉】jquery 注冊事件的方法

原文鏈接:http://outofmemory.cn/code-snippet/2123/jquery-zhuce-event-method 1.使用事件名來綁定,可用的事件名有 change,click,dblclick,error,focus,focusin,focusout,keydown,keypress,keyup,mousedown,mouseenter,mouseleave,mousemove,mouseout,…

ffmpeg 時間戳

轉http://blog.csdn.net/yfh1985sdq/article/details/5721953 AVpacket里的時間戳pts和dts.單位好像是us. 問 : 時間戳pts和dts,這里兩個時間戳各有什么意義? 答 : 顯示時間,解碼時間. DTS:decoding time stamp PTS:presentation time stamp Generally …

鍵盤改鍵軟件_一秒五鍵,一鍵三招,萬種光污染,杜伽K310櫻桃軸機械鍵盤感受...

機械鍵盤我一直用的青軸,或者各種其他名字但其實本質就是青軸的。喜歡青軸那種清脆的聲音,在我聽來如同山間小溪流水般的叮咚。不過這聲音在夜間分外的具有穿透力,更會在人身體不好的時候難以承受,所以每每用過之后卻又不得不換回…

ubuntu 15.10下cmake 的安裝

因為原先ubuntu自帶的cmake有點舊,就想著安裝個最新的,可是直接安裝卡在了某一步上,后面有說明。現將正確的安裝方法列出來。1.卸載原有的版本sudo apt-get autoremove cmake2. 下載最新的cmake :https://cmake.org/download/3. 解壓&#xf…

codeigniter鉤子的使用

CodeIgniter 的鉤子功能,使得我們可以在不修改系統核心文件的基礎上,來改變或增加系統的核心運行功能。可是鉤子究竟該怎么用呢?雖然不是很難,不過很多剛用ci的朋友可能還是不明白怎么用。 通過本文的簡單實例,大家一下…

wxWidgets之wxGrid控件

1. 介紹wxGrid控件時wxWidgets界面庫中內置的網格控件。通經常使用來顯示表格數據。該控件擁有強大的功能。開發人員可依據自己的需求對其進行定制。 2. 經常使用API 構造函數:wxGrid ()wxGrid (wxWindow *parent, wxWindowID id, const wxPoint &poswxDef…

powerdesigner畫關系圖_想畫好手繪,這些圖你一定要畫一下!

畫好手繪除了對透視要深入了解掌握以及線條運用把握之外,還有很重要的就是要對空間物體的關系、比例、光影關系都要理解透徹。大體快可分割成多個x小體塊。其實當年學習的繪畫基礎也是畫好手繪的基礎,畫手繪依然需要去理解整體畫面的空間黑白灰、物體穿插…

C#,pdf文件轉換成圖片文件。

本文采用Adobe Acrobat9.0的COM組件,將Pdf文件的每一頁轉換成對應的圖片文件。 開發環境:VS2010,.Net Framework4.0,Adobe Acrobat9.0。 工程中添加COM引用:Adobe Acrobat 9.0 Type Library(必須裝了Adobe …

Android進程間通信

一.Linux系統進程間通信有哪些方式? 1.socket; 2.name pipe命名管道; 3.message queue消息隊列; 4.singal信號量; 5.share memory共享內存; 二.Java系統的通信方式是什么? 1.socket; 2.name pip…

最新的一些開源face alignment及評價

dlib :https://github.com/davisking/dlib/tree/v18.18 評價:速度快,可商用,有些時候不太準確 2. CLM-framework: https://github.com/TadasBaltrusaitis/CLM-framework 評價:很準確,不可商用 3. Face Detection…