Function creation (what happened?)

George Sakkis george.sakkis at gmail.com
Fri May 9 09:24:19 EDT 2008


On May 9, 9:02 am, Viktor <alefn... at gmail.com> wrote:
> This completely slipped of my mind... :)
>
> I'm trying to change the:http://wordaligned.org/svn/etc/echo/echo.py
>
> So if the function is method it prints ClassName.MethodName instead of
> MethodName(self|klass|cls=<... ClassName>).
>
> But it turned out that in the decorator, the wrapped function is
> always just a TypeFunction (I cannot find out if the function is
> method, classmethod, staticmethod or just a plain function - tried
> with inspect also)... And what is most interesting, when I do:
>
> def w(fn):
>     print 'fn:', id(fn)
>     return fn
>
> class A:
>     @w
>     def __init__(self): pass
>
> print 'A.__init__:', id(A.__init__)
>
> It turns out that the function I receive in the wrapper (even when I
> return the same function) is not the function which will finally be
> attached to the class...
>
> Is there a way to find out in the decorator "what will the decorated
> function be"?

The decorator does receive the correct function. The problem is that
at this point __init__ is still a plain function, not a method, i.e.
the sequence is:
   function -> decorated function -> method

There are several workarounds if you really want to differentiate
between functions and methods, none of them perfect:

- Apply the decorator after the class has been built, i.e. after the
functions have been wrapped in (unbound) methods:
    A.__init__ = w(A.__init__)

- (Risky Hack): Guess whether a function is intended to be wrapped in
a method by checking whether its first argument is named "self".
Obviously this is not foolproof and it doesn't work for static/class
methods.

- Have two different decorators, one intended for plain functions and
one for functions-to-be-methods (e.g. @deco, @decomethod).

George



More information about the Python-list mailing list