Overriding the decorator of an abstract class in the inherited class

954 views Asked by At

So here's what I have:

The abstract class:

class DataWrapper(object):
    def decorator(f):
        def preprocess(*args, **kwargs):
            return f(*args, **kwargs)
        return preprocess

    @decorator
    def datamethod1(self, ..): ...

    @decorator
    def datamethod2(self, ..): ...

The inheriting class:

class DataManipulation(DataWrapper):
    def __init__(self, ..): ..

    def decorator(f):
        print 'here'
        def preprocess(*args, **kwargs):
            ret = f(*args, **kwargs)
        return preprocess

Essentially I have a bunch of general data methods (defined in DataWrapper) which are used by various classes. I allow a decorator to be defined to perform any pre / post processing on the data before being returned, which is defined in DataWrapper just as a placeholder.

Unfortunately, the decorator isn't being overridden when I try defining it in inherited classes; i.e. 'here' is not being printed.

I saw this and tried adding the override decorator in the inherited class, and while there's no error, 'here' still is not being printed.

Anyone have any suggestions?

1

There are 1 answers

0
Martijn Pieters On BEST ANSWER

Decorators are applied to functions when the class is defined, their return values replace the functions they decorated. By the time the DataWrapper class has been defined, you can no longer alter what decorator is being used.

Rather than use decorators, have the decorator delegate to another method on the class that subclasses can override:

def method_process(f):
    def wrapper(self, *args, **kwargs)
        return self.process(f, *args, **kwargs)                

class DataWrapper(object):
    def process(self, f, *args, **kwargs):
        # subclass to process the methods
        return f(self, *args, **kwargs)

    @method_process
    def datamethod1(self, ..):
        # ...

    @method_process
    def datamethod2(self, ..):
        # ...


class DataManipulation(DataWrapper):    
    def process(self, f, *args, **kwargs):
        print 'preprocessing here'
        return super(DataManipulation, self).process(f, *args, **kwargs)