Aahz:
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.
Not quite, but I don't understand how everything works so what I
say may also need corrections.
The call syntax "foo()" does two things. The first is to
get the 'thing' used for the call and the second is to actually
call it. The latter is not done recursively - if the returned
thing can't be called, the attempt at making the call fails.
If 'foo' is an instance, then the implementation code is
something like
thing_to_call = getattr(foo, "__call__")
if thing_to_call is not None:
DO_CALL(thing_to_call, args, kwargs)
The 'DO_CALL' is not a Python function, it's part of
how the implementation works.
The getattr implementation for an instance first tries to
find "__call__" in foo's instance __dict__. If that fails, it
looks in the parent class, and returns a bound method,
that is, a new 'thing' with references to the class method
and to the instance itself. The DO_CALL does the
actual call to this thing with the new arguments. The
bound method thing prepends the self parameter and
does the actual call to the underlying code.
Pretty complicated, and I don't think I was very clear
on that. Here's an example though to show that
foo() != foo.__class__.__call__(foo)
.... def __init__(self):
.... def callme(x):
.... print "Hello", x
.... self.__call__ = callme
.... def __call__(self, x):
.... print "Hej", x
....
I'm also missing something because I don't know how
functions work. I thought it was always 'use
getattr(obj, "__call__") to get the thing to call then do
the call machinery on that thing", but it doesn't seem
to do that for functions.
.... print "f(%s)" % x
........ print "g(%s)" % x
....
I expected the 'f(4)' call to return 'g(4)' since I replaced
the function's __call__ with g's __call__.
What's throwing me off is that g.__call__ returns
a new wrapper object each time, while once I
assigned f.__call__, it persistently stayed that way.
So there's some getattr shenanigans with functions
I don't understand. To make it worse, there's also
I'll leave the clarification to someone else.
Andrew
(e-mail address removed)