다음은 함수 호출 횟수(10초에 한 번 호출)를 제한하는 Python 데코레이터 방법입니다. 좋은 참고 값이 있으며 모든 사람에게 도움이 되기를 바랍니다. 함께 살펴볼까요
최근 한 대기업 블로거의 인터뷰 질문입니다. 함수가 10초에 한 번씩 호출되도록 제한하는 데코레이터를 작성해 보세요. 당시에는 필기시험이었고, 대략적인 코드만 작성하고 돌아와서 파이썬 데코레이터에 대한 기본 지식을 복습하고 코드 작성을 마쳤습니다. 그것을 기록하기 위해 블로그를 쓰기로 결정했습니다.
데코레이터는 매개변수가 있는 데코레이터와 매개변수가 없는 데코레이터로 구분됩니다.
#不带参数的装饰器 @dec1 @dec2 def func(): ... #这个函数声明等价于 func = dec1(dec2(func)) #带参数的装饰器 @dec(some_args) def func(): ... #这个函数声明等价于 func = dec(some_args)(func)
매개변수가 없는 데코레이터에 대해 주의할 사항
1. 데코레이터 함수(데코레이터) 자체에 대해
그래서 데코레이터는 일반적으로 두 가지 기능에 해당합니다. 하나는 데코레이터입니다. 일부 초기화 작업을 수행합니다. 하나는 장식된 함수 func의 추가 처리를 구현하는 데 사용되는 Decorated_func입니다. 그리고 func에 대한 참조를 유지하기 위해 Decorator_func는 일반적으로 데코레이터의 내부 함수로 사용됩니다
def decorator(func): def decorator_func() func() return decorated_func
데코레이터 함수는 함수가 선언될 때 한 번만 호출됩니다
데코레이터는 실제로 구문 설탕이며 함수가 호출된 후에 호출되고, Decorated_func를 생성하고, func 기호에 대한 참조를 Decorated_func로 바꿉니다. 그 후 func 함수가 호출될 때마다 실제로 Decorated_func가 호출됩니다(이것은 매우 중요합니다. 장식 후에는 실제로 매번 Decorated_func가 호출됩니다).
>>> 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'
반환된 Decorator_func의 함수 이름이 func의 함수 이름과 동일한지 확인하려면 데코레이터 함수가 Decorated_func를 반환하기 전에 Decorator_func.name = func.name을 추가해야 합니다. functools 모듈은 이 작업을 완료할 수 있는 Wraps 데코레이터를 제공합니다.
#@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'
데코레이터 함수의 지역 변수를 훌륭하게 사용
클로저의 특성으로 인해(클로저 부분에 대한 자세한 내용은 (1) 참조) 데코레이터가 선언하는 변수는 다음과 같습니다. Decorator 메소드가 종료된 후에는 Decorator 메소드의 지역 변수가 재활용되지 않으므로, Decorator 메소드의 지역 변수를 카운터, 캐시 등으로 사용할 수 있습니다.
변수의 값을 변경하려면 변수가 가변 객체여야 하므로 카운터도 목록으로 구현해야 한다는 점에 유의할 필요가 있습니다. 그리고 함수가 데코레이터 함수를 한 번 호출하여 서로 다른 함수의 카운터가 서로 충돌하지 않도록 선언합니다. 예를 들어:
#!/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
코드 작성을 시작해 보겠습니다.
#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'
우리는 그냥 아무렇지도 않게 테스트했습니다. 기본적으로는 문제가 없습니다.
>>> 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
관련 권장 사항:
위 내용은 python 데코레이터 - 함수 호출 수를 제한하는 방법(10초마다 한 번씩 호출)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!