spencer
spencer

Reputation: 189

Why is it necessary to place self as a parameter for method decorators?

For module-level functions, this code holds:

def dec(f):
    def wrap(*args, **kwargs):
        f(*args, **kwargs)
    return wrap

@dec
def foo(arg1):
    pass

When decorating methods however, all of a sudden you'll have to have one parameter to catch the instance.

def dec(f):
    def wrap(self, *args, **kwargs):
        f(self, *args, **kwargs)
    return wrap


class Test:
    def __init__(self):
        pass

    @dec
    def foo(self, arg1):
        pass

Why is that the case? What's so special about self that *args isn't able to catch it? After all isn't it just another positional argument? Also, how is it(self) passed into the inner wrap function?

For the first case, it's simply equivalent to foo = dec(foo). From what I've learned with closures, before foo is passed as an argument to the decorator. It creates an enclosure with __closure__, so it's able to retain whatever arguments were passed to foo.

Why is it that when it comes to methods then, apparently self doesn't seem to be part of the __closure__?

Upvotes: 4

Views: 94

Answers (2)

NPE
NPE

Reputation: 500367

Why is that the case? What's so special about self that *args isn't able to catch it?

This question is based on a premise that's flawed. As a matter of fact, *args can include self, both with and without decorators. This is illustrated by the following two examples.

Without decorators:

class Test(object):

  def foo(self, *args):
    return (self,) + args

  def bar(*args):  # for the purposes of illustration
    return args

t = Test()
print(t.foo(42))
print(t.bar(42))

With decorators:

def dec(f):
    def wrap(*args, **kwargs):
        return f(*args, **kwargs)
    return wrap

class Test(object):

    @dec
    def foo(self, arg1):
        return (self, arg1)

t = Test()
print(t.foo(42))

Upvotes: 3

David Duffrin
David Duffrin

Reputation: 87

I think it is best stated by the creator of Python himself:

http://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html

The main two points are:

There's a pretty good argument to make that requiring explicit 'self' in the parameter list reinforces the theoretical equivalency between these two ways of calling a method.

and

Another argument for keeping explicit 'self' in the parameter list is the ability to dynamically modify a class by poking a function into it, which creates a corresponding method.

Upvotes: 0

Related Questions