2012-03-28 32 views
14

Czy ktoś mógłby pokazać prosty przykład tego? Staram się osiągnąć to, co zostało zaimplementowane w Pythonie 2.6 używając PEP 3129 wyjątkiem stosowania klasy nie funkcje, jak Bruce Eckel wyjaśnia herepython: udekoruj klasę definiując dekoratora jako klasę

następujące prace:

class Decorator(object): 
    def __init__(self, arg): 
     self.arg = arg 

    def __call__(self, cls): 
     def wrappedClass(*args): 
      return cls(*args) 
     return type("TestClass", (cls,), dict(newMethod=self.newMethod, classattr=self.arg)) 

    def newMethod(self, value): 
     return value * 2 

@Decorator("decorated class") 
class TestClass(object): 
    def __init__(self): 
     self.name = "TestClass" 
     print "init %s"%self.name 

    def TestMethodInTestClass(self): 
     print "test method in test class" 

    def newMethod(self, value): 
     return value * 3 

wyjątkiem, w powyższym wrappedClass nie jest klasa, ale funkcja manipulowana, aby zwrócić typ klasy. Chciałbym napisać to samo, co:

def __call__(self, cls): 
     class wrappedClass(cls): 
      def __init__(self): 
       ... some code here ... 
     return wrappedClass 

Jak to zrobić? EDIT: Nie jestem do końca pewien, co dzieje się "" "... jakiś kod tutaj ... """

+0

Czy próbowałeś sam napisanego kodu? Powinno działać. –

+0

Pierwsza część korzystająca z funkcji działa. Jak jednak napisać wrappedClass jako prawdziwą klasę? – tsps

+1

Co powinien zrobić twój dekorator? Nie mogę powiedzieć, jaki kod musi przejść do "jakiegoś kodu tutaj", nie wiedząc, co ten kod ma zrobić. –

Odpowiedz

13

Jeśli chcesz nadpisać new_method(), po prostu to zrobić:

class Decorator(object): 
    def __init__(self, arg): 
     self.arg = arg 
    def __call__(self, cls): 
     class Wrapped(cls): 
      classattr = self.arg 
      def new_method(self, value): 
       return value * 2 
     return Wrapped 

@Decorator("decorated class") 
class TestClass(object): 
    def new_method(self, value): 
     return value * 3 

Jeśli nie chcesz zmieniać __init__(), nie musisz go zastępować.

2

Po tym, NormalClass klasa staje się ClassWrapper instancja:

def decorator(decor_arg): 

    class ClassWrapper: 
     def __init__(self, cls): 
      self.other_class = cls 

     def __call__(self,*cls_ars): 
      other = self.other_class(*cls_ars) 
      other.field += decor_arg 

    return ClassWrapper 

@decorator(" is now decorated.") 
class NormalClass: 
    def __init__(self, name): 
     self.field = name 

    def __repr__(self): 
     return str(self.field) 

Test:

if __name__ == "__main__": 

    A = NormalClass('A'); 
    B = NormalClass('B'); 

    print A 
    print B 
    print NormalClass.__class__ 

wyjściowa:

A teraz urządzone.
B jest teraz udekorowany.
__main __. ClassWrapper

+2

zapomniałeś zwrócić "inną" zmienną wewnątrz metody __call__ –