Why doesn't __call__ lead to infinite recursion?

Beni Cherniavsky cben at techunix.technion.ac.il
Tue Aug 19 20:41:46 CEST 2003


In article <87ekzldf3d.fsf at pobox.com>, John J. Lee wrote:
>aahz at pythoncraft.com (Aahz) writes:
>[...]
>> you'll see __call__ there.  When you do foo(), Python actually does
>> type(foo).__call__(foo).  Because type(foo).__call__ is manipulating
>> foo, you don't get the circular reference.
>
>Still seems weird that type(foo).__call__.__call__ (etc.) is defined.
>
[I'm afraid I sent this 2 or 3 already in private by mistake; resending in
public.  I apologize, it's late...]

The point is that down there, sits the C level which doesn't go
through the Python definition.  When you call ``foo()``, ``type(foo)``
is asked at the *C* level how to call it (read: the type struct is
accessed and the call-behavior slot, if non-NULL, is called by plain
C function call - which can't be intercepted in C so there is no futher
recursion).

It so happens that classes, when asked this, go back into the Python
level and look for the `__call__` attribute.  They do this for all
operations, giving you the dynamism and flexibility we all love.

OTOH, functions, when asked this, simply execute their code objects with the
given arguments.  The attribute `__call__` on function is a "proxy" attribute. 
It is not used by function objects for the call, it only exposes the C-level
call machinery at Python level.  The same convention is used for other
built-in types and operations, so that from Python you see Python-level and
C-level methods in the same way.  You only have to be aware of the distinction
when working with bizzare extension types that don't respect this convention,
or asking questions like this one about how it all works...  (Another one: why
__getattribute__ is not infinitely recusive?  Same explanation.)

-- 
Beni Cherniavsky <cben at tx.technion.ac.il>

Look, Mom, no viruses!  [Hint: I use GNU/Linux]




More information about the Python-list mailing list