복붙노트

[PYTHON] 내가 추가 한 각 메소드에 대해 반복해서 타이핑하지 않고 클래스의 모든 기능을 어떻게 장식 할 수 있습니까? 파이썬 [복제]

PYTHON

내가 추가 한 각 메소드에 대해 반복해서 타이핑하지 않고 클래스의 모든 기능을 어떻게 장식 할 수 있습니까? 파이썬 [복제]

내 클래스에 많은 메소드가 있다고 가정하고 각 메소드에 데코레이터를 적용하고 싶습니다. 나중에 새 메소드를 추가 할 때 동일한 데코레이터를 적용하고 싶지만 메소드 선언 위에 @mydecorator를 모두 쓰려고합니다. 시간?

내가 __call__을 들여다 보면 그게 올바른 길인가?

감사

중요 : 아래 예제는 원래 질문 한 것과 다른 문제를 해결하는 것으로 보입니다.

편집 : ID는이 질문을 나중에 발견, anyobody에 대한 내 문제에 대한 비슷한 솔루션을이 방법으로 표시하려면 같은 의견을 언급 한대로 mixin 사용하십시오.

class WrapinMixin(object):
    def __call__(self, hey, you, *args):
        print 'entering', hey, you, repr(args)
        try:
            ret = getattr(self, hey)(you, *args)
            return ret
        except:
            ret = str(e)
            raise
        finally:
            print 'leaving', hey, repr(ret)

그럼 너는 다른

class Wrapmymethodsaround(WrapinMixin): 
    def __call__:
         return super(Wrapmymethodsaround, self).__call__(hey, you, *args)

