成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

四年完成400萬行Python代碼檢查,甚至順手寫了個編譯器

新聞 前端
本文,Dropbox 公司完整輸出了從項目研究到實踐的 Python 靜態(tài)檢查全過程,以期對各位開發(fā)者有所幫助。

作為 Python 的大用戶之一,Dropbox 公司內(nèi)部聚集了數(shù)百萬行 Python 代碼,動態(tài)類型的存在讓代碼越來越難以理解。因此,公司開始利用 mypy 逐步將代碼轉(zhuǎn)換為靜態(tài)類型。雖然效果得到了充分驗證,但整個過程充滿了各種錯誤和失敗。

本文,Dropbox 公司完整輸出了從項目研究到實踐的 Python 靜態(tài)檢查全過程,以期對各位開發(fā)者有所幫助。

事實上,Python 已經(jīng)成為 Dropbox 公司使用范圍最廣的語言,其廣泛適用于后端服務(wù)與桌面客戶端應(yīng)用程序等(當(dāng)然,Dropbox 公司也在大量使用 Go、TypeScript 以及 Rust 等語言)。在 Dropbox 公司數(shù)以百萬計的 Python 代碼行中,動態(tài)類型的存在讓代碼越來越難以理解,并嚴(yán)重影響生產(chǎn)力水平。為了緩解這一問題,Dropbox 公司一直在利用 mypy 逐步將代碼轉(zhuǎn)換為靜態(tài)類型(順帶一提,mypy 可能是目前 Python 當(dāng)中最流行的獨立類型檢查器,屬于開源項目,其核心開發(fā)團(tuán)隊來自于 Dropbox。)。

截至目前,Dropbox 已經(jīng)在成千上萬個項目當(dāng)中使用 mypy,而且效果都得到了很好地驗證。但對于此次全方位檢查 Python 代碼,Dropbox 仍然抱著忐忑的心情,整個過程也充滿了錯誤與失敗。在今天的文章中,Dropbox 將向大家分享 Python 靜態(tài)檢查之旅——從最早的學(xué)術(shù)研究項目,到現(xiàn)在逐步讓類型檢查與類型提示成為 Python 社區(qū)中眾多開發(fā)人員的常規(guī)操作?,F(xiàn)在,已經(jīng)有多種工具支持類型檢查功能,包括各類 IDE 與代碼分析器等。

為什么要進(jìn)行類型檢查?

如果開發(fā)者只使用過動態(tài)類型的 Python,當(dāng)然有可能對靜態(tài)類型以及 mypy 感到陌生。甚至,不少開發(fā)者就是因為動態(tài)類型而喜歡上 Python,但這事兒在邏輯上就有點莫名其妙。其關(guān)鍵應(yīng)該在于,靜態(tài)類型檢查是實現(xiàn)規(guī)模化的前提:項目越大,需要的靜態(tài)類型就越多。

一旦項目中包含成千上萬行代碼,而且有多位工程師在同時使用,以往開發(fā)經(jīng)驗告訴我們,理解代碼內(nèi)容就成了保障開發(fā)人員工作效率的關(guān)鍵所在。如果沒有類型注釋,基本的代碼作用推理(例如找到函數(shù)的有效參數(shù),或者可能的返回值類型)就會成為一大難題。以下是幾個在缺少類型注釋時,開發(fā)人員難以回答的典型問題: 

  • 這個函數(shù)能返回 None 嗎?
  • 這里的 items 參數(shù)是干什么用的?
  • id 屬性是什么類型:到底是 int、str、抑或是自定義類型?
  • 這個參數(shù)需要的是一份清單、一個元組還是一個組?

只要有了類型注釋,開發(fā)者能夠很輕松地回答這些與代碼片段相關(guān)的問題,例如:

  1. class Resource: 
  2. id: bytes 
  3. ... 
  4. def read_metadata(self, 
  5. items: Sequence[str]) -> Dict[str, MetadataItem]: 
  6. ... 
  • read_metadata 并不會返回 None,因為返回類型不是 Optional[…]
  • items 參數(shù)代表一系列字符串,其不可能隨意迭代。
  • id 屬性為字節(jié)字符串。

