Function creation (what happened?)

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Fri May 9 10:41:42 EDT 2008


En Fri, 09 May 2008 10:02:01 -0300, Viktor <alefnula at gmail.com> escribió:

> 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:

The decorator receives the original, plain function (unless you chain decorators) and whatever it returns is used instead of the original function.

> 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"?

Whatever you return from the decorator.
But the decorator returns a *function* and A.__init__ is a *method*, an instance method in fact. The function can be found as A.__dict__['__init__']. Try this:

m = A.__init__
print m, type(m), id(m)
f = A.__dict__['__init__']
print f, type(f), id(f)

A method combines a function with an instance that becomes the "self" argument. In your case you're building an "unbound" method because it's not tied to a particular instance, but even such unbound method is not the same thing as a plain function (it must ensure that its first argument, when called, is an A instance and not any other object).
The "magic" that converts a simple function into an instance method, for old-style classes like yours, was in the Class type itself. For new style classes, the descriptor protocol is used. See http://www.python.org/doc/newstyle/

-- 
Gabriel Genellina




More information about the Python-list mailing list