[Tutor] Counting method calls

Kent Johnson kent37 at tds.net
Mon Sep 24 02:15:34 CEST 2007


Ricardo Aráoz wrote:
> Kent Johnson wrote:
>> One more reference:
>> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252151
>>
>> This appears as recipe 6.6 in the second edition of the printed cookbook.
>>
>> Kent
> 
> Thanks Kent. I guess I got into deep waters.
> It's a shame though that you can not do this in a simple manner,
> considering python simplifies so many other chores.

I agree, also because it is so easy to do with old-style classes.

The root of the problem seems to be that new-style classes do not use 
the normal attribute lookup mechanism to find special methods when they 
are being invoked by the interpreter *as* special methods. For example, 
when executing a[0], __getattribute__() is not called on the class of a 
or its metaclass. Instead the predefined slot for __getitem__ is 
accessed; if it is empty then indexing is not allowed.

Here is a demonstration that __getattribute__() is not called on the 
class or the metaclass when __getitem__() is accessed as a special method:

In [4]: class ShowMeta(type):
    ...:     def __getattribute__(self, name):
    ...:         print 'ShowMeta:', name
    ...:         return type.__getattribute__(self, name)
    ...:
    ...:
In [5]: class Show(object):
    ...:     def __getattribute__(self, name):
    ...:         print 'Show:', name
    ...:         return object.__getattribute__(self, name)
    ...:     __metaclass__ = ShowMeta
    ...:
    ...:
In [6]: a=Show()
In [7]: a[1]
------------------------------------------------------------
Traceback (most recent call last):
   File "<ipython console>", line 1, in <module>
<type 'exceptions.TypeError'>: 'Show' object is unindexable

Notice that neither __getattribute__() is called. OTOH if __getitem__() 
is accessed as a normal attribute then Show.__getattribute__() *is* called:

In [9]: a.__getitem__(0)
Show: __getitem__
------------------------------------------------------------
Traceback (most recent call last):
   File "<ipython console>", line 1, in <module>
   File "<ipython console>", line 4, in __getattribute__
<type 'exceptions.AttributeError'>: 'Show' object has no attribute 
'__getitem__'

The only way to put something in the __getitem__ slot to assign to 
cls.__getitem__. That is why the cookbook recipe copies methods from the 
delegate into the proxy. It seems unfortunate that the recipe requires 
knowing which special methods you want to delegate. Maybe an approach 
like the one here
http://groups.google.com/group/comp.lang.python/msg/f4bf020fd94d631a
of delegating all special methods with a list of exceptions would work 
better.

Kent


More information about the Tutor mailing list