2015-08-17 6 views
1

В Python 3 У меня есть базовый класс, от которого производный класс:Сделать декоратора вызов метода конкретных до и после методы в классе

class Base: 
    # Tell the Base class to look and for pre/post 
    # functions the same name, and call them 
    def f(self): 
     print("f()") 

    def no_prepost(self): # should work, too 
     print("nothing") 

class Derived(Base): 
    def pre_f(self): 
     print("pre_f()") 

    def post_f(self): 
     print("post_f()") 

Я хочу назвать методы предварительной/пост, если они существует, но без явного указания их все время:

foo = Derived() 

# if exists: foo.pre_f() -- too verbose, do this automatically! 
foo.f() 
# if exists: foo.post_f() 

ответ

1

функция декоратор и некоторый класс самоанализ может сделать это. Если функция найдена подходящая она вызывается с теми же аргументами:

def prepost(f): 
    def prepost_wrapper(self, *args, **kwargs): 
     pre_name = 'pre_' + f.__name__ 
     post_name = 'post_' + f.__name__ 
     if hasattr(self, pre_name): getattr(self, pre_name) (*args, **kwargs) 
     ret = f(self, *args, **kwargs) 
     if hasattr(self, post_name): getattr(self, post_name)(*args, **kwargs) 
     return ret 
    return prepost_wrapper 

class Base: 
    @prepost  
    def f(self, a, b=99): 
     print("f()", a, b) 
    @prepost 
    def missing(self): 
     print("nothing special here") 

class Derived(Base): 
    def pre_f(self, a, b=0): # the arguments must match! 
     print("pre_f()", a, b) 
    def post_f(self, a, b=1): 
     print("post_f()", a, b) 

foo = Derived() 
foo.f("abc") 
foo.missing() 
foo.f("xyz", 12) 

Выход:

pre_f() abc 0 
f() abc 99 
post_f() abc 1 
nothing special here 
pre_f() xyz 12 
f() xyz 12 
post_f() xyz 12