遇到乙個記憶體洩露的問題,除錯了很久發現是快取裝飾器的鍋。
環境:python3.8
有這樣乙個用作快取的裝飾器,示例**如下:
# cache.py
import time
import random
import functools
class cache(object):
"""這是乙個裝飾器,我也是第一次看到這麼寫的裝飾器"""
def __init__(self, func):
self.func = func
self.data = {}
def __call__(self, *args):
if args in self.data:
return self.data[args]
value = self.func(*args)
self._set_cache(value, *args)
return value
def _set_cache(self, value, *args):
self.data[args] = value
def __get__(self, obj, objtype):
func = functools.partial(self.__call__, obj)
return func
測試demo如下:
from .cache import cache
class fish(object):
def __init__(self):
pass
@cache
def get(self, n):
return "-".join([str(int(time.time())), str(n)])
fish = fish()
print(fish.get(3))
time.sleep(1)
print(fish.get(3))
time.sleep(1)
print(fish.get(3))
輸出結果:
1602759443-3
1602759443-3
1602759443-3
可以看到最後輸出的結果是一樣的,說明裝飾器的快取起作用了。
裝飾器物件的建立是在建立fish類get方法的時候,而不是在建立fish物件的時候。所以快取在程式執行期間會一直存在,不會隨著物件的刪除而消失。在web程式中這會有問題,每次請求的資料都會被快取儲存,導致記憶體不斷增大。
實際上裝飾器在python直譯器建立函式物件的時候就會執行,示例**如下:
class dec1(object):
def __init__(self, func):
print("dec1")
self.func = func
def __call__(self, *args):
print("call func...")
return self.func(*args)
def dec2(func):
print("dec2")
return func(*args, **kwargs)
@dec1
def f1():
pass
@dec1
def f2():
pass
@dec2
def f3():
pass
if __name__ == "__main__":
pass
輸出結果:
dec1
dec1
dec2
雖然我們的程式中沒有執行任何東西,但可以看到裝飾器內的**還是執行了。在建立f1/f2/f3 這些函式物件時,裝飾器就被執行了。
python裝飾器 Python 裝飾器
簡言之,python裝飾器就是用於拓展原來函式功能的一種函式,這個函式的特殊之處在於它的返回值也是乙個函式,使用python裝飾器的好處就是在不用更改原函式的 前提下給函式增加新的功能。一般而言,我們要想拓展原來函式 最直接的辦法就是侵入 裡面修改,例如 這是我們最原始的的乙個函式,然後我們試圖記錄...
python裝飾器原理 Python裝飾器原理
裝飾器 decorator 是物件導向設計模式的一種,這種模式的核心思想是在不改變原來核心業務邏輯 的情況下,對函式或類物件進行額外的修飾。python中的裝飾器由python直譯器直接支援,其定義形式如下 decorator def core service 要理解上述 的含義,我們從自定義函式裝...
python裝飾器作用 python裝飾器有什麼用
簡言之,python裝飾器就是用於拓展原來函式功能的一種函式,這個函式的特殊之處在於它的返回值也是乙個函式,使用python裝飾器的好處就是在不用更改原函式的 前提下給函式增加新的功能。一般而言,我們要想拓展原來函式 最直接的辦法就是侵入 裡面修改,例如 import time def func p...