python裝飾器 Python奇怪的裝飾器

2021-10-11 19:51:11 字數 1992 閱讀 8557

遇到乙個記憶體洩露的問題,除錯了很久發現是快取裝飾器的鍋。

環境: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...