當某些函數的運算相對複雜時,我們可以隨手補上 functools.lru_cache / functools.cache 來幫函數做快取;但當我們把這個裝飾器放到類別成員上時會觸發 flake8-bugbear 的 B019 報錯,例如:
import functools
class Foo:
@functools.lru_cache()
def bar(self): ...
會產出:
foo.py:5:5: B019 Use of `functools.lru_cache` or `functools.cache` on methods can lead to memory leaks
|
4 | class Foo:
5 |
6 | @functools.lru_cache
| ^^^^^^^^^^^^^^^^^^^^ B019
7 | def bar(self): ...
|
原因是 lru_cache
會需要把當次執行的所有引數紀錄下來、作為鍵來查表;而當我們把它套用在成員函數上時——這會使得 self
也被記錄進去,進而導致快取的儲存空間與該實例產生循環相依,使它們一起跟著彼此活到海枯石爛也不被 GC,然後產生記憶體滲漏的問題。
以上故事在 @anthonywritescode 的影片 don't lru_cache methods! 有相關的示範。