[python] 파이썬 데코레이터의 일반적인 용도는 무엇입니까? [닫은]

필자는 자신을 합리적으로 유능한 Python 코더로 생각하고 싶지만, 결코 그런 적이 없었던 언어의 한 측면은 데코레이터입니다.

나는 그들이 무엇인지 (피상적으로) 알고, 스택 오버플로에 대한 자습서, 예제, 질문을 읽었으며 구문을 이해하고 내 자신을 작성할 수 있으며 때로는 @classmethod 및 @staticmethod를 사용할 수 있지만 내 자신의 파이썬 코드에서 문제를 해결하는 데코레이터. “흠 … 이것은 데코레이터의 직업처럼 보입니다!”

여러분의 프로그램에서 데코레이터를 어디에서 사용했는지에 대한 예제를 제공 할 수 있을지 궁금합니다. “A-ha!” 순간과 그들을 얻을 .



답변

나는 주로 타이밍 목적으로 데코레이터를 사용합니다.

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 이후) 객체 with와 함께 명령문 을 사용하여 데코레이터의 구현을 다음과 같이 단순화 할 수 있습니다.threading.Lockmultiprocessing.Lock

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 메서드에 전달되는 형식 검사 매개 변수에 데코레이터를 사용합니다. 따라서 동일한 매개 변수 계산을 반복하는 대신 예외 발생 점보 점보를 반복해서 반복합니다.

예를 들어,

def myMethod(ID, name):
    if not (myIsType(ID, 'uint') and myIsType(name, 'utf8string')):
        raise BlaBlaException() ...

나는 단지 선언한다 :

@accepts(uint, utf8string)
def myMethod(ID, name):
    ...

그리고 accepts()나를 위해 모든 작업을 수행합니다.


답변

데코레이터는 추가 기능으로 투명하게 “포장”하려는 모든 용도로 사용됩니다.

Django는이 기능을 사용하여 뷰 기능 에서 “로그인 필요”기능 을 래핑하고 필터 기능등록합니다 .

클래스 데코레이터를 사용 하여 명명 된 로그를 클래스추가 할 수 있습니다 .

기존 클래스 또는 함수의 동작에 “고착”할 수있는 충분히 일반적인 기능은 장식용 게임입니다.

Python-Dev 뉴스 그룹 에서 PEP 318-함수 및 메소드 데코레이터 (Decoators for Functions and Methods)가 지적한 유스 케이스에 대한 토론도 있습니다 .


답변

노즈 테스트의 경우 몇 가지 매개 변수 세트로 단위 테스트 기능 또는 방법을 제공하는 데코레이터를 작성할 수 있습니다.

@parameters(
   (2, 4, 6),
   (5, 6, 11),
)
def test_add(a, b, expected):
    assert a + b == expected


답변

Twisted 라이브러리는 생성기와 결합 된 데코레이터를 사용하여 비동기 기능이 동기 적이라는 착각을줍니다. 예를 들면 다음과 같습니다.

@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()