Python 데코레이터의 일반적인 용도는 무엇입니까?
나는 내가 꽤 유능한 Python 코더라고 생각하는 것을 좋아하지만, 내가 여태껏 이해하지 못했던 언어의 한 측면은 데코레이터이다.
나는 그것들이 무엇인지 알고 있다.나는 Stack Overflow에 대한 튜토리얼, 예시, 질문을 읽고 구문을 이해한다.그리고 가끔 @class method와 @static method를 사용할 수 있다.그러나 내 Python 코드의 문제를 해결하기 위해 데코레이터를 사용하는 것은 결코 생각하지 않는다."음...이거 데코레이터가 할 일 같은데!"라고 생각하는 문제는 한 번도 마주치지 않아요.
그래서, 여러분이 자신의 프로그램에서 데코레이터를 사용한 몇 가지 예를 들어주실 수 있는지 궁금합니다. 그리고 제가 "아하!"하는 순간을 가져서 그것들을 얻었으면 좋겠습니다.
나는 주로 타이밍을 맞추기 위해 데코레이터를 사용한다.
def time_dec(func):
def wrapper(*arg):
t = time.clock()
res = func(*arg)
print func.func_name, time.clock()-t
return res
return wrapper
@time_dec
def myFunction(n):
...
동기화하는 데 썼어
import functools
def synchronized(lock):
""" Synchronization decorator """
def wrap(f):
@functools.wraps(f)
def newFunction(*args, **kw):
lock.acquire()
try:
return f(*args, **kw)
finally:
lock.release()
return newFunction
return wrap
코멘트에서 지적된 바와 같이 Python 2.5부터 (또는 버전 2.6 이후) 오브젝트와 함께 스테이트먼트를 사용하여 데코레이터의 구현을 단순화할 수 있습니다.
import functools
def synchronized(lock):
""" Synchronization decorator """
def wrap(f):
@functools.wraps(f)
def newFunction(*args, **kw):
with lock:
return f(*args, **kw)
return newFunction
return wrap
그 후, 다음과 같이 사용합니다.
import threading
lock = threading.Lock()
@synchronized(lock)
def do_something():
# etc
@synchronzied(lock)
def do_something_else():
# etc
으로는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★lock.acquire()
lock.release()
이치노
RMI를 통해 Python 메서드에 전달되는 파라미터 타입 체크용 데코레이터를 사용하고 있기 때문에 같은 파라미터 카운트를 반복하는 대신 몇 번이고 예외적으로 mumbo-jumbo를 올립니다.
예를 들어 다음과 같습니다.
def myMethod(ID, name):
if not (myIsType(ID, 'uint') and myIsType(name, 'utf8string')):
raise BlaBlaException() ...
선언합니다.
@accepts(uint, utf8string)
def myMethod(ID, name):
...
★★★★★★★★★★★★★★★★★」accepts()
모든 일을 다 해내죠
데코레이터는 추가 기능으로 투명하게 "랩"하려는 모든 작업에 사용됩니다.
Django는 뷰 기능에서 "로그인 필요" 기능을 래핑하고 필터 기능을 등록하기 위해 사용합니다.
클래스 데코레이터를 사용하여 명명된 로그를 클래스에 추가할 수 있습니다.
기존 클래스나 함수의 동작을 "터치 온"할 수 있는 충분히 일반적인 기능은 장식하기에 적절한 게임입니다.
PEP 318이 지적한 Python-Dev 뉴스그룹에서는, 「기능과 방법을 위한 장식」의 사용 사례에 대해서도 설명합니다.
노드 테스트의 경우 단위 테스트 함수 또는 메서드에 다음과 같은 파라미터 세트를 제공하는 데코레이터를 작성할 수 있습니다.
@parameters(
(2, 4, 6),
(5, 6, 11),
)
def test_add(a, b, expected):
assert a + b == expected
트위스트 라이브러리는 생성기와 결합된 장식기를 사용하여 비동기 함수가 동기화되어 있는 것처럼 착각합니다.예를 들어 다음과 같습니다.
@inlineCallbacks
def asyncf():
doStuff()
yield someAsynchronousCall()
doStuff()
yield someAsynchronousCall()
doStuff()
이를 사용하면 수많은 작은 콜백 함수로 분할된 코드를 하나의 블록으로 자연스럽게 작성할 수 있어 보다 쉽게 이해하고 관리할 수 있습니다.
한 가지 분명한 용도는 물론 로깅입니다.
import functools
def log(logger, level='info'):
def log_decorator(fn):
@functools.wraps(fn)
def wrapper(*a, **kwa):
getattr(logger, level)(fn.__name__)
return fn(*a, **kwa)
return wrapper
return log_decorator
# later that day ...
@log(logging.getLogger('main'), level='warning')
def potentially_dangerous_function(times):
for _ in xrange(times): rockets.get_rocket(NUCLEAR=True).fire()
주로 디버깅(인수 및 결과를 출력하는 함수 주위에 래퍼) 및 검증(인수가 올바른 유형인지, 웹 애플리케이션의 경우 사용자가 특정 메서드를 호출할 수 있는 충분한 권한이 있는지 등)에 사용합니다.
데코레이터는 함수의 특성을 정의하거나 함수의 특성을 변경하는 보일러 플레이트로 사용됩니다. 완전히 다른 함수를 반환하는 것은 가능하지만 직관에 반합니다.다른 반응을 살펴보면, 가장 일반적인 용도 중 하나는 로깅, 프로파일링, 보안 검사 등 다른 프로세스의 범위를 제한하는 것입니다.
CherryPy는 오브젝트 디스패치를 사용하여 URL을 오브젝트에 일치시키고 최종적으로 메서드에 일치시킵니다.그 방법들의 장식가들은 체리파이가 그 방법들을 사용해도 되는지 아닌지를 알려준다.예를 들어, 자습서에서 수정한 내용:
class HelloWorld:
...
def secret(self):
return "You shouldn't be here."
@cherrypy.expose
def index(self):
return "Hello world!"
cherrypy.quickstart(HelloWorld())
스레드 세이프 기능을 만들기 위해 다음과 같은 데코레이터를 사용하고 있습니다.코드를 읽기 쉽게 만듭니다.이는 John Fouhy가 제안한 것과 거의 유사하지만, 한 가지 기능에 대해 작업하고 잠금 객체를 설명할 필요가 없다는 점이 다릅니다.
def threadsafe_function(fn):
"""decorator making sure that the decorated function is thread safe"""
lock = threading.Lock()
def new(*args, **kwargs):
lock.acquire()
try:
r = fn(*args, **kwargs)
except Exception as e:
raise e
finally:
lock.release()
return r
return new
class X:
var = 0
@threadsafe_function
def inc_var(self):
X.var += 1
return X.var
최근에 소셜 네트워킹 웹 어플리케이션 작업을 하면서 그것들을 사용했어요.커뮤니티/그룹의 경우, 저는 새로운 토론을 만들고 특정 그룹의 구성원이 되어야 하는 메시지에 회신할 수 있는 회원 권한을 부여하기로 되어 있었습니다.저는 데코레이터를 .@membership_required
제가 보기엔 그걸 원하는 곳에 둬요
데코레이터를 사용하면 함수 방식 변수를 쉽게 만들 수 있습니다.
def static_var(varname, value):
'''
Decorator to create a static variable for the specified function
@param varname: static variable name
@param value: initial value for the variable
'''
def decorate(func):
setattr(func, varname, value)
return func
return decorate
@static_var("count", 0)
def mainCallCount():
mainCallCount.count += 1
이 데코레이터를 사용하여 파라미터를 수정합니다.
def fill_it(arg):
if isinstance(arg, int):
return "wan" + str(arg)
else:
try:
# number present as string
if str(int(arg)) == arg:
return "wan" + arg
else:
# This should never happened
raise Exception("I dont know this " + arg)
print "What arg?"
except ValueError, e:
return arg
def fill_wanname(func):
def wrapper(arg):
filled = fill_it(arg)
return func(filled)
return wrapper
@fill_wanname
def get_iface_of(wanname):
global __iface_config__
return __iface_config__[wanname]['iface']
일부 함수는 인수 "wann"을 통과해야 하지만 이전 코드에서는 N 또는 N만 통과했습니다.
언급URL : https://stackoverflow.com/questions/489720/what-are-some-common-uses-for-python-decorators
'source' 카테고리의 다른 글
Java 인터페이스 방식을 추상화라고 선언하는 이유는 무엇입니까? (0) | 2022.11.14 |
---|---|
Apache 사용 시 PHP에서 액세스하기 위한 환경 변수 설정 (0) | 2022.11.14 |
쉼표로 구분된 문자열을 json 어레이로 마이그레이션 (0) | 2022.11.14 |
MySQL SELECT만 null 값이 아닙니다. (0) | 2022.11.14 |
모델 데이터 및 동작은 어디에 배치해야 합니까?[tl;dr; 서비스 사용] (0) | 2022.11.14 |