分享幾個冷門 Python 技巧

整理字符串輸入

對用戶輸入進行整理的問題幾乎適用於你編寫的所有程序。通常情況下,將字符轉換爲小寫或大寫就足夠了,有時你可以使用 Regex 來完成這項工作,但對於複雜的情況來說,可能有更好的方法:

在本例中,你可以看到空白字符 “\n” 和“\t”已被單個空格替換,而 “\r” 已被完全刪除。這是一個簡單的例子,但是我們可以更進一步,使用 unicodedata 包和它的 combining()函數來生成並進行映射,從而生成更大的重新映射表,我們可以使用它來刪除字符串中的所有重音符(注:英文中的'符號)。

對迭代器進行切片

如果你嘗試對一個迭代器進行切片,你會得到一個 TypeError,這說明生成器對象是不可下標訪問的,但有一個簡單的解決方案可以解決這個問題:

使用 itertools.islice 我們可以創建一個 islice 對象,它是一個會生成所需項的迭代器。需要注意的是,這將消耗 slice 開始之前的所有生成器項,以及 islice 對象中的所有項。

跳過可迭代對象的開始部分

有時你必須處理那些以你不想要的可變數量的行 (如註釋) 開始的文件。itertools 再次爲這個問題提供了簡單的解決方案:

這代碼段只生成初始註釋部分之後的行。如果我們只想在可迭代對象的開頭跳過一些循環(這裏是跳過開頭的行),並且不知道具體有多少時,那麼這種方法是很有用的。

只帶有關鍵字參數 (kwargs) 的函數

在使用以下這樣的函數時,創建只接受關鍵字參數的函數來(強制)提供更多的清晰性是很有幫助的:

正如你所看到的,這可以通過在關鍵字參數之前放置單個 * 參數來輕鬆解決。如果我們把位置參數放在 * 參數之前,位置參數顯然也會存在。

創建支持 with 語句的對象

例如,我們都知道如何使用 with 語句來打開文件或獲取鎖,但是我們可以實現自己的 with 語句嗎? 當然,我們可以使用__enter__和__exit__方法來實現上下文管理協議:

這是在 Python 中實現上下文管理最常見的方法,但是還有更簡單的實現方法:

上面的代碼片段使用 contextmanager 管理器裝飾器實現了內容管理協議。在進入 with 塊時,tag 函數 (在 yield 之前) 的第一部分會被執行,然後該 with 塊被執行,最後,tag 函數的其餘部分會被執行。

使用__slots__節省內存

如果你曾經編寫過一個創建某個類的大量實例的程序,你可能會注意到你的程序會突然需要大量內存。這是因爲 Python 使用字典來表示類實例的屬性,這使得它的速度很快,但是內存效率不高,這通常並不是一個問題。然而,如果它成爲你的程序的一個問題時,你可以嘗試使用__slots__:

這裏的情況是,當我們定義了__slots__屬性時,Python 會使用小的固定大小的數組而不是字典來定義屬性,這大大減少了每個實例所需的內存。使用__slots__也有一些缺點——我們不能聲明任何新的屬性,並且我們只能使用在__slots__上這些屬性。而且,帶有__slots__的類不能使用多重繼承。

限制 CPU 和內存的使用

如果你不想優化你的程序內存或 CPU 使用,你只想把它限制在某個固定大小的內存上,那麼 Python 也有一個這樣的庫來做到這一點:

這裏我們可以看到設置最大 CPU 運行時間和最大內存使用限制的兩個選項。對於 CPU 限制,我們首先獲取特定資源 (RLIMIT_CPU) 的軟限制和硬限制,然後使用參數指定的秒數和前面檢索到的硬限制來設置它。最後,我們註冊信號,如果 CPU 時間超過限制,該信號會導致系統退出。對於內存,我們再次檢索軟限制和硬限制,並使用帶有大小參數的 setrlimit 和檢索的硬限制來設置它。

控制什麼可以導入,什麼不可以導入

一些語言有非常明顯的導出成員 (變量、方法、接口) 的控制機制,例如 Golang,其中只有以大寫字母開頭的成員會被導出。另一方面,在 Python 中,所有東西都可以被導出,除非我們使用__all__:

根據上面的代碼片段,我們知道只有 bar 函數會被導出。同樣,我們可以讓__all__爲空,這樣,當我們從這個模塊導入的時候,任何東西都不會被導出,並且會導致 AttributeError。

實現比較運算符的簡單方式

考慮到目前已經有相當多的比較操作符——ltlegt  或 ge_,因此,爲一個類實現所有的比較操作符是相當煩人的。但如果有更簡單的方法可以實現呢?functools.total_ordering 就派上用場了:

那麼,這到底是怎麼工作的呢?total_ordering 裝飾器用於簡化實現類實例排序的過程。我們只需要定義__lt__和__eq__,它們是剩餘操作的映射所需的最小值,裝飾器就會爲我們填充空白。

結論

並不是所有這些特性在日常的 Python 編程中都是必需和有用的,但是它們中的一些可能會在某個時刻派上用場,而且它們還可能會簡化那些非常冗長和難以實現的任務。所有這些特性都是 Python 標準庫的一部分,雖然其中的一些看起來不是那麼 “標準”。所以當你想用 Python 實現某種功能時,不妨先去標準庫裏找找看。(即使標準庫裏沒找到,那大概率也會有第三方庫提供。)

英文原文:https://martinheinz.dev/blog/1

作者:Martin Heinz
譯者:測

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ARYvHfSK7fmdwdbJ9ExrzQ