bestsource

매개 변수와 함께 또는 매개 변수 없이 사용할 수 있는 장식기를 만드는 방법은 무엇입니까?

bestsource 2023. 8. 22. 22:18
반응형

매개 변수와 함께 또는 매개 변수 없이 사용할 수 있는 장식기를 만드는 방법은 무엇입니까?

파라미터와 함께 사용할 수 있는 파이썬 데코레이터를 만들고 싶습니다.

@redirect_output("somewhere.log")
def foo():
    ....

또는 출력을 기본적으로 stderr로 리디렉션하지 않는 경우:

@redirect_output
def foo():
    ....

그게 가능할까요?

출력 리디렉션 문제에 대한 다른 해결책을 찾고 있는 것이 아니라 제가 달성하고자 하는 구문의 예일 뿐입니다.

이 질문이 오래된 것은 알지만, 일부 의견은 새로운 것이고, 실행 가능한 모든 해결책이 본질적으로 동일하지만, 대부분은 그다지 깨끗하지 않거나 읽기가 쉽지 않습니다.

Thobe의 대답처럼, 두 사건을 모두 처리하는 유일한 방법은 두 시나리오를 모두 확인하는 것입니다.가장 쉬운 방법은 단순하게 단일 인수가 있고 그것이 callabe인지 확인하는 것입니다(참고: 장식자가 하나의 인수만 사용하고 호출 가능한 개체인 경우 추가 검사가 필요합니다).

def decorator(*args, **kwargs):
    if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
        # called as @decorator
    else:
        # called as @decorator(*args, **kwargs)

첫 번째 경우 일반 장식가가 수행하는 작업을 수행하고 전달된 함수의 수정 또는 랩 버전을 반환합니다.

두 번째 경우에는 *args, **kwargs와 함께 전달된 정보를 어떻게든 사용하는 '새로운' 데코레이터를 반환합니다.

이것은 괜찮지만, 여러분이 만드는 모든 장식가를 위해 그것을 써야 하는 것은 꽤 성가시고 깨끗하지 않을 수 있습니다.대신에, 우리의 장식품을 다시 쓸 필요 없이 자동으로 수정할 수 있다면 좋을 것입니다...하지만 그것이 장식가들이 필요한 이유입니다!

다음과 같은 장식가 장식가를 사용하면 논쟁 없이 사용할 수 있도록 장식가를 타락시킬 수 있습니다.

def doublewrap(f):
    '''
    a decorator decorator, allowing the decorator to be used as:
    @decorator(with, arguments, and=kwargs)
    or
    @decorator
    '''
    @wraps(f)
    def new_dec(*args, **kwargs):
        if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
            # actual decorated function
            return f(args[0])
        else:
            # decorator arguments
            return lambda realf: f(realf, *args, **kwargs)

    return new_dec

이제 우리는 장식가들을 @double wrap으로 장식할 수 있습니다. 그리고 그들은 논쟁을 하거나 논쟁을 하지 않고 다음과 같은 한 가지 주의 사항을 가지고 작업할 것입니다.

위에서 언급했지만 여기서 반복해야 합니다. 이 장식가의 체크는 장식가가 받을 수 있는 인수(즉, 하나의 호출 가능한 인수를 받을 수 없음)에 대한 가정을 합니다.우리는 지금 어떤 발전기에도 적용할 수 있도록 하고 있기 때문에, 그것을 염두에 두거나 모순될 경우 수정할 필요가 있습니다.

다음은 이 기능의 사용을 보여줍니다.

def test_doublewrap():
    from util import doublewrap
    from functools import wraps    

    @doublewrap
    def mult(f, factor=2):
        '''multiply a function's return value'''
        @wraps(f)
        def wrap(*args, **kwargs):
            return factor*f(*args,**kwargs)
        return wrap

    # try normal
    @mult
    def f(x, y):
        return x + y

    # try args
    @mult(3)
    def f2(x, y):
        return x*y

    # try kwargs
    @mult(factor=5)
    def f3(x, y):
        return x - y

    assert f(2,3) == 10
    assert f2(2,5) == 30
    assert f3(8,1) == 5*7

키워드 인수를 기본값(kquinn에서 제안함)과 함께 사용하는 것이 좋지만 괄호를 포함해야 합니다.

@redirect_output()
def foo():
    ...

장식가의 괄호 없이 작동하는 버전을 원할 경우 장식가 코드에 두 시나리오를 모두 설명해야 합니다.

