[Python-bugs-list] [ python-Bugs-560438 ] foo() doesn't use __getattribute__

noreply@sourceforge.net noreply@sourceforge.net
Fri, 31 May 2002 14:16:01 -0700


Bugs item #560438, was opened at 2002-05-25 08:59
You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=560438&group_id=5470

Category: Type/class unification
Group: Python 2.2
Status: Open
Resolution: None
Priority: 5
Submitted By: Steve Alexander (stevea_zope)
Assigned to: Nobody/Anonymous (nobody)
Summary: foo() doesn't use __getattribute__

Initial Comment:
In the Python 2.2 release notes, it says::

- For new-style classes, what was previously called
__getattr__ is now
  called __getattribute__.  This method, if defined, is
called for
  *every* attribute access.  

However, if I define a callable class that also defines
a __getattribute__ method, the __getattribute__ method
is not used when I say instance().

class Foo(object):

    def __getattribute__(self, name):
        print "__getattribute__ with name =",name
        if name=="__call__":
            return lambda:1
        object.__getattribute__(self, name)

    def __call__(self):
        print "__call__ method called"
        
f = Foo()
f.__call__()
f()

$ python /tmp/test.py
__getattribute__ with name = __call__
__call__ method called

I would expect the second line of output to be the same
as the first.

----------------------------------------------------------------------

>Comment By: Steve Alexander (stevea_zope)
Date: 2002-05-31 21:16

Message:
Logged In: YES 
user_id=492001

Thanks for the thoughts Phillip.

I agree with what you say about the existence of a __call__
attribute beingn predicated upon callability.

However, I don't think that is relevant to my example.

My example class Foo is callable. I define the __call__
method. However, on calling a foo instance, the __call__
method is called, whereas according to the documentation, if
calling an object includes an attribute access, 
__getattribute__ should be called.

----------------------------------------------------------------------

Comment By: Phillip J. Eby (pje)
Date: 2002-05-31 21:02

Message:
Logged In: YES 
user_id=56214

This looks like behavior that is "as designed".  The
existence of a __call__ attribute is predicated upon
callability, *not* the other way around.  Or to put it
another way, callability is decided by an object's type, not
its instance attributes.  By way of contrasting example,
consider that if you set a '__call__' attribute on a module,
that doesn't make the module callable!

While this is not consistent with old-style class behavior,
I don't think changing it to match old-style classes is
consistent with type/class unification.  If you need to be
able to compute the __call__ attribute, the simple way is to
use a property or other attribute descriptor, e.g.:

def __call__(self):
    return lambda: 1

__call__ = property(__call__)

I'm not sure which other magic attributes are amenable to
this sort of treatment, however.


----------------------------------------------------------------------

Comment By: Steve Alexander (stevea_zope)
Date: 2002-05-25 09:05

Message:
Logged In: YES 
user_id=492001

Properly formatted test case in uploaded file.

----------------------------------------------------------------------

You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=560438&group_id=5470