The Magick of __call__ (Or, Digging Deeper Than I Ought To)

Corey Richardson kb1pkl at aim.com
Fri Apr 1 11:07:15 EDT 2011


All callables (things you can foo(bar)) are really just objects that
implement the __call__ method, as far as I understand. Well then, that
would appear to make methods themselves callable, so let's do a little
playing around...

lavos at lavos ~ $ python
Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class Foo(object):
...     def __call__(self, foo):
...             self.name(foo)
...     def name(self, bar):
...             print "Name: {0}".format(bar)
...
>>> foo = Foo()
>>> foo("Me!")
Name: Me!

Ok, nothing out of the ordinary. But what happens if....

>>> foo.name.__call__("Corey")
Name: Corey
>>> eval("foo.name" + (".__call__" * 9001) + "('Corey')")
Name: Corey
>>> foo.name.__call__.__call__.__call__.__call__.__call__("Corey")
Name: Corey
>>> eval("foo.name" + (".__call__" * 100000000) + "('Corey')")
^C^Z
[1]+  Stopped                 python

(Which was then followed by a ps aux and a kill -9...it ate all my
memory and then moved on to my swap.)

I've been told that much magick lies in the CALL_FUNCTION bytecode, and
that if I really cared I could look at ceval.c. I don't speak enough C
or know enough of Python's C API for it to be of any use (yes I
looked!). Would looking at something such as PyPy's version of it be
good for me / does anyone else have insights?

-- 
Corey Richardson



More information about the Python-list mailing list