Python 3.0을 사용하는 경우 키워드만 사용할 수 있습니다.

def redirect_output(fn=None,*,destination=None):
  destination = sys.stderr if destination is None else destination
  def wrapper(*args, **kwargs):
    ... # your code here
  if fn is None:
    def decorator(fn):
      return functools.update_wrapper(wrapper, fn)
    return decorator
  else:
    return functools.update_wrapper(wrapper, fn)

Python 2.x에서는 다음과 같은 변수 트릭으로 에뮬레이션할 수 있습니다.

def redirected_output(*fn,**options):
  destination = options.pop('destination', sys.stderr)
  if options:
    raise TypeError("unsupported keyword arguments: %s" % 
                    ",".join(options.keys()))
  def wrapper(*args, **kwargs):
    ... # your code here
  if fn:
    return functools.update_wrapper(wrapper, fn[0])
  else:
    def decorator(fn):
      return functools.update_wrapper(wrapper, fn)
    return decorator

이러한 버전을 사용하면 다음과 같은 코드를 작성할 수 있습니다.

@redirected_output
def foo():
    ...

@redirected_output(destination="somewhere.log")
def bar():
    ...

오래된 질문인 것은 알지만, 제안된 기술 중 어떤 것도 정말 마음에 들지 않아 다른 방법을 추가하고 싶었습니다.저는 장고가 그들의 장식가에서 정말 깨끗한 방법을 사용하는 것을 보았습니다.장식가의 문서에서 볼 수 있듯이, 그것은 단독으로 사용될 수 있습니다.@login_required인수가 경우에는 또는논과함께,@login_required(redirect_field_name='my_redirect_field').

그들이 그것을 하는 방법은 매우 간단합니다.은 가합니다를 합니다.kwarg(function=None논쟁 에서. 그들의 장식가 논쟁 앞에서.한다면, 데레이터단사경우용할로독를으코,function이 될 반면에 만약 이 인수와 , 그이장식있될것다이면불, 반만그논함다려진께쟁과것이약,function▁▁be 될 것입니다.None.

예:

from functools import wraps

def custom_decorator(function=None, some_arg=None, some_other_arg=None):
    def actual_decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            # Do stuff with args here...
            if some_arg:
                print(some_arg)
            if some_other_arg:
                print(some_other_arg)
            return f(*args, **kwargs)
        return wrapper
    if function:
        return actual_decorator(function)
    return actual_decorator

@custom_decorator
def test1():
    print('test1')

>>> test1()
test1

@custom_decorator(some_arg='hello')
def test2():
    print('test2')

>>> test2()
hello
test2

@custom_decorator(some_arg='hello', some_other_arg='world')
def test3():
    print('test3')

>>> test3()
hello
world
test3

저는 장고가 여기서 제안한 다른 기술들보다 더 우아하고 이해하기 쉽도록 사용하는 이 접근법을 발견했습니다.

여기에 있는 몇 가지 답변은 이미 문제를 잘 해결합니다.하지만 스타일과 관련하여, 저는 이 장식가의 곤경을 해결하는 것을 선호합니다.functools.partial데이비드 비즐리의 파이썬 쿡북 3에서 제안된 바와 같이:

from functools import partial, wraps

def decorator(func=None, foo='spam'):
    if func is None:
         return partial(decorator, foo=foo)

    @wraps(func)
    def wrapper(*args, **kwargs):
        # do something with `func` and `foo`, if you're so inclined
        pass
    
    return wrapper

네, 하지만 당신은 그냥 할 수 있습니다.

@decorator()
def f(*args, **kwargs):
    pass

펑키한 해결책이 없다면, 저는 그것이 이상해 보이고, 저는 단순히 장식하는 옵션을 갖는 것을 좋아합니다.@decorator.

2차 임무 목표에 대해서는, 함수의 출력을 리디렉션하는 것이 이 스택 오버플로 게시물에서 다루어집니다.


더 깊이 파고들고 싶다면 온라인에서 무료로 읽을 수 있는 파이썬 쿡북 3의 9장(메타프로그래밍)을 확인하세요.

Beazley의 멋진 YouTube 비디오 Python 3 메타프로그래밍에서 그 자료 중 일부가 라이브 데모(추가로!)되었습니다.

예를 들어 첫 번째 인수의 유형을 사용하여 두 경우를 모두 탐지하고 그에 따라 래퍼(매개 변수 없이 사용되는 경우) 또는 장식자(인수와 함께 사용되는 경우)를 반환해야 합니다.

from functools import wraps
import inspect

def redirect_output(fn_or_output):
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **args):
            # Redirect output
            try:
                return fn(*args, **args)
            finally:
                # Restore output
        return wrapper

    if inspect.isfunction(fn_or_output):
        # Called with no parameter
        return decorator(fn_or_output)
    else:
        # Called with a parameter
        return decorator

