파이썬의 클래스 데코레이터 : 실제 사용 사례


9

파이썬 클래스 데코레이터의 실용적이고 합성되지 않은 사용 사례를 찾고 있습니다. 지금까지 나에게 맞는 유일한 경우는 플러그인 또는 이벤트와 같은 게시자 구독자 시스템에 클래스를 등록하는 것입니다.

@register
class MyPlugin(Plugin):
    pass

또는

@recieves_notifications
class Console:
    def print(self, text):
        ...

내가 생각한 다른 건전한 사례는 상속, 메타 클래스 또는 장식 방법을 기반으로 구축되었을 수 있습니다. 클래스 데코레이터 사용에 대한 좋은 (또는 나쁜!) 예를 공유해 주시겠습니까?

감사합니다!


우선 데코레이터는 개념적으로 메타 클래스보다 훨씬 간단합니다. 메타 클래스보다 데코레이터를 작성하는 것이 훨씬 간단하며, 여러 메타 클래스를 결합하는 방법을 알아낼 필요가 없습니다.
amon

@amon 노련한 개발자가 메타 클래스를 사용하는 경우 일반적으로 다른 옵션을 철저히 고려하여 메타 클래스가 문제를 해결하는 가장 좋은 방법임을 의미합니다. 또한 명시 적은 암시 적보다 낫습니다. 이것이 클래스 데코레이터가 ABCMeta아닌 우리가 가진 이유 일 수 있습니다 @abstractclass.
Zaur Nasibov

2
저는 파이썬 프로그래머이고 솔직히 필요하지 않습니다. 언어 기능이 존재한다고해서 언어 기능을 사용해야하거나 심지어 사용해야한다는 의미는 아닙니다. 설계자들은 불필요하거나 심지어 후시로 피해를 입었던 모든 종류의 미친 기능을 생각해냅니다. 실제로, 당신은 당신의 질문에 다른 두 가지 특징을 언급했습니다 :)
gardenhead

1
내가 없이는 살 수 없다는 것을 알지 못했지만 유용한 것으로 밝혀진 것은 클래스 데코레이터를 사용하여 클래스의 모든 메소드의 모든 입력과 출력을 기록하는 것입니다.
bgusach

답변:


8

를 갖는 단위를 기록하는 경우 테스트 @unittest.skipIf하고 @unittest.skipUnless어느 방법에 개별 또는 전체에서 사용할 수있는 unittest.TestCase클래스 정의. 따라서 플랫폼 별 문제에 대한 테스트를 훨씬 쉽게 작성할 수 있습니다.

의 예 asyncio/test_selectors

# Some platforms don't define the select.kqueue object for these tests.
# On those platforms, this entire grouping of tests will be skipped.

@unittest.skipUnless(hasattr(selectors, 'KqueueSelector'),
                 "Test needs selectors.KqueueSelector)")
class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
...

2

클래스 데코레이터는 PEP에서 메타 클래스를 통해 이미 표현할 수있는 것들을보다 즐겁게 만들기 위해 명시 적으로 만들어졌습니다 .

동기 유스 케이스는 CPython 인터프리터의 구현 세부 사항에 대해 특정 구문을보다 쉽게 ​​표현하고 덜 의존하게 만드는 것입니다. 메타 클래스를 사용하여 클래스 데코레이터와 같은 기능을 표현할 수 있지만 결과는 일반적으로 불쾌하며 구현은 매우 취약합니다. 또한 메타 클래스는 상속되는 반면 클래스 데코레이터는 상속되지 않으므로 클래스 클래스 데코레이터의 단일 클래스 별 사용에는 적합하지 않습니다. Zope과 같은 대규모 Python 프로젝트가 BDFL보다 클래스 데코레이터와 같은 것을 달성하기 위해 이러한 거친 왜곡을 겪고 있다는 사실.


PEP-3129를 인용 해 주셔서 감사합니다. 그러나 클래스 데코레이터가 존재하는 이유, Guido가 어떻게 생각하는지, Zope 또는 IronPython이 등장하기 전에 어떻게 사용할 수 있었는지에 대한 질문은 아닙니다. 문제는 2016 년 현재의 실제 사용량에 관한 것입니다.
Zaur Nasibov

1
요점은 원래 질문에 메타 클래스가 클래스 데코레이터와 같은 기능을 구현하는 데 사용할 수있는 것으로 표시되지만 데코레이터의 전체 요점은 메타 클래스보다 사용하기 쉽고 명확하다는 것입니다. 따라서 질문의 해당 부분에 대한 대답은 "데코레이터 또는 메타 클래스 사이에 찢어진 경우 다른 사람이 이해하기 쉽기 때문에 데코레이터를 사용해야합니다."
quodlibetor

당신은 대답 더 많은 질문을 떠나고 있습니다. "... 데코레이터의 전체 요점은 메타 클래스보다 사용하기 쉽고 명확하다는 것입니다."-어떤 경우에? 그렇다면 "... 다른 사람들이 이해하기 쉽기 때문에 데코레이터를 사용해야합니다." 파이썬에 오랫동안 중독 된 결과로, 나는 몇 가지 추악하고 아름다운 메타 클래스를 보았습니다. 그러나 어떤 클래스 데코레이터도 전혀 발견하지 못했습니다.
Zaur Nasibov

1

에서 스택 오버플로 질문 :

def singleton(class_):
  instances = {}
  def getinstance(*args, **kwargs):
    if class_ not in instances:
        instances[class_] = class_(*args, **kwargs)
    return instances[class_]
  return getinstance

@singleton
class MyClass(BaseClass):
  pass

그러나 동일한 SO 질문에 대조가 주어집니다 : 메타 클래스가 더 나은 접근 방식입니다.
Zaur Nasibov

1

클래스에서 데코레이터로 수행 할 수있는 사용 사례를 찾는 것은 쓸모 가 없습니다. 클래스에서 데코레이터로 수행 할 수있는 모든 것은 메타 클래스로 수행 할 수 있습니다. 등록의 예조차도. 이를 증명하기 위해 다음은 데코레이터를 적용하는 메타 클래스입니다.

파이썬 2 :

def register(target):
    print 'Registring', target
    return target


class ApplyDecorator(type):
    def __new__(mcs, name, bases, attrs):
        decorator = attrs.pop('_decorator')
        cls = type(name, bases, attrs)
        return decorator(cls)

    def __init__(cls, name, bases, attrs, decorator=None):
        super().__init__(name, bases, attrs)


class Foo:
    __metaclass__ = ApplyDecorator
    _decorator = register

파이썬 3 :

def register(target):
    print('Registring', target)
    return target


class ApplyDecorator(type):
    def __new__(mcs, name, bases, attrs, decorator):
        cls = type(name, bases, attrs)
        return decorator(cls)

    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)


class Foo(metaclass=ApplyDecorator, decorator=register):
    pass

1
당신이 말하는 것처럼-데코레이터로 무엇이든 할 수 있습니다. 문제는 메타 클래스가 아닌 클래스 데코레이터를 통해 수행 해야하는 경우입니다 .
Zaur Nasibov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.