[Tutor] Counting method calls

Kent Johnson kent37 at tds.net
Sat Sep 22 18:46:37 CEST 2007


Ricardo Aráoz wrote:
> Kent Johnson wrote:

>> What version of Python are you using? When I try this program it prints
> 
> Py 0.9.5
> Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit
> (Intel)] on win32
> 
> I thought it might be you were trying the class with the list init call
> but I tried it and works the same way.
> Was using PyAlaMode, tried it using IDLE and it works like yours,
> probably a bug of PyAlaMode.

My guess is PyAlaMode is trying to introspect the objects in some way 
and that is causing the extra access (to non-existent attributes).

>> class CallCounter(object):
>>      def __init__(self, delegate):
>>          self._delegate = delegate
>>          self.calls = 0
>>      def __getattr__(self, name):
>>          value = getattr(self._delegate, name)
>>          if callable(value):
>>              self.calls += 1
>>          return value
>>
>> a = CallCounter(list())
> 
> Sadly :
>>>> a = CallCounter(list())
>>>> a.append(1)
>>>> a.calls
> 2
>>>> a.append(2)
>>>> a.append(3)
>>>> a.calls
> 5
>>>> a[3]
> 
> Traceback (most recent call last):
>   File "<pyshell#15>", line 1, in <module>
>     a[3]
> TypeError: 'CallCounter' object is unindexable

Hmm. The problem is that new-style classes don't look up special methods 
on instances, just in the class itself.

There is some discussion here, it looks a bit ugly:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/c5bb6496970b5c5a?hl=en&tvc=2
Alex Martelli's second response proposes a solution that overrides 
__new__() to create a custom class for each wrapper.

There might be some help here too, I haven't read it closely:
http://tinyurl.com/25lx5t

The code works if CallCounter is an old-style class.

Kent


More information about the Tutor mailing list