Python3 - 仅通过装饰器继承在类上执行代码

时间:2016-05-31 17:36:07

标签: python-decorators

我试图仅在一个条件下执行代码:当代码在继承自类AI的类A中执行时。

我希望我能拥有的输出如下:

 # module maintenance 

 1     from functools import wraps 
 2 

守则如下:

 3     def cleaning_logs(): 
 4         print("Cleaning logs") 
 5 

A要执行的代码是:

 6     def archive_log(func): 
 7         @wraps(func) 
 8         def enhanced_func(*args, **kwargs): 
 9             func(*args,**kwargs) 
10             cleaning_logs() 
11         return enhanced_func 
12 

为了不触及A类,我创建了一个装饰器:

 13     def cls_archive_log(cls): 
 14         #... Missing Code : I have tried many things 
 15         #... Missing Code : I have tried many things 
 16         setattr(cls, '__call__', archive_log) 
 17         return cls 
 18 

因为我认为无法从上面的装饰器中检索类的信息,所以我试图创建一个类装饰器。以下代码不完整,因为这是我的问题:

 19     @cls_archive_log 
 20     class AI(object): 
 21         def __call__(self): 
 22             self.stop() 
 23             print("Executing the common task") 
 24 
 25     class A(AI): 
 26         def stop(self): 
 27             print('Stopping A') 
 28 
 29     class B(AI): 
 30         def stop(self): 
 31             print('Stopping B') 
 32 

我在以下代码中使用的这个类装饰器:

<a>

但实际上,我已经为类装饰器尝试了一切。

我知道如何通过装饰师解决我的问题吗?

1 个答案:

答案 0 :(得分:0)

每一个容易。只需将属性设置如下:

16 def maintenance(cls):                                                                                                                                                                                                                                                       
17     setattr(cls, '__call__', archive_logs(cls.__call__))                                                                                                                                                                                                                    
18     return cls 

装饰需要实施维护的类

31 @maintenance                                                                                                                                                                                                                                                                
32 class A(AI):                                                                                                                                                                                                                                                                
33     def stop(self):                                                                                                                                                                                                                                                         
34         print("Stopping A") 

完整代码如下:

#!/usr/bin/env python                                                                                                                                                                                                                                                       

from abc import ABCMeta, abstractmethod                                                                                                                                                                                                                                     
from functools import wraps                                                                                                                                                                                                                                                 

def cleaning_logs():                                                                                                                                                                                                                                                        
    print("Cleaning logs")                                                                                                                                                                                                                                                  

def archive_logs(func):                                                                                                                                                                                                                                                     
    @wraps(func)                                                                                                                                                                                                                                                            
    def enhanced_func(*args, **kwargs):                                                                                                                                                                                                                                     
        func(*args, **kwargs)                                                                                                                                                                                                                                               
        cleaning_logs()                                                                                                                                                                                                                                                     
    return enhanced_func                                                                                                                                                                                                                                                    

def maintenance(cls):                                                                                                                                                                                                                                                       
    setattr(cls, '__call__', archive_logs(cls.__call__))                                                                                                                                                                                                                    
    return cls                                                                                                                                                                                                                                                              

class AI(object):                                                                                                                                                                                                                                                           
    __metaclass__ = ABCMeta                                                                                                                                                                                                                                                 

    @abstractmethod                                                                                                                                                                                                                                                         
    def stop():                                                                                                                                                                                                                                                             
        raise NotImplemtedError('NotImplemtedError')                                                                                                                                                                                                                        

    def __call__(self):                                                                                                                                                                                                                                                     
        self.stop()                                                                                                                                                                                                                                                         
        print("Executing the common AI task")                                                                                                                                                                                                                               

@maintenance                                                                                                                                                                                                                                                                
class A(AI):                                                                                                                                                                                                                                                                
    def stop(self):                                                                                                                                                                                                                                                         
        print("Stopping A")                                                                                                                                                                                                                                                 

class B(AI):                                                                                                                                                                                                                                                                
    def stop(self):                                                                                                                                                                                                                                                         
        print("Stopping B")