How to use __getattribute__ to access a class attribute?

Shalabh Chaturvedi shalabh at gameboard.org
Sun Feb 29 23:33:00 EST 2004


Ruud de Jong <ruud.de.jong at consunet.nl> wrote in message news:<40425d1b$0$41761$5fc3050 at dreader2.news.tiscali.nl>...
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 type(o) and not o itself.
Also, getattr() is usually all you need.

HTH,
Shalabh



More information about the Python-list mailing list