Callable modules?

Pekka Pessi Pekka.Pessi at nokia.com
Tue Jul 30 19:02:10 EDT 2002


Paul Rubin <phr-n2002b at NOSPAMnightsong.com> writes:
>Is there a way to do that?  I tried putting

>  def __call__(x): ...

>into foo.py but that didn't work.  

	There is no magic in a __call__ attribute. Python language
	reference does not promise you anything about it. For example, 

>>> class O(object):
...   pass
... 
>>> o = O()
>>> o.__call__ = lambda x: x * x
>>> o(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'O' object is not callable

	However, the __call__ method is special:

>>> class O2(object):
...   def __call__(self, x):
...     return x * x
... 
>>> o2 = O2()
>>> o2(2)
4

	The function __call__ you added to the module is an attribute,
	not a method, so it does not have any magic.

	(The __call__ attribute does work on instances, but I think it
	is considered as a bug.)

>>> class I:
...   pass
... 
>>> i = I()
>>> i.__call__ = lambda x: x * x
>>> i(2)
1

	Now, back to your question. You can have a callable module, no
	problem:

>>> import types
>>> class module(types.ModuleType):
...   def __call__(self, x): return x * x
... 
>>> module()(2)
4

	If you want to call the __call__ attribute, that is a
	no-brainer, too:

>>> class module(types.ModuleType):
...   def __call__(self, *x, **kw):
...     try:
...       func = getattr(self, "__call__")
...       return apply(func, x, kw)
...     except AttributeError:
...       raise TypeError("'%s' module is not callable." % (self.__name__,))
... 
>>> m = module()
>>> m.__call__ = lambda x: x * x
>>> m(2)
4

	You can propably find out rest of the gory details by looking
	around in imp and knee modules.

>If there's not a way to do this already, maybe it's a reasonable
>addition.

	Guido disagrees, I'm afraid. I have asked twice, and got nixed
	twice.

					Pekka



More information about the Python-list mailing list