Decorators on bound methods with access to class and his ancestors
<p>When I decorated the bound method in Python class, I need get some info in this decorator from outer class. Is that possible?</p>

<p>For example:</p>

<pre><code>def modifier(func):
    import sys
    cls_namespace = sys._getframe(1).f_locals
    cls_namespace['data']  # dictonary has no key 'data'
    ...
    return func

class Parent:
    data = "Hi!"

class Child(Parent):

    @modifier
    def method(self):
        pass
</code></pre>

<p>the <code>cls_namespace</code> is just incomplete namespace of current class without <code>data</code> field that I need to get.</p>

<p>Is there ways to get it in decorator?</p>

<p>Function decoration takes place when the class body is being executed, nothing is known about the class itself or its base classes at this time. This means that <code>modifier</code> decorates the <em>unbound function object</em> and only when <code>func</code> is actually called on an instance will it be bound.</p>

<p>You could return a wrapper function to replace the decorated function, it'll be bound instead and you'll have access to <code>self</code>:</p>

<pre><code>from functools import wraps

def modifier(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        # self is an instance of the class
        self.data
        return func(self, *args, **kwargs)
    return wrapper
</code></pre>

<p>The wrapper will then be called each time <code>method</code> is called on an instance.</p>

<p>If you must have access to the <em>base classes</em> at class creation time, you'll have to wait until the <code>class Child</code> statement has <em>completed execution</em>. Until Python 3.6, that's only possible from a class decorator or metaclass; each is called after the class body is created and you'll have access to (at the least) the base classes.</p>

<p>Using a class decorator, for example:</p>

<pre><code>def modifier(cls):
    # cls is the newly created class object, including class attributes
    cls.data
    return cls

@modifier
class Child(Parent):
    def method(self):
        pass
</code></pre>

<p>Note the location of the decorator now.</p>

<p>Python 3.6 adds an <a href="https://docs.python.org/3.6/whatsnew/3.6.html#pep-487-simpler-customization-of-class-creation" rel="nofollow"><code>__init_subclass__</code> method</a> that could also give you that access; the (class) method is called each time a subclass is created of the current class:</p>

<pre><code>class Parent:
    def __init_subclass__(cls, **kwargs):
        # cls is a subclass of Parent
        super().__init_subclass__(**kwargs)
        cls.data

    data = "Hi!"

class Child(Parent):
    def method(self):
        pass
</code></pre>

python class reflection decorator python-decorators