@redirect_output("output.log") 구문,redirect_output 인수 단일인호니로 됩니다."output.log"그리고 그것은 논쟁으로 장식될 기능을 수락하는 장식가를 반환해야 합니다. 경우용우로 할 때@redirect_output인수로 장식할 함수와 함께 직접 호출됩니다.

로: 는다른말: 더또.@구문 뒤에는 유일한 인수로 장식될 함수를 받아들이고 장식된 함수를 반환하는 함수가 와야 합니다.식 자체가 함수 호출일 수 있으며, 이는 다음과 같습니다.@redirect_output("output.log")사실입니다:-) 잡하지만사실입다니 :-)

파이썬 장식가는 당신이 그것에 인수를 주는지에 따라 근본적으로 다른 방식으로 불립니다.장식은 실제로 (구문적으로 제한된) 표현일 뿐입니다.

첫 번째 예에서는 다음과 같습니다.

@redirect_output("somewhere.log")
def foo():
    ....

라는 redirect_output인수와 되며, 되며, 그 는 주진인수함호며이는, 반예것며되상으로다자로호, 니출됩그할는체환를수함자, 어장식와되출께,▁is다▁with▁called호로 호출됩니다.foo최종 장식 함수를 반환할 것으로 예상되는 인수로(!).

동등한 코드는 다음과 같습니다.

def foo():
    ....
d = redirect_output("somewhere.log")
foo = d(foo)

두 번째 예제에 해당하는 코드는 다음과 같습니다.

def foo():
    ....
d = redirect_output
foo = d(foo)

따라서 원하는 작업을 수행할 수 있지만 완전히 원활하지는 않습니다.

import types
def redirect_output(arg):
    def decorator(file, f):
        def df(*args, **kwargs):
            print 'redirecting to ', file
            return f(*args, **kwargs)
        return df
    if type(arg) is types.FunctionType:
        return decorator(sys.stderr, arg)
    return lambda f: decorator(arg, f)

이것은 함수를 장식가에 대한 인수로 사용하려는 경우가 아니라면 문제가 없어야 합니다. 이 경우 장식가는 인수가 없다고 잘못 가정합니다.또한 이 장식이 함수 유형을 반환하지 않는 다른 장식에 적용되는 경우에도 실패합니다.

다른 방법은 인수가 없는 경우에도 항상 데코레이터 함수를 호출하도록 요구하는 것입니다.이 경우 두 번째 예는 다음과 같습니다.

@redirect_output()
def foo():
    ....

데코레이터 기능 코드는 다음과 같습니다.

def redirect_output(file = sys.stderr):
    def decorator(file, f):
        def df(*args, **kwargs):
            print 'redirecting to ', file
            return f(*args, **kwargs)
        return df
    return lambda f: decorator(file, f)

다른 답변 작성하기

"논쟁을 할 때나 할 때나 쓸 때나 쓸 때나 쓸 수 있는 장식기를 만들 수 있는 방법이 없을까요?"

아니요, 현재 파이썬 언어에서 두 가지 다른 사용 사례를 감지하기 위한 무언가가 누락되어 있기 때문에 일반적인 방법은 없습니다.

그러나 예와 같은 다른 답변에서 이미 지적했듯이 수신된 첫 번째 위치 인수의 유형과 값을 확인하고 기본값이 아닌 다른 인수가 없는지 확인하는 번거로운 해결 방법이 있습니다.사용자가 장식가의 첫 번째 인수로 호출부호를 전달하지 않을 것으로 보장되는 경우, 이 해결 방법을 사용할 수 있습니다.클래스 장식자도 마찬가지입니다(이전 문장에서 클래스로 호출 가능 대체).