在理想情況下,我們當(dāng)然希望把這一切都記錄在文檔中,但擁有從業(yè)經(jīng)驗的開發(fā)者肯定知道沒這么好的事兒。即使存在此類文檔,我們也無法完全信任其中的內(nèi)容——例如內(nèi)容含糊不清或者不夠準(zhǔn)確,因此帶來巨大的誤解空間。對于大型團(tuán)隊或代碼庫,這類問題可能產(chǎn)生巨大的影響:

雖然 Python 在項目早期與中期階段表現(xiàn)良好,但當(dāng)項目發(fā)展到特定階段后,成功的項目與使用 Python 語言的企業(yè)可能面臨一個關(guān)鍵性決定:我們是否需要利用靜態(tài)類型語言重寫所有內(nèi)容? 

類似 mypy 這樣的類型檢查器主要負(fù)責(zé)提供用于類型描述的形式語言,并通過驗證所獲得的類型與實現(xiàn)(以及可能存在的可選項)間的匹配解決這一難題。更具體地講,類型檢查器專門提供經(jīng)過驗證的文檔。

當(dāng)然,除此之外,類型檢查器還可帶來其它助益: 

  • 類型檢查器能夠發(fā)現(xiàn)許多微妙(以及不那么微妙)的 bug。其中的典型例子,就是開發(fā)者忘記處理的 None 值或者其它一些特殊條件。
  • 重構(gòu)更簡單,因為類型檢查器通常能夠準(zhǔn)確告訴我們需要變更的代碼。我們不需要進(jìn)行 100% 全覆蓋測試,這本身也不具備可行性。另外,我們也不需要跟蹤深層堆棧以了解到底出了什么問題。
  • 即使是在大型項目中 ,mypy 也能夠在幾分之一秒內(nèi)完成完整的類型檢查。運行測試通常需要幾十秒或者幾分鐘。類型檢查帶來的快速反饋,能夠幫助開發(fā)者更快實現(xiàn)迭代。這意味著不需要編寫脆弱且難以維護(hù)的單元測試,用以模擬及修復(fù)現(xiàn)有代碼以獲取快速反饋。
  • 以 PyCharm 以及 Visual Studio Code 為代表的 IDE 和編輯器可利用類型注釋實現(xiàn)代碼補(bǔ)全、高亮顯示錯誤并支持更好的定義功能——這里僅列出幾項典型的功能性應(yīng)用。對于一部分程序員而言,這些功能直接決定著他們的生產(chǎn)效率。這類用例不需要獨立的類型檢查工具。當(dāng)然,像 mypy 這樣的獨立工具仍有助于保證注釋與代碼之間的同步。

啟動遷移:性能成為瓶頸

在 Dropbox,我們成立了一個三人小隊,從 2015 年底開始研究 mypy。成員分別是 Guido、Greg Price 以及 David Fisher。從那時起,工作開始快速推進(jìn)。首先,在 mypy 采用面前的最大障礙就是性能。我們一直在將其運行在 CPython 解釋器上,這對于 mypy 這樣的工具來說速度有點不夠用。(作為包含 JIT 編譯器的 Python 替代性方案,PyPy 在這方面也幫不上什么忙。)

幸運的是,我們實現(xiàn)了一系列算法層面的改進(jìn)。我們采用的第一項加速措施就是 增量檢查。 其背后的思路非常簡單:如果模塊的所有依賴關(guān)系都與 mypy 運行前的狀態(tài)毫無區(qū)別,那我們完全可以使用前一次運行的緩存數(shù)據(jù)獲取依賴關(guān)系,意味著只需要類型檢查修改了的文件及其依賴關(guān)系。mypy 則在此基礎(chǔ)上更進(jìn)一步:如果模塊的外部接口沒有改變,mypy 甚至不需要重新檢查導(dǎo)入該模塊的其它模塊。

