Descriptors and decorators

bruno.desthuilliers at gmail.com bruno.desthuilliers at gmail.com
Mon Oct 25 15:20:35 CEST 2010


On 25 oct, 14:15, Joost Molenaar <j.j.molen... at gmail.com> wrote:
> WebOb contains this little nugget of code that allows you to define a
> decorator that works on both methods and functions:
>
> class Decorator(object):
>     def __init__(self, func):
>         self.func = func
>     def __get__(self, object, type=None):
>         if type is None:
>             return self
>         newfunc = self.func.__get__(object, type)
>         return self.__class__(newfunc)
(snip)

> I'm still not sure what Decorator.__get__ does, or at least I'm not
> sure enough to be able to explain it well.

http://wiki.python.org/moin/FromFunctionToMethod


> Logically, the method C.m is unbound at the time the class is defined

"At the time the class is defined" - that is (usually) when the
"class" statement's body is executed -, 'm' is a plain function. Note
that by that time, class 'C' doesn't even exist, so there's no way you
could have a 'C.m' method ;)

So, your decorator is applied to a function, and wraps it into a
Decorator object. Or more exactly, the function is defined, then the
Decorator class is called so a new Decorator object is instanciated
with the function as argument, and finally this Decorator instance is
rebound to the name under which the function was formely known. All
this happenning _before_ class C even exists, so when the class object
is created, it has an attribute by the name of the decorated function
which is in fact a Decorator instance.

Now this instance is itself a descriptor, so when C.m or o.m are
looked up, the descriptor protocol is fired and Descriptor.__get__ is
called. If called without at least a 'type' argument, it just returns
itself, so it works as an ordinary function. Else it calls the
function's own descriptor implementation to get a bound or unbound
method, and returns a new instance of the decorator with the method as
argument.

HTH



More information about the Python-list mailing list