staticmethod and __call__

Bruce Eckel Bruce at
Tue Dec 11 21:41:03 CET 2001

Actually, I can simplify this in one sentence: if you can make
__call__ a static method, then how do you create objects of that

Obvious once I think about it -- it would make the normal
constructor syntax vanish.

*********** REPLY SEPARATOR  ***********

On 12/7/01 at 9:20 AM Roeland Rengelink wrote:

>The reason this doesn't work is that ItemGenerator() never looks
for a
>static attribute __call__ in its own definition. __call__ is used
>define the meaning of instance(). Or, put differently, obj(*args,
>**kwargs) is equivalent to obj.__class__.__call__(obj, *args,
>Now, the __class__ of a class is its metaclass. Hence,
>looks for the __call__ method in its metaclass. 
>So, what's the metaclass of ItemGenerator? Well, unfortunately for
>classic (pre-2.2) classes that's not really obvious. Unless you've
>the Don Beaudry hook (you don't wanna know) to roll your own
>you can't point to an object and say that's the metaclass of
>ItemGenerator. For new style classes (derived from object or one
of the
>other build-ins), the answer is given by the call
>which turns out to be 'type'. That is 'type' is the metaclass of
>build in types (including itself). Since the type of a new style
>instance is its class, this means (a.o.) that in Python 2.2 
>obj(*args, **kwargs) is simply equivalent to 
>type(obj).__call__(obj, *args, **kwargs)
>Python 2.2 also introduces staticmethods. This has led some of us
to try
>to do the same thing you do here. Namely use staticmethod to try
>override the metaclass method. However, the general rule is that
>staticmethod can't be used to force an override for methods
defined in
>the metaclass. I (now) think this is a good thing. Why? Well
>exactly this example. The meaning of obj() is now very
>obj() => type(obj).__call__(obj)
>If we allowed staticmethod to override, it would become something
>if (isinstance(type(obj), type) and 
>    hasattr(obj, '__call__') and 
>    isinstance(obj.__call__, staticmethod)):
>    return obj.__call__()
>    return type(obj).__call__(obj)
>So, what use are staticmethods?
>I think Guido resisted introducing static methods for a long time
>an argument that goes something like:
>"Classes are for generating instances and defining their
behaviour. If
>you just want a namespace, use modules (or dictionaries)."
>I.e. somethink like
>import random
>rgen = random.Random()
>class Item:
>    __init__(self, val):
>       self.val = val
>    def f(self):
>       print 'An item with value', self.val
>items = [Item('a'), Item('b'), Item('c')]
>def ItemGenerator():
>    return rgen.choice(items)
>--- ---
>import items
>myitems = [items.ItemGenerator() for i in range(5)]
>for i in myitems:
>    i.f()
>I have the feeling the argument against static methods still
applies in
>most cases, probably augmented with:
>"... and if you really, really want do _that_, use metaclasses"
>Hope this helps,
>Bruce Eckel wrote:
>> I seem to have trouble getting __call__ to behave as a static
>> method:
>> class Item:
>>   def f(): print 'An Item'
>> Item.a = 'a'
>> Item.b = 'b'
>> Item.c = 'c'
>> class ItemGenerator:
>>   import random
>>   rgen = random.Random()
>>   items = [j for j in vars(Item).values() if isinstance(j,
>>   def __call__():
>>     return ItemGenerator.rgen.choice(ItemGenerator.items)
>>   __call__ = staticmethod(__call__)
>> items = [ItemGenerator() for i in range(5)]
>> for i in items:
>>   i.f()
>r.b.rigilink at
>"Half of what I say is nonsense. Unfortunately I don't know which

Most current information can be found at:
Bruce Eckel
Contains free electronic books: "Thinking in Java 2e" & "Thinking
in C++ 2e"
Please subscribe to my free newsletter -- just send any email to:
join-eckel-oo-programming at
My schedule can be found at:

More information about the Python-list mailing list