在對現(xiàn)有代碼進(jìn)行批量注釋時,增量檢查確實非常有用,因為其中往往涉及 mypy 的大量迭代運行,用以處理陸續(xù)插入且逐漸細(xì)化的類型。最初的 mypy 運行仍然相當(dāng)緩慢,這是因為它需要處理大量依賴項。為此,我們實現(xiàn)了遠(yuǎn)程緩存。如果 mypy 檢測到本地緩存可能已經(jīng)過期,mypy 將從集中存儲庫下載整個代碼庫的最新緩存快照。在此之后,它會以下載到的緩存為基礎(chǔ)執(zhí)行增量構(gòu)建。這又進(jìn)一步提高了性能表現(xiàn)。

到 2016 年底,Dropbox 公司已經(jīng)有大約 42 萬行 Python 完成了類型注釋。很多用戶都熱衷于類型檢查,而 mypy 的使用則在 Dropbox 各團(tuán)隊之間迅速傳播。

情況看起來相當(dāng)不錯,但距離真正的成功還有很長的路。我們開始定期進(jìn)行內(nèi)部用戶調(diào)查,借以找出痛點,并確定需要優(yōu)先考慮的工作(這種習(xí)慣直到今天也一直被保持下來)。其中,有兩項請求始終排名最高:更大的類型檢查覆蓋范圍以及更快的 mypy 運行速度。 很明顯,我們的性能與采用提升工作還沒有全部完成。為此,我們還得在這兩項任務(wù)上再多下點力氣。

性能提升方法一:使用 mypy 守護(hù)進(jìn)程

增量構(gòu)建雖然提升了 mypy 的速度,但仍然沒有達(dá)到頂峰。大量增量運行可能需要一分鐘的處理時長。對于任何面對大型 Python 代碼庫的用戶來講,其中的原因相信并不難理解:循環(huán)導(dǎo)入。

我們擁有數(shù)百個模塊,模塊相互間接導(dǎo)入。如果導(dǎo)入周期的任何文件發(fā)生變更,那么 mypy 就必須處理周期中的所有文件,同時還得處理在此周期內(nèi)導(dǎo)入該模塊的所有其它模塊。其中最臭名昭著的循環(huán)就是“糾結(jié)(tangle)”,它給 Dropbox 帶來了很大麻煩。其中一度包含有數(shù)百個模塊,眾多測試級乃至產(chǎn)品級功能都要或直接或間接地將其導(dǎo)入。

我們一直在考慮打理這種糾結(jié)無比的依賴關(guān)系,但卻始終沒有合適的方法著手進(jìn)行。畢竟我們不熟悉的代碼太多了。因此,我們想出了另一個辦法——即使存在這種“糾結(jié)”,我們同樣可以提升 mypy 速度。答案就是,使用 mypy 守護(hù)進(jìn)程。守護(hù)進(jìn)程是一項服務(wù)器進(jìn)程,負(fù)責(zé)執(zhí)行兩項非常重要的工作。

首先,它將關(guān)于整體代碼庫的信息保存在內(nèi)存中,這樣每次 mypy 運行就不再需要加載數(shù)千條與所導(dǎo)入依賴項相對應(yīng)的緩存數(shù)據(jù)。其次,它會跟蹤函數(shù)與其構(gòu)造之間的細(xì)粒度依賴關(guān)系。例如,如果函數(shù) foo 調(diào)用函數(shù) bar,那么就存在一項從 bar 到 foo 的依賴關(guān)系。當(dāng)文件發(fā)生變更時,守護(hù)程序會首先單獨處理已經(jīng)變更的文件;接下來,它會查找該文件中包含的外部可見變更,例如變更的函數(shù)簽名。守護(hù)程序所采用的細(xì)粒度依賴項管理機(jī)制,能夠確保只重新檢查實際變更的那些函數(shù)——換言之,只檢查極少數(shù)函數(shù)。

實現(xiàn)上述目標(biāo)當(dāng)然是個巨大的挑戰(zhàn),因為我們最初的 mypy 實現(xiàn)方案只適合一次處理一個文件。但在實際需求發(fā)生變化之后——例如當(dāng)某個類獲得一個新的基類時,我們必須重新處理大量邊緣情況。經(jīng)過艱苦卓絕的努力與投入,我們成功將大部分增量運行縮短至幾秒鐘。這是一場偉大的勝利,至少在我們當(dāng)事人看來相當(dāng)偉大!

