staticmethod and __call__

Bruce Eckel Bruce at EckelObjects.com
Tue Dec 11 15:41:03 EST 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
class?

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:

>Hi,
>
>The reason this doesn't work is that ItemGenerator() never looks
for a
>static attribute __call__ in its own definition. __call__ is used
to
>define the meaning of instance(). Or, put differently, obj(*args,
>**kwargs) is equivalent to obj.__class__.__call__(obj, *args,
**kwargs).
>Now, the __class__ of a class is its metaclass. Hence,
ItemGenerator()
>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
used
>the Don Beaudry hook (you don't wanna know) to roll your own
metaclass,
>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
type(ItemGenerator),
>which turns out to be 'type'. That is 'type' is the metaclass of
all
>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
to
>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
consider
>exactly this example. The meaning of obj() is now very
straightforward.
>
>obj() => type(obj).__call__(obj)
>
>If we allowed staticmethod to override, it would become something
like
>
>if (isinstance(type(obj), type) and 
>    hasattr(obj, '__call__') and 
>    isinstance(obj.__call__, staticmethod)):
>    return obj.__call__()
>else:
>    return type(obj).__call__(obj)
>	
>So, what use are staticmethods?
>
>I think Guido resisted introducing static methods for a long time
with
>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
>
>--- items.py
>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)
>---
>
>--- use_it.py ---
>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,
>
>Roeland
>
>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,
Item)]
>>   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 chello.nl
>
>"Half of what I say is nonsense. Unfortunately I don't know which
half"
>-- 
>http://mail.python.org/mailman/listinfo/python-list



Most current information can be found at:
http://www.mindview.net/Etc/notes.html
===================
Bruce Eckel    http://www.BruceEckel.com
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 earth.lyris.net
My schedule can be found at:
http://www.mindview.net/Calendar
===================






More information about the Python-list mailing list