해결법

  1. ==============================

    1.클래스의 속성을 살펴보고 호출 가능 항목을 꾸미는 함수로 클래스를 꾸미십시오. 호출 할 수있는 클래스 변수가 있고 중첩 클래스 (Sven Marnach가 이것을 가리키는 크레디트)를 꾸미면 일반적으로 오히려 깨끗하고 단순한 솔루션 일 경우 잘못 될 수 있습니다. 예제 구현 (특별한 메소드 (__init__ 등)은 제외되지 않는다.)

    클래스의 속성을 살펴보고 호출 가능 항목을 꾸미는 함수로 클래스를 꾸미십시오. 호출 할 수있는 클래스 변수가 있고 중첩 클래스 (Sven Marnach가 이것을 가리키는 크레디트)를 꾸미면 일반적으로 오히려 깨끗하고 단순한 솔루션 일 경우 잘못 될 수 있습니다. 예제 구현 (특별한 메소드 (__init__ 등)은 제외되지 않는다.)

    def for_all_methods(decorator):
        def decorate(cls):
            for attr in cls.__dict__: # there's propably a better way to do this
                if callable(getattr(cls, attr)):
                    setattr(cls, attr, decorator(getattr(cls, attr)))
            return cls
        return decorate
    

    다음과 같이 사용하십시오.

    @for_all_methods(mydecorator)
    class C(object):
        def m1(self): pass
        def m2(self, x): pass
        ...
    

    파이썬 3.0과 3.1에서는 호출 가능 함수가 존재하지 않습니다. 그것은 Python 2.x에서 영원히 존재했으며 Python 3.2에서 isinstance (x, collections.Callable)의 래퍼로 돌아 왔습니다. 따라서이 버전에서이 클래스를 사용할 수 있습니다 (또는 이것을 사용하여 자신 만의 호출 가능 대체를 정의 할 수 있습니다).

  2. ==============================

    2.명시 적 접근이 가능할 때 나는 마법적인 접근 방식을 선호하지 않지만, 아마도 이것을 위해 메타 클래스를 사용할 수 있습니다.

    명시 적 접근이 가능할 때 나는 마법적인 접근 방식을 선호하지 않지만, 아마도 이것을 위해 메타 클래스를 사용할 수 있습니다.

    def myDecorator(fn):
        fn.foo = 'bar'
        return fn
    
    class myMetaClass(type):
        def __new__(cls, name, bases, local):
            for attr in local:
                value = local[attr]
                if callable(value):
                    local[attr] = myDecorator(value)
            return type.__new__(cls, name, bases, local)
    
    class myClass(object):
        __metaclass__ = myMetaClass
        def baz(self):
            print self.baz.foo
    

    myClass의 각 호출 가능 객체가 myDecorator로 꾸며져있는 것처럼 작동합니다.

    >>> quux = myClass()
    >>> quux.baz()
    bar
    
  3. ==============================

    3.죽은자를 살리기 위해서가 아니라, 나는 정말로 델의 대답을 좋아했지만, 그것이 부족하다는 것을 알았다.

    죽은자를 살리기 위해서가 아니라, 나는 정말로 델의 대답을 좋아했지만, 그것이 부족하다는 것을 알았다.

    def for_all_methods(exclude, decorator):
        def decorate(cls):
            for attr in cls.__dict__:
                if callable(getattr(cls, attr)) and attr not in exclude:
                    setattr(cls, attr, decorator(getattr(cls, attr)))
            return cls
        return decorate
    

    편집 : 들여 쓰기 수정

    그래서 당신은 메소드 // 속성 // 당신이 장식하고 싶지 않은 것들을 지정할 수 있습니다.

  4. ==============================

    4.위의 답 중 아무 것도 __dict__를 사용하여 수행하지 않은 상속 된 메서드를 꾸미려고했기 때문에 나에게 도움이되지 않았으며 메타 클래스로 작업을 복잡하게 만들지 않았습니다. 마지막으로, 클래스의 모든 함수에서 사용되는 시간을 측정하기위한 프로파일 링 코드를 추가해야 할 필요가 있기 때문에 Python 2에 대한 해결책이있는 것이 좋습니다.

    위의 답 중 아무 것도 __dict__를 사용하여 수행하지 않은 상속 된 메서드를 꾸미려고했기 때문에 나에게 도움이되지 않았으며 메타 클래스로 작업을 복잡하게 만들지 않았습니다. 마지막으로, 클래스의 모든 함수에서 사용되는 시간을 측정하기위한 프로파일 링 코드를 추가해야 할 필요가 있기 때문에 Python 2에 대한 해결책이있는 것이 좋습니다.

    import inspect
    def for_all_methods(decorator):
        def decorate(cls):
            for name, fn in inspect.getmembers(cls, inspect.ismethod):
                setattr(cls, name, decorator(fn))
            return cls
        return decorate
    

    출처 (약간 다른 해결책) : https://stackoverflow.com/a/3467879/1243926 거기에서 파이썬 3을 위해 그것을 어떻게 바꾸는 지 볼 수 있습니다.

    다른 답변에 대한 의견을 제안 할 때 inspect.getmembers (cls, inspect.isroutine)를 대신 사용해보십시오. 파이썬 2와 파이썬 3 모두에서 작동하고 상속 된 메소드를 장식하는 적절한 솔루션을 찾았다면 여전히 7 줄에서 수행 할 수 있습니다.

  5. ==============================

    5.당신은 메타 클래스를 생성 할 수 있습니다. 상속 된 메서드를 장식하지 않습니다.

    당신은 메타 클래스를 생성 할 수 있습니다. 상속 된 메서드를 장식하지 않습니다.

    def decorating_meta(decorator):
        class DecoratingMetaclass(type):
            def __new__(self, class_name, bases, namespace):
                for key, value in list(namespace.items()):
                    if callable(value):
                        namespace[key] = decorator(value)
    
                return type.__new__(self, class_name, bases, namespace)
    
        return DecoratingMetaclass
    

    이렇게하면 지정된 함수로 모든 메소드를 꾸미는 메타 클래스가 생성됩니다. 다음과 같이 Python 2 또는 3에서 사용할 수 있습니다.

    def doubling_decorator(f):
        def decorated(*a, **kw):
            return f(*a, **kw) * 2
        return decorated
    
    class Foo(dict):
        __metaclass__ = decorating_meta(doubling_decorator)
    
        def lookup(self, key):
            return self[key]
    
    d = Foo()
    d["bar"] = 5
    print(d.lookup("bar")) # prints 10
    
  6. from https://stackoverflow.com/questions/6307761/how-can-i-decorate-all-functions-of-a-class-without-typing-it-over-and-over-for by cc-by-sa and MIT license