staticmethod and __call__

James_Althoff at i2.com James_Althoff at i2.com
Thu Dec 6 18:49:28 EST 2001


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()
>
>Output:
>Traceback (most recent call last):
>  File "test.py", line 18, in ?
>    i.f()
>AttributeError: ItemGenerator instance has no attribute 'f'
>
>It doesn't seem to be making the __call__

We are presented with several mysteries here. <wink>

For one, "isinstance(j, Item)" is going to fail since none of class Item's
attributes have values that are instances of class Item itself.  So
ItemGenerator.items is the empty list [].

Also, __call__ is normally added to a class like ItemGenerator to make its
*instances* callable -- the ItemGenerator class object already responds to
(), it being a class object -- so making __call__ a static method seems
unusual.  Nonetheless, it will be called if ItemGenerator() is changed to
ItemGenerator()() (note the extra paren.s).

Having called __call__ as a static method on an ItemGenerator instance
(which is probably not what was desired), however, "i.f()" will still
generate an error because of "def f():" not being "def f(self):".

Seems like there should be a more straightforward way. <wink>

Jim






More information about the Python-list mailing list