위의 내용을 확인하기 위해 저는 위에서 언급한 모든 전략(그리고 자기 성찰을 포함한 더 많은 전략)의 조합을 사용하여 필요에 따라 "가장 지능적인 해결 방법"을 수행하는 라이브러리를 구현하기도 했습니다.두 가지 모드(네스트 모드와 플랫 모드)가 함께 제공됩니다.

중첩 모드에서는 항상 함수를 반환합니다.

from decopatch import function_decorator

@function_decorator
def add_tag(tag='hi!'):
    """
    Example decorator to add a 'tag' attribute to a function. 
    :param tag: the 'tag' value to set on the decorated function (default 'hi!).
    """
    def _apply_decorator(f):
        """
        This is the method that will be called when `@add_tag` is used on a 
        function `f`. It should return a replacement for `f`.
        """
        setattr(f, 'tag', tag)
        return f
    return _apply_decorator

"플랫 모드"에서 메서드는 데코레이터가 적용될 때 직접 실행되는 코드입니다.장식된 기능 물체가 주입됩니다.f:

from decopatch import function_decorator, DECORATED

@function_decorator
def add_tag(tag='hi!', f=DECORATED):
    """
    Example decorator to add a 'tag' attribute to a function.
    :param tag: the 'tag' value to set on the decorated function (default 'hi!).
    """
    setattr(f, 'tag', tag)
    return f

하지만 솔직히 여기에 어떤 라이브러리도 필요하지 않고 파이썬 언어에서 바로 그 기능을 얻는 것이 가장 좋습니다.저처럼 파이썬 언어가 현재 이 질문에 대한 깔끔한 답변을 제공할 수 없는 것이 안타깝다고 생각한다면 주저하지 말고 파이썬 버그 트래커: https://bugs.python.org/issue36553 에서 이 아이디어를 지원하십시오.

실제로 @bj0 솔루션의 경고 사례는 쉽게 확인할 수 있습니다.

def meta_wrap(decor):
    @functools.wraps(decor)
    def new_decor(*args, **kwargs):
        if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
            # this is the double-decorated f. 
            # Its first argument should not be a callable
            doubled_f = decor(args[0])
            @functools.wraps(doubled_f)
            def checked_doubled_f(*f_args, **f_kwargs):
                if callable(f_args[0]):
                    raise ValueError('meta_wrap failure: '
                                'first positional argument cannot be callable.')
                return doubled_f(*f_args, **f_kwargs)
            return checked_doubled_f 
        else:
            # decorator arguments
            return lambda real_f: decor(real_f, *args, **kwargs)

    return new_decor

은 이 입니다.meta_wrap.

    @meta_wrap
    def baddecor(f, caller=lambda x: -1*x):
        @functools.wraps(f)
        def _f(*args, **kwargs):
            return caller(f(args[0]))
        return _f

    @baddecor  # used without arg: no problem
    def f_call1(x):
        return x + 1
    assert f_call1(5) == -6

    @baddecor(lambda x : 2*x) # bad case
    def f_call2(x):
        return x + 1
    f_call2(5)  # raises ValueError

    # explicit keyword: no problem
    @baddecor(caller=lambda x : 100*x)
    def f_call3(x):
        return x + 1
    assert f_call3(5) == 600

아무도 이것을 언급하지 않았기 때문에, 특히 장식자가 복잡하고 여러 방법(기능)으로 나누고 싶을 수 있는 경우에 더 우아하다고 생각하는 콜 가능 클래스를 활용하는 솔루션도 있습니다.은 이솔션다활다니합용을 활용합니다.__new__본질적으로 다른 사람들이 지적한 것을 하는 마법의 방법.리턴을 적절히 조정하기 전에 먼저 데코레이터가 사용된 방식을 감지합니다.

class decorator_with_arguments(object):

    def __new__(cls, decorated_function=None, **kwargs):

        self = super().__new__(cls)
        self._init(**kwargs)

        if not decorated_function:
            return self
        else:
            return self.__call__(decorated_function)

    def _init(self, arg1="default", arg2="default", arg3="default"):
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3

    def __call__(self, decorated_function):

        def wrapped_f(*args):
            print("Decorator arguments:", self.arg1, self.arg2, self.arg3)
            print("decorated_function arguments:", *args)
            decorated_function(*args)

        return wrapped_f

@decorator_with_arguments(arg1=5)
def sayHello(a1, a2, a3, a4):
    print('sayHello arguments:', a1, a2, a3, a4)

@decorator_with_arguments()
def sayHello(a1, a2, a3, a4):
    print('sayHello arguments:', a1, a2, a3, a4)