性能提升方法二:將 Python 編譯為 C

配合之前提到的遠(yuǎn)程緩存,mypy 守護(hù)進(jìn)程幾乎完全解決了增量類用例,工程師們只需要對少量文件進(jìn)行迭代變更即可。但是,最差情況下的性能表現(xiàn)仍然遠(yuǎn)未達(dá)到最佳狀態(tài)。進(jìn)行一次徹底的 mypy build 可能需要 15 分鐘,這樣的結(jié)果當(dāng)然無法令人滿意。由于工程師們在不斷編寫新代碼,并在現(xiàn)有代碼當(dāng)中添加類型注釋,因此情況每周都在惡化。我們的用戶渴望獲得更高的性能,而我們也自然不能讓大家失望。

因此,我們決定延續(xù) mypy 立項之初的重要想法——將 Python 編譯為 C。 遺憾的是,Cython(一款現(xiàn)成的 Python 到 C 編譯器)并不能提供任何顯著的加速效果,因此 我們決定從零開始編寫編譯器。 由于 mypy 代碼庫(使用 Python 編寫)已經(jīng)全面完成類型注釋,因此利用這些注釋來加快速度自然是符合邏輯的選擇。我構(gòu)建了一套快速概念驗證原型,其在各類微基準(zhǔn)測試中將性能提升了 10 倍以上。我們的想法是將 Python 模塊編譯為 CPython C 擴(kuò)展模塊,并將類型注釋轉(zhuǎn)換為運行時類型檢查(在運行時中通常被忽略的類型注釋,僅供類型檢查器使用)。我們開始著手將 mypy 實現(xiàn)由 Python 遷移至真正的靜態(tài)類型語言,這恰好與 Python 的遷移思路完全匹配。(這種跨語言遷移正成為新的常態(tài),mypy 最初由 Alore 編寫,但后來則轉(zhuǎn)換為 Java/Python 自定義語法的混合體。)

對 CPython 擴(kuò)展 API 的定位,是保持項目整體可管理性的關(guān)鍵所在。我們不需要實現(xiàn)虛擬機(jī)或者 mypy 所需要的任何庫。此外,我們?nèi)匀豢梢岳靡磺性?Python 生態(tài)系統(tǒng)與工具(例如 pytest),并能夠在開發(fā)期間繼續(xù)使用經(jīng)過解釋的 Python 代碼,從而實現(xiàn)極快的編輯測試周期且不必等待編譯過程。

這款被我們命名為 mypyc 的編譯器(因為它利用 mypy 作為前端來執(zhí)行類型分析)非常成功。總體而言,我們在不使用緩存的前提下實現(xiàn)了大約 4 倍的運行性能提升。mypyc 項目的核心開發(fā)在小團(tuán)隊的推動之下用了大約 4 個月即告完成,團(tuán)隊成員包括 Michael Sullivan、Ivan Levkivskyi、Hugh Han 和我自己。很明顯,這里的工作量遠(yuǎn)少于使用 C++ 或者 Go 完全重寫 mypy,相關(guān)影響也要小得多。我們希望 mypyc 最終能夠被交付至 Dropbox 的其他工程師手上,供他們編譯并加速自己的更多代碼。

在達(dá)成如此出色的性能提升效果的過程中,我們嘗試了不少有趣的性能工程方法。編譯器可以利用快速、低級 C 構(gòu)造實現(xiàn)眾多操作的加速。例如,對某個已編譯函數(shù)的調(diào)用會被翻譯成 C 函數(shù)調(diào)用,而后者要比調(diào)用解釋函數(shù)快得多。另外,某些操作(例如字典查找)仍然會回退至常規(guī)的 CPython C API 調(diào)用,從而略微提升編譯時的調(diào)用速度??偠灾?,我們擺脫了解釋帶來的性能開銷,從而稍稍改善了操作的速度表現(xiàn)。

