source

Python 데코레이터의 일반적인 용도는 무엇입니까?

nicesource 2022. 11. 14. 21:36
반응형

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

반응형