@decorator_with_arguments
def sayHello(a1, a2, a3, a4):
    print('sayHello arguments:', a1, a2, a3, a4)

데코레이터가 인수와 함께 사용되는 경우 이는 다음과 같습니다.

result = decorator_with_arguments(arg1=5)(sayHello)(a1, a2, a3, a4)

을 알 수.arg1생성자에게 올바르게 전달되고 장식된 기능이 전달됩니다.__call__

그러나 디케이터가 인수 없이 사용되는 경우, 이는 다음과 같습니다.

result = decorator_with_arguments(sayHello)(a1, a2, a3, a4)

이 경우 장식된 기능이 생성자에게 직접 전달되는 것을 보고 호출합니다.__call__전체가 생략되었습니다.는 이 사건을 처리하기 위해 논리를 해야 합니다.__new__마술적인 방법

는 사할수없이를 수 없습니까?__init____new__은 이는간다에서 하는 것을 합니다. 파이썬은 없음 이외의 다른 값을 반환하는 것을 금지합니다.__init__

경고문

이 접근법은 한 가지 부작용이 있습니다.함수 서명은 보존되지 않습니다!

이렇게 하면 문제 없이 작업을 수행할 수 있습니다.

from functools import wraps

def memoize(fn=None, hours=48.0):
  def deco(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
      return fn(*args, **kwargs)
    return wrapper

  if callable(fn): return deco(fn)
  return deco

나를 위한 이 일:

def redirect_output(func=None, /, *, output_log='./output.log'):
    def out_wrapper(func):
        def wrapper(*args, **kwargs):
            res = func(*args, **kwargs)
            print(f"{func.__name__} finished, output_log:{output_log}")
            return res

        return wrapper

    if func is None:
        return out_wrapper  # @redirect_output()
    return out_wrapper(func)  # @redirect_output


@redirect_output
def test1():
    print("running test 1")


@redirect_output(output_log="new.log")
def test2():
    print("running test 2")

test1()
print('-----')
test2()

코드 제예 코드multiply()아래는 장식가로부터 하나의 인수 또는 괄호를 받아들일 수 있습니다.sum()아래는 두 개의 숫자를 합할 수 있습니다.

from numbers import Number

def multiply(num):
    def _multiply(func):
        def core(*args, **kwargs):
            result = func(*args, **kwargs)
            if isinstance(num, Number):
                return result * num
            else:
                return result
        return core
    if callable(num):
        return _multiply(num)
    else:
        return _multiply

def sum(num1, num2):
    return num1 + num2

그서만에약을 .@multiply(5)sum()그 다음에 방문sum(4, 6)아래와 같이:

# (4 + 6) x 5 = 50

@multiply(5) # Here
def sum(num1, num2):
    return num1 + num2

result = sum(4, 6)
print(result)

다음과 같은 결과를 얻을 수 있습니다.

50

그리고 만약에.@multiplysum()그 다음에 방문sum(4, 6)아래와 같이:

# 4 + 6 = 10

@multiply # Here
def sum(num1, num2):
    return num1 + num2
    
result = sum(4, 6)
print(result)

다음과 같은 결과를 얻을 수 있습니다.

10

하지만, 만약 당신이.@multiply()sum()그 다음에 방문sum(4, 6)아래와 같이:

@multiply() # Here
def sum(num1, num2):
    return num1 + num2
    
result = sum(4, 6)
print(result)

아래 오류가 발생합니다.

유형 오류: multiply()에 필요한 위치 인수 'num'이(가) 없습니다.

그래서, 당신이 원한다면,@multiply()오류 없이 실행하려면 기본값을 에 추가해야 합니다.num아래와 같이:

from numbers import Number
             # Here
def multiply(num=1):
    def _multiply(func):
        def core(*args, **kwargs):
# ...

러면을 넣으면 .@multiply()sum()그 다음에 방문sum(4, 6)아래와 같이:

# (4 + 6) x 1 = 10

@multiply() # Here
def sum(num1, num2):
    return num1 + num2
    
result = sum(4, 6)
print(result)

다음과 같은 결과를 얻을 수 있습니다.

10

인터넷에서 이러한 솔루션에 대해 쉽게 이해할 수 있는 설명을 찾지 못했기 때문에 이 솔루션에서 어떤 일이 발생했는지 시각적으로 보여드리겠습니다.

먼저, 무엇이 다른지 알아보겠습니다.@decorator그리고.@decorator() 그렇습니다.

@decorator괄호 없음:

def decorator(func=None):
    if func:
        print('success')
        return func
    else:
        print('failure')
        return print


@decorator
def hello():
    print('hello')
    return


hello()  # <- result bellow
success
hello

Process finished with exit code 0

지금이다@decorator()괄호 포함:

def decorator(func=None):
    if func:
        print('success')
        return func
    else:
        print('failure')
        return print


@decorator()
def hello():
    print('hello')
    return


hello()
failure
<function hello at 0x00000170FEC889A0>
Traceback (most recent call last):
  File "C:\Users\User\PycharmProjects\stackoverflow\answer_1.py", line 41, in <module>
    hello()
TypeError: 'NoneType' object is not callable

Process finished with exit code 1

<function hello at 0x00000170FEC889A0>는 와동합다니와 .print(hello)

괄호와 함께 데코레이터를 호출하면 아래의 함수는 무시됩니다(다른 응답에서 볼 수 있음).함수를 할 때( 반예는경하우환를함수나그러예경(우:▁(▁but:print), hello본 바와 같이

다른 예:

def decorator(func=None, arg=None):
    if func:
        print('success')
        return func
    else:
        print('failure')
        if arg:
            print(arg)
        return print


@decorator('i am an str')
def hello():
    print('hello')
    return


hello()
Traceback (most recent call last):
  File "C:\Users\User\PycharmProjects\stackoverflow_question_1\answer_1.py", line 37, in <module>
    @decorator('i am an str')
     ^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'str' object is not callable
success

Process finished with exit code 1

여기서 장식가는 부르려고 합니다.str그것은 그것으로 통과되었습니다.func매개 변수(콘솔에서 성공적으로 인쇄되었기 때문에), 괄호 안의 첫 번째 및 유일한 인수입니다.

만약 당신이 장식가가 어떻게 작동하는지 안다면, 당신은 아마 이미 그것을 알아냈을 것입니다.

우리가 전화할 때@decoratordef hello는 리는우를 받습니다.hello다음과 같이:

hello = decorator(hello)  # if hello is already defined

우리가 전화할 때@decorator()대신 우리는 다음을 얻습니다.

hello = decorator()(hello)
# this is calling the return value of decorator().

Python은 장식자 구문 코드를 가능한 한 단순하게 만들었습니다. @ 뒤에 줄에 놓는 모든 것이 유일한 인수로 아래의 정의와 함께 호출될 것입니다.@12341234는 와동합다니와 .... = 12341234(...)안 되기 에, 호할수없때문에기출,▁since때문없.@12341234유형 오류가 발생합니다.

다른 장식가를 위한 간단한 장식가:

from functools import wraps, partial

def with_optional_params(decorator):
    return wraps(decorator)(
        lambda func=None, /, **kwargs: partial(decorator, **kwargs)
        if func is None
        else decorator(func, **kwargs)
    )

@with_optional_params
def printed(func, *, pre=True, post=True):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if pre:
            print('pre')
        result = func(*args, **kwargs)
        if post:
            print('post')
        return result
    return wrapper

@printed
def foo(): pass

@printed(post=False)
def foo(): pass

저는 장식가들이 선택적 키워드 인수를 사용할 수 있도록 하기 위해 장식가와 함께 이 요지를 썼습니다.이 문제에 대한 우아한 해결책일 수 있습니다.

https://gist.github.com/ramonrosa/402af55633e9b6c273882ac074760426

기본값이 있는 키워드 인수를 사용해 보셨습니까?비슷한 것

def decorate_something(foo=bar, baz=quux):
    pass

일반적으로 Python에서 기본 인수를 지정할 수 있습니다...

def redirect_output(fn, output = stderr):
    # whatever

하지만 그것이 장식가들에게도 효과가 있는지는 확실하지 않습니다.저는 그것이 왜 그렇게 되지 않는지 어떤 이유도 모릅니다.

Vartec의 답변을 기반으로 구축:

imports sys

def redirect_output(func, output=None):
    if output is None:
        output = sys.stderr
    if isinstance(output, basestring):
        output = open(output, 'w') # etc...
    # everything else...

언급URL : https://stackoverflow.com/questions/653368/how-to-create-a-decorator-that-can-be-used-either-with-or-without-parameters

반응형