我們還進(jìn)行了一系列分析工作,希望了解“慢速操作”中的普遍共性。有了這些數(shù)據(jù),我們嘗試調(diào)整 mypyc 為這些操作生成速度更快的 C 代碼,或者利用更快的操作方式重寫相關(guān) Python 代碼(有時候確實沒什么好辦法,只能硬著頭皮重寫)。后者通常要比在編譯器中自動轉(zhuǎn)換容易得多,不過從長遠(yuǎn)來看,我們更傾向于實現(xiàn)自動化轉(zhuǎn)換。但還是要具體問題具體分析,有時候為了以最低的投入獲得更大的性能提升,我們也會抄近路。

實操:檢查 400 萬行代碼

在完成上述工作后,還面臨一個重要挑戰(zhàn)(也是 mypy 用戶調(diào)查中排名第二的重要要求)就是提升類型檢查的覆蓋范圍。 我們嘗試了多種方法以實現(xiàn)這項目標(biāo):從有機(jī)增長,到專注于 mypy 團(tuán)隊的手動調(diào)整,再到靜態(tài)與動態(tài)自動化類型推理等。最后,我們發(fā)現(xiàn)其中并不存在簡單的實現(xiàn)策略,但我們將多種方法結(jié)合起來,從而顯著提高了能夠在代碼庫中實現(xiàn)的快速注釋工作量。

結(jié)果就是,我們在最大的 Python 庫(后端代碼)中的注釋行數(shù)在大約三年之內(nèi)增長至近 400 萬行,這些全都遷移成了靜態(tài)類型代碼。mypy 現(xiàn)在支持多種覆蓋報告,能夠幫助我們輕松跟蹤相關(guān)進(jìn)度。具體來講,我們可以報告各類不夠明確的類型來源——例如在注釋中使用的顯式、未經(jīng)檢查的類型,或者未進(jìn)行類型注釋的已導(dǎo)入第三方庫等。為了在 Dropbox 當(dāng)中改善類型檢查精度,我們還在中央 Python 類型庫中為不少流行的開源庫提供經(jīng)過針對性改進(jìn)的類型定義(即 stub 文件)。

我們實現(xiàn)了(并在后續(xù) PEP 當(dāng)中標(biāo)準(zhǔn)化了)新的類型系統(tǒng),旨在為某些慣用的 Python 模式提供更精確的類型。其中一個典型例子正是 TypeDict,其負(fù)責(zé)提供 JSON 類字典類型。字典當(dāng)中包含一組固定的字符串鍵,各個字符串擁有不同的值類型。我們后續(xù)還將不斷擴(kuò)展這套類型系統(tǒng),同時考慮改進(jìn)對 Python 數(shù)字堆棧的支持能力。

四年完成400万行Python代码检查,甚至顺手写了个编译器

四年完成400万行Python代码检查,甚至顺手写了个编译器

四年完成400万行Python代码检查,甚至顺手写了个编译器

以下是 Dropbox 在提升注釋覆蓋率時,設(shè)定的核心工作要點: 

  • 嚴(yán)格性。逐漸增加了對新代碼的嚴(yán)格要求。我們先從較為簡單的角度入手,要求為原有文件補(bǔ)充注釋。現(xiàn)在,我們則要求在繼續(xù)補(bǔ)充注釋的同時,在新的 Python 文件中使用類型注釋。
  • 覆蓋率報告。我們每周都會向各團(tuán)隊發(fā)送電子郵件報告,旨在統(tǒng)計他們的注釋覆蓋率,并提供關(guān)于最有必要注釋的內(nèi)容的相關(guān)建議。
  • 外展。我們與各團(tuán)隊就 mypy 進(jìn)行交流,以幫助他們快速上手這款新工具。
  • 調(diào)查。我們定期進(jìn)行用戶調(diào)查以找到最重要的痛點,并竭盡全力解決這些問題(甚至可以發(fā)明一種新的語言來加快 mypy 的速度?。?。
  • 性能。我們通過 mypy 守護(hù)程序與 mypyc 改進(jìn)了 mypy 性能(p75 獲得高達(dá) 44 倍的性能提升),從而減少注釋流程中的阻礙,并允許用戶根據(jù)需要擴(kuò)展類型檢查代碼庫的規(guī)模。
  • 編輯器集成。我們?yōu)?Dropbox 內(nèi)部流行的各款編輯器提供了 mypy 運行集成,具體包括 PyCharm、Vim 以及 VS Code 等。這使得注釋迭代變得更輕松,也提升了大家為遺留代碼做注釋的熱情。
  • 靜態(tài)分析。我們編寫了一款利用靜態(tài)分析來推斷函數(shù)簽名的工具。雖然目前它只能處理非常簡單的場景,但仍然幫助我們快速提升了注釋覆蓋范圍。
  • 第三方庫支持。我們的不少代碼都用到了 SQLAlchemy,它使用的很多動態(tài) Python 函數(shù)無法由 PEP 484 類型進(jìn)行直接建模。為此,我們制作了一個 PEP 561 stub 文件包及一款開源 mypy 插件以提供支持。

