Search code examples
pythonpython-3.xpython-decorators

How do I write a python decorator that depends on a class attribute? Or is there a better way to approach this problem?


I am writing a class that takes an external object from an api, performs some processing on that object, exposes some useful methods, then writes the processed object to a database. In cases where the external object no longer exists, I want the class methods to use the data from the database record.

This is causing a lot of repeated, simple code in the class methods:

class Synchronised_object:
    def __init__(self, obj=None, rec=None):

        self.object = obj
        self.record = rec

    def a(self):
        if self.object:
            return self.object.a
        else:
            return self.record['a']

    def b(self):
        if self.object:
            return self.object.b.upper()
        else:
            return self.record['b']

Repeated, simple code in functions sounds like a great use case for decorators, but in this case the decorator code would depend on an attribute of the instantiated class object, which appears to be problematical from everything I read on here and elsewhere.

Is there any way to write a decorator that depends on self.object? If not, is there another way to reduce the repetition of the "if self.object.... else return self.record[name]"?


Solution

  • You really just want a method that handles the logic of deferring to the record. Something like:

    class SynchronisedObject:
        def __init__(self, obj=None, rec=None):
            self.object = obj
            self.record = rec
        def _proxy(self, attr):
            if self.object:
                return getattr(self.object, attr)
            return self.record[attr]
        def a(self):
            return self._proxy("a")
        def b(self):
            return self._proxy("b").upper()