How to use __getattribute__ to access a class attribute?

Shalabh Chaturvedi shalabh at cafepy.com
Sun Feb 29 23:32:23 EST 2004


Ruud de Jong wrote:
> I have the situation where I need to construct the name
> of a static method, and then retrieve the corresponding
> function from a class object.

If what you're trying to do is get C.a (where C is the class and a is 
the name of the staticmethod) but all you have is the class C and a 
string mname = "a", then just getattr(C, mname) should work. Generally 
this works for any attribute access where you have the attribute name in 
another variable.

Another way to get the naked function, which also works for 
classmethods, is to do C.__dict__['a']. See comments below that explain 
what you see.

> I thought I could just use __getattribute__ for this purpose.
> This works fine if I already have an instantiation of the class,
> but not when I try this on the class object directly.
> 
> A bare bones example:
> 
>  >>> class C(object):
>     def a():
>         print "static method a"
>     a = staticmethod(a)
> 
> It works for a instantiation of class C:
>     
>  >>> x = C()
>  >>> x.a
> <function a at 0x00A981B0>
>  >>> x.__getattribute__('a')
> <function a at 0x00A981B0>
>  >>> x.__getattribute__('a')()
> static method a

When Python comes across x.a, it doesn't call x.__getattribute__('a'), 
it calls type(x).__getattribute__(x, 'a'). Now type(x) is C, and it just 
so happens (in this case) that x.__getattribute__ also ends up calling 
the same method, since x doesn't have a __getattribute__ of its own. 
This is why what you do above works.

> But for the class object it works differently:
> 
>  >>> C.a
> <function a at 0x00A981B0>
>  >>> C.__getattribute__(C,'a')
> <staticmethod object at 0x00AC6A10>
>  >>> C.a()
> static method a
>  >>> C.__getattribute__(C,'a')()
> 
> Traceback (most recent call last):
>   File "<pyshell#219>", line 1, in -toplevel-
>     C.__getattribute__(C,'a')()
> TypeError: 'staticmethod' object is not callable

To repeat the same experiment, you should call 
type(C).__getattribute__(C, 'a'). Note that in this case C *has* its own 
__getattribute__ attribute (which is meant for instances of C, not C 
itself). In fact you do this later, and it works. Hmm, at first glance 
I'd expect what you do above to return an exception if passed C instead 
of an instance of C (like any other well behaved method). I don't know 
why that doesn't happen.

In conclusion, __getattribute__() does return the computed attribute 
value, but for an object o it is called on the type(o) and not o itself. 
Also, getattr() is usually all you need.

HTH,
Shalabh






More information about the Python-list mailing list