Question

In Python 3 there are no bound methods (known from Python 2), but we always create functions.

After declaring a function inside a class, something is creating automatic Pythons descriptor, which will append self as first argument, when this function will be called as instance method.

So basically, following code:

def funcdecorator(func):
    def f(*args, **kwargs):
        print('funcdecorator:', args, kwargs)
    return f

class X:
    @funcdecorator
    def f(self):
        pass

X().f()

will output:

funcdecorator: (<__main__.X object at ...>,) {}

(the first argument is passed as self)

but with following code:

def classdecorator(func):
    class C:
        def __call__(*args, **kwargs):
            print('classdecorator:', args, kwargs)
    return C()

class X:
    @classdecorator
    def f(self):
        pass

X().f()

we get:

classdecorator: (<__main__.C object at 0x1bbea10>,) {}

which is logical.

But, is it possible to return from decorator an class instance and mimic it is a function, so when 'calling' it, the first passed argument will be an instance of X, not an instance of C?

Was it helpful?

Solution

The class C needs to be a descriptor, i.e. implement __get__. Then, X().f() will first call the descriptor's __get__, passing the X instance and a reference to X. Whatever __get__ returns will then see __call__ invoked.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top