經(jīng)驗總結(jié) 檢查 400 萬行代碼絕非易事,我們在整個過程中遇到不少挑戰(zhàn),當(dāng)然也犯過錯誤。下面,我想總結(jié)經(jīng)驗教訓(xùn),希望能給大家?guī)韱⑹尽?/p>

文件丟失。 起步之初,我們的 mypy 版本只需處理少量內(nèi)部文件——或者說,從未接觸過 build 之外的一切。在添加第一條注釋時,文件被隱式添加到 build 當(dāng)中。如果從 build 外部的模塊導(dǎo)入任何內(nèi)容,則會獲得 Any 類型的值——而這些值根本就不會被納入檢查范圍。這導(dǎo)致類型分析精度大打折扣,并在遷移早期給我們帶來了不少麻煩。雖然現(xiàn)在已經(jīng)解決了,而且也算是一種典型做法,但在最糟糕的情況下,如果兩個孤立的類型檢查機(jī)制被合并起來,而這兩種機(jī)制之間又互不兼容,那么我們就必須對注釋進(jìn)行大量更改!回想起來,我們應(yīng)該盡早將基礎(chǔ)庫模塊添加到 mypy build 中。

注釋遺留代碼。 在剛剛開始時,我們面對著超過 400 萬行的現(xiàn)有 Python 代碼。很明顯,對如此規(guī)模的代碼進(jìn)行注釋是項浩大的工程。我們編寫了一款名為 PyAnnotate 的工具,它能夠在運行測試的同時收集類型,并根據(jù)類型結(jié)果插入類型注釋——但最終這款工具并沒能得到廣泛采用。理由很簡單:收集類型的速度很慢,而生成的類型通常也需要大量人為調(diào)整。我們也考慮過在每一次 build 測試時對一小部分實時網(wǎng)絡(luò)請求自動運行這款工具,但考慮到這兩種方式都可能帶來較大風(fēng)險,最終只能作罷。

大多數(shù)代碼都是由代碼所有者手動注釋。 我們提供關(guān)于高價值模塊與函數(shù)的報告,以幫助簡化注釋流程。那些在數(shù)百個位置使用的庫模塊,自然是注釋工作中的優(yōu)先考量對象;正在被替換的遺留服務(wù)同樣值得關(guān)注。此外,我們還嘗試?yán)渺o態(tài)分析為遺留代碼生成靜態(tài)注釋。

導(dǎo)入周期。 導(dǎo)入周期(也就是「tangle」或者說糾結(jié)周期)的存在令 mypy 提速變得非常困難。我們還需要努力讓 mypy 支持來自導(dǎo)入周期的各種習(xí)慣。我們最近剛剛完成了一個重大項目的重新設(shè)計,最終解決了大多數(shù)導(dǎo)入周期問題。這些解決方案實際上源自項目早期研究中使用的 Alore 語言。Alore 的語法使得導(dǎo)入周期的處理變得更輕松。當(dāng)然,我們也在這種簡單的實現(xiàn)中繼承了某些限制因素(對 Alore 來說倒不是什么問題)。Python 之所以很難搞定導(dǎo)入周期,是因為其語句當(dāng)中可能指代多種事物。例如,賦值可能實際上定義了一個類型別名,而且 mypy 在大部分導(dǎo)入周期處理完成之后一直無法檢測到該類型。Alore 就不存在這種模糊性??傊?,有些早期設(shè)計中不經(jīng)意做出的決定,很可能成為多年之后的痛苦根源!

結(jié)束語

從早期原型設(shè)計到如今對 400 萬行代碼進(jìn)行類型檢查,這是一段漫長的旅程。在過程當(dāng)中,我們對 Python 的類型提示進(jìn)行了標(biāo)準(zhǔn)化,建立起圍繞 Python 類型檢查發(fā)展出的新興生態(tài)系統(tǒng)、為 IDE 與編輯器開發(fā)出類型提示支持機(jī)制,在多種類型檢查器之間進(jìn)行功能權(quán)衡并實現(xiàn)了庫支持能力。

雖然在 Dropbox 公司內(nèi)部,類型檢查已經(jīng)被視為一項必要工作,但我相信就整個社區(qū)而言,對 Python 代碼進(jìn)行類型檢查仍是種新生事物。當(dāng)然,我也堅信這種好習(xí)慣將不斷推廣并給更多人帶來助益。如果大家還沒有在自己的大型 Python 項目中使用類型檢查,那么現(xiàn)在就是最好的時機(jī)——根據(jù)我的交流整理,所有嘗試類型檢查的開發(fā)者都后悔沒有早點參與??偠灾愋蜋z查正幫助 Python 成長為一款更適合大型項目的出色語言。

原文鏈接:https://blogs.dropbox.com/tech/2019/09/our-journey-to-type-checking-4-million-lines-of-python/ 

 

責(zé)任編輯:張燕妮 來源: AI前線
相關(guān)推薦

2017-03-23 14:07:55

代碼程序員

2021-03-02 13:56:24

Linux 5.12代碼驅(qū)動

2019-01-03 09:29:15

Linux 系統(tǒng) 數(shù)據(jù)

2020-04-02 15:39:51

代碼編譯器前端

2012-07-23 09:58:50

代碼程序員

2020-02-24 16:27:19

開源大數(shù)據(jù)計算引擎

2009-07-21 08:44:14

微軟Linux內(nèi)核開源操作系統(tǒng)

2018-06-07 16:20:56

代碼代碼質(zhì)量程序員

2022-09-05 10:03:55

MypyPython代碼

2015-09-01 16:26:18

Linux內(nèi)核

2020-05-27 14:10:50

代碼開發(fā)工具

2010-01-11 15:47:37

C++編譯

2023-08-31 11:13:51

物聯(lián)網(wǎng)IOT

2023-08-28 10:28:18

5G物聯(lián)網(wǎng)

2009-08-20 16:34:50

Linux源代碼紅帽Linux內(nèi)核

2011-05-03 09:10:12

項目管理程序員

2024-03-13 15:48:43

2009-07-21 08:51:33

微軟發(fā)布Linux設(shè)備微軟開源虛擬化

2012-04-05 09:13:17

C代碼

2018-10-15 09:20:08

代碼軟件工程師
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 天堂一区二区三区 | 日本中文字幕日韩精品免费 | 国产精品一区三区 | 国产精品欧美精品 | 欧美日韩亚洲国产 | 成人av电影网 | 欧美精品日韩精品 | 一区二区三区回区在观看免费视频 | 国产精品入口 | 中文一区二区视频 | 日本在线视频一区二区 | 亚洲视频免费在线观看 | 一区二区三区福利视频 | 国产电影一区二区三区爱妃记 | 一区二区精品 | 视频一区 国产精品 | 久热电影 | 国产视频久 | 一区影视 | 成人欧美一区二区三区在线观看 | 成人在线视频观看 | 国产精品99视频 | 99re国产 | 国产精品久久 | 91国内精精品久久久久久婷婷 | 中文日韩在线视频 | 欧美日韩精品一区二区三区蜜桃 | 在线日韩 | aaa精品| 亚洲性人人天天夜夜摸 | 欧美日韩成人影院 | 伊人看片| 久热久| 99国产精品久久久久久久 | 九七午夜剧场福利写真 | 亚洲精品久久久久久一区二区 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 亚洲精品视频在线看 | 日日草夜夜草 | 福利网站导航 | 国产精品1区2区3区 欧美 中文字幕 |