2.2: __call__ method via __getattr__ not working

Roeland Rengelink r.b.rigilink at chello.nl
Wed Aug 15 03:07:35 EDT 2001


Drew Csillag wrote:
> 
> I don't know if this is a known bug in the current CVS version of 2.2
> but the following code breaks.
> 
> class bar(object):
>     def __call__(self, args):
>         print args
> 
> b = bar()
> b(1) #works ok here
> 
> class foo(object):
>     def _call_(self, args):
>         print args
>     def __getattr__(self, attr):
>         if attr == '__call__':
>             return self._call_
>         raise AttributeError, attr
> 
> f = foo()
> f(1) #dies here
> 

Well, I think this is (currently) a feature:

This works:

class foo(object):
    def __call__(): pass  # Convince Py foo is callable
    def _call_(self, args):
        print args
    def __getattr__(self, attr):
        if attr == '__call__':
            attr = attr[1:-1]
        return object.__getattr__(self, attr)

The reason this works is that when the this class definition is executed
def __call__():pass will fill the tp_call slot of the newly defined foo
type with a wrapper
that basically does an attribute lookup for __call__. If that def is not
present execution of the class definition will erroneously conclude that
tp_call needs not be set. When f(1) is then executed Python will check
this slot and conclude that a foo object is not callable.
    
Believe me, the previous sentences make sense when you look at the C
code

Hope this helps,

Roeland
-- 
r.b.rigilink at chello.nl

"Half of what I say is nonsense. Unfortunately I don't know which half"





More information about the Python-list mailing list