當前位置:
首頁 > 知識 > Python3.7中一種懶載入的方式

Python3.7中一種懶載入的方式

Python3.7中一種懶載入的方式

Python部落組織翻譯,歡迎轉發,禁止轉載

注意:這篇博文中的代碼,現在已經是PyPI上modutil模塊的一部分了。

Python3.7在模塊上也添加了__getattr__和__dir__兩個方法。這個新特性讓我們能夠實現一些有趣的事情。例如,通過定義__dir__方法,你可以要求dir(模塊)只顯示__all__中定義的內容了。

但對於我來說,我更關心__getattr__方法,以及我如何能利用這個特性實現懶載入。在本文的開始,我希望先告訴大家,大多數人的代碼是不需要懶載入的。只有當懶載入帶來的好處很有用時你才應該使用它,比如,一個運行時間很短的終端程序。對於大多數人,懶載入都是沒有必要的,甚至是有害的,它會讓你延後得知導入失敗,而不是項目一啟動時就能夠知道。

舊方法

之前我們有兩種方式做懶載入。最古老的方式是在局部載入,而不是全局載入(例如在你定義的函數內進行導入,而不是在模塊頂部進行導入)。這種方式確實推遲了載入的時間點,在你的函數被運行時,函數里的import語句才會進行真正的載入。但它有一個缺點就是,這個import語句需要在不同的函數中寫很多次。而且由於你只是在一些函數中寫了import語句,你很可能寫著寫著就忘記了想要規避哪個模塊的全局引用,然後後面又不小心全局引用了同樣的模塊。這個做法確實能實現懶載入,就是寫法不夠好。

另一種方法是使用importlib中提供的延遲載入器。Google、Facebook和Mercurial的很多開發者在使用這個延遲載入器。Google和Facebook主要是看中這個方法性能不錯,Mercurial主要是看中這個方法比較簡單、開發迅速。使用這個延遲載入器有一個很好的效果,它會提前檢查要導入的模塊是否能找到,如果找不到會拋出一個ModuleNotFoundError錯誤,而真正被延遲的只是模塊載入的過程。

很多人很喜歡這個延遲載入器,以至於他們讓所有的東西都延遲載入了。這樣做有優點也有缺點。優點是你沒有額外付出什麼努力,就讓所有的模塊都延遲載入了。缺點是因為你讓模塊默認延遲載入了,會導致一些需要即時載入的模塊的邏輯發生錯誤(這也就是Python箴言中為什麼說明確優於隱晦)。事實上,Mercurial為了避免這個問題,專門維護了一個模塊黑名單,黑名單上的模塊不進行延遲載入。但為此,他們不得不一直維護這個名單,所以這樣做也不是一個很好的辦法。

新方法

在Python3.7中,模塊上可以定義一個__getattr__方法,這讓開發者可以定義一個函數,使得訪問的模塊屬性不存在時,導入一個模塊作為當前模塊的屬性。這樣做確實也有「發現導入錯誤被推遲」這個弊病,但是由於你的導入還是全局的,所以代碼更容易控制。

這個代碼本身並不複雜。

Python3.7中一種懶載入的方式

你可以這樣使用上面的代碼

Python3.7中一種懶載入的方式

設計這個函數時,最棘手的部分就是模擬import ... as ... 語法來避免命名衝突,我最終選擇使用一個類似原有as語法的字元串。我也可以把as語法字元串再拆分為第三個參數,這個參數也是一個字典對象,但是我想沒必要這樣做,能與原有語法有更多的相同點,當然是最好的。

無論如何,這個思考的過程都讓我很享受。我喜歡這種用20行Python代碼就完成一個不錯的功能的感覺!

譯者:詩書塞外

英文原文:https://snarky.ca/lazy-importing-in-python-3-7/

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

心裡苦:61%的「入門級」工作要求三年以上工作經驗
Python的10大集成開發環境和代碼編輯器(指南)

TAG:Python部落 |