pythondecoratorcomposition

Access parent object data member from sub-object in Python


I have a setup like the following

class decorator:
    def __init__(self, fn):
        self.fn = fn

    @staticmethod
    def wrap(fn):
        return decorator(fn)

    def __call__(self):
        print(f"decorator {self} function called")


class A:
    @decorator.wrap
    def foo(self):
        print(f"Object {self} called")

    def __init__(self):
        self.boo = 'Boo'

How do I from the decorator object access boo variable?


Solution

  • @S.B's solution works but is not thread-safe since multiple instances of A may be calling the foo method at about the same time in different threads, overriding the decorator object's instance attribute before a call to the __call__ method originated from another instance is made.

    A thread-safe approach would be to return a wrapper function from the __get__ method with the instance available through closure:

    class decorator:
        def __init__(self, fn):
            self.fn = fn
    
        def __get__(self, instance, owner=None):
            def wrapper(*args, **kwargs):
                print(f'decorator {self} function called; boo = {instance.boo}')
                return self.fn(instance, *args, **kwargs)
            return wrapper
    
    class A:
        @decorator
        def foo(self):
            print(f"Object {self} called")
    
        def __init__(self):
            self.boo = 'Boo'
    
    A().foo()
    

    This outputs:

    decorator <__main__.decorator object at 0x7f6ef3316c10> function called; boo = Boo
    Object <__main__.A object at 0x7f6ef3339580> called
    

    Demo: Try it online!