Maison >développement back-end >Tutoriel Python >python decorator - une méthode pour limiter le nombre d'appels de fonction (appel une fois toutes les 10 secondes)
Ce qui suit est un décorateur python - une méthode pour limiter le nombre d'appels de fonction (appel une fois toutes les 10 secondes). Il a une bonne valeur de référence et j'espère qu'il sera utile à tout le monde. Jetons un coup d'œil ensemble
Il s'agit d'une récente question d'entretien d'un blogueur d'une grande entreprise Écrivez à un décorateur et limitez l'appel de la fonction une fois toutes les 10 secondes. C'était un test écrit à l'époque, et je n'écrivais qu'un code approximatif. Après mon retour, j'ai révisé les connaissances de base des décorateurs Python et j'ai fini d'écrire le code. J'ai décidé d'écrire un blog pour l'enregistrer.
Les décorateurs sont divisés en décorateurs avec paramètres et décorateurs sans paramètres.
#不带参数的装饰器 @dec1 @dec2 def func(): ... #这个函数声明等价于 func = dec1(dec2(func)) #带参数的装饰器 @dec(some_args) def func(): ... #这个函数声明等价于 func = dec(some_args)(func)
Quelques détails à noter sur les décorateurs sans paramètres
1. (décorateur) lui-même
Par conséquent, un décorateur correspond généralement à deux fonctions, l'une est la fonction décorateur, qui est utilisée pour effectuer certaines opérations d'initialisation, et l'autre est décorée_func, qui est utilisée pour implémenter le traitement supplémentaire pour les fonctions décorées func. Et afin de conserver une référence à func, decor_func est généralement utilisée comme fonction interne de decorator
def decorator(func): def decorator_func() func() return decorated_func
La fonction decorator n'est appelée qu'une seule fois lorsque le la fonction est déclarée
Le décorateur est en fait du sucre syntaxique. Il sera appelé après la déclaration de la fonction, générera décoré_func et remplacera la référence du symbole func par décoré_func. Chaque fois que la fonction func est appelée par la suite, decor_func est effectivement appelée (c'est très important, après la décoration, decor_func est en fait appelée à chaque fois).
>>> def decorator(func): ... def decorated_func(): ... func(1) ... return decorated_func ... #声明时就被调用 >>> @decorator ... def func(x): ... print x ... decorator being called #使用func()函数实际上使用的是decorated_func函数 >>> func() 1 >>> func.__name__ 'decorated_func'
Si vous voulez vous assurer que le nom de fonction du décoré_func renvoyé est le même que le nom de la fonction de la fonction, vous devez ajouter décoré_func.name = avant que la fonction décorateur ne renvoie décoré_func. func.name De plus, le module functools fournit le décorateur wraps pour effectuer cette action.
#@wraps(func)的操作相当于 #在return decorated_func之前,执行 #decorated_func.__name__ = func.__name__ #func作为装饰器参数传入, #decorated_func则作为wraps返回的函数的参数传入 >>> def decorator(func): ... @wraps(func) ... def decorated_func(): ... func(1) ... return decorated_func ... #声明时就被调用 >>> @decorator ... def func(x): ... print x ... decorator being called #使用func()函数实际上使用的是decorated_func函数 >>> func() 1 >>> func.__name__ 'func'
La merveilleuse utilisation des variables locales de la fonction décorateur
Parce que des caractéristiques de fermeture (Voir (1) Fermeture Partielle pour plus de détails). Les variables déclarées par le décorateur seront référencées par decor_func.func_closure, donc après l'appel de la méthode décorateur, les variables locales de la méthode décorateur ne seront pas recyclées, vous pouvez donc utiliser les variables locales de la méthode decorator. Les variables font office de compteurs, de caches, etc.
Il convient de noter que si vous souhaitez modifier la valeur d'une variable, la variable doit être un objet mutable, donc même un compteur doit être implémenté avec une liste. Et déclarez que la fonction appelle la fonction décorateur une fois, pour que les compteurs des différentes fonctions n'entrent pas en conflit entre eux, par exemple :
#!/usr/bin/env python #filename decorator.py def decorator(func): #注意这里使用可变对象 a = [0] def decorated_func(*args,**keyargs): func(*args, **keyargs) #因为闭包是浅拷贝,如果是不可变对象,每次调用完成后符号都会被清空,导致错误 a[0] += 1 print "%s have bing called %d times" % (func.__name__, a[0]) return decorated_func @decorator def func(x): print x @decorator def theOtherFunc(x): print x
Commençons à écrire le code :
#coding=UTF-8 #!/usr/bin/env python #filename decorator.py import time from functools import wraps def decorator(func): "cache for function result, which is immutable with fixed arguments" print "initial cache for %s" % func.__name__ cache = {} @wraps(func) def decorated_func(*args,**kwargs): # 函数的名称作为key key = func.__name__ result = None #判断是否存在缓存 if key in cache.keys(): (result, updateTime) = cache[key] #过期时间固定为10秒 if time.time() -updateTime < 10: print "limit call 10s", key result = updateTime else : print "cache expired !!! can call " result = None else: print "no cache for ", key #如果过期,或则没有缓存调用方法 if result is None: result = func(*args, **kwargs) cache[key] = (result, time.time()) return result return decorated_func @decorator def func(x): print 'call func'
Je viens de le tester et il n'y a pratiquement aucun problème.
>>> from decorator import func initial cache for func >>> func(1) no cache for func call func >>> func(1) limit call 10s func 1488082913.239092 >>> func(1) cache expired !!! can call call func >>> func(1) limit call 10s func 1488082923.298204 >>> func(1) cache expired !!! can call call func >>> func(1) limit call 10s func 1488082935.165979 >>> func(1) limit call 10s func 1488082935.165979
Recommandations associées :
Python limite le nombre d'appels de fonction
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!