How to use __getattribute__ to access a class attribute?

Discussion in 'Python' started by Ruud de Jong, Feb 29, 2004.

  1. Ruud de Jong

    Ruud de Jong Guest

    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.

    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

    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

    After some experimentation and documentation searching,
    I found that to get at the actual function, the __get__
    method for the staticmethod descriptor must be called:

    >>> C.__getattribute__(C,'a').__get__(None, C)

    <function a at 0x00A981B0>
    >>> C.__getattribute__(C,'a').__get__(None, C)()

    static method a

    If I use an class instance as the first argument
    it works OK. But I ran into this problem when I tried
    to use __getattribute__ in the __new__ function of a class
    -- there is no class instance yet at that point,
    and calling C() there leads to infinite recursion.

    Another variant that worked is to call __getattribute__
    on the metaclass:

    >>> type(C).__getattribute__(C,'a')

    <function a at 0x00A981B0>
    >>> type(C).__getattribute__(C,'a')()

    static method a

    But according to section 3.3.2.1 of the Language Reference
    (More attribute access for new-style classes),
    __getattribute__ "... should return the (computed) attribute value".
    This could be interpreted to say that __getattribute__ should
    return the function, not the staticmethod object.

    Is there a reason for this difference in behavior?
     
    Ruud de Jong, Feb 29, 2004
    #1
    1. Advertising

  2. Ruud de Jong

    Chris Guest

    Perhaps it might be easier if you made your own static method object:

    >>> class MyStaticMethod(object):

    .... def __call__(self):
    .... print "static method a"
    .... def __get__(self, cls, inst):
    .... return self.__call__
    ....
    >>> class C(object):

    .... a = MyStaticMethod()
    >>> C.a

    <bound method MyStaticMethod.__call__ of <__main__.MyStaticMethod object at
    0x00E57390>>
    >>> C.a()

    static method a
    >>> C.__getattribute__(C,'a')

    <__main__.MyStaticMethod object at 0x00E57390>
    >>> C.__getattribute__(C,'a')()

    static method a
    >>> c = C()
    >>> c.a()

    static method a
    >>> C.__getattribute__(c,'a')

    <bound method MyStaticMethod.__call__ of <__main__.MyStaticMethod object at
    0x00E57390>>
    >>> C.__getattribute__(c,'a')()

    static method a

    As far as your question goes, __getattribute__ is following the "... should
    return the (computed) attribute value" rule for retrieving the static method
    object... unfortunatly the calculated value in this case is a reference to
    the static method object rather then the __get__ method bound to the static
    method object.

    HTH

    Chris

    "Ruud de Jong" <> wrote in message
    news:40425d1b$0$41761$...
    > 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.
    >
    > 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
    >
    > 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
    >
    > After some experimentation and documentation searching,
    > I found that to get at the actual function, the __get__
    > method for the staticmethod descriptor must be called:
    >
    > >>> C.__getattribute__(C,'a').__get__(None, C)

    > <function a at 0x00A981B0>
    > >>> C.__getattribute__(C,'a').__get__(None, C)()

    > static method a
    >
    > If I use an class instance as the first argument
    > it works OK. But I ran into this problem when I tried
    > to use __getattribute__ in the __new__ function of a class
    > -- there is no class instance yet at that point,
    > and calling C() there leads to infinite recursion.
    >
    > Another variant that worked is to call __getattribute__
    > on the metaclass:
    >
    > >>> type(C).__getattribute__(C,'a')

    > <function a at 0x00A981B0>
    > >>> type(C).__getattribute__(C,'a')()

    > static method a
    >
    > But according to section 3.3.2.1 of the Language Reference
    > (More attribute access for new-style classes),
    > __getattribute__ "... should return the (computed) attribute value".
    > This could be interpreted to say that __getattribute__ should
    > return the function, not the staticmethod object.
    >
    > Is there a reason for this difference in behavior?
    >
     
    Chris, Feb 29, 2004
    #2
    1. Advertising

  3. 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
     
    Shalabh Chaturvedi, Mar 1, 2004
    #3
  4. Ruud de Jong <> wrote in message news:<40425d1b$0$41761$>...
    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
     
    Shalabh Chaturvedi, Mar 1, 2004
    #4
  5. Ruud de Jong

    Ivo Guest

    A good read you can find : www.diveintopython.com

    "Ruud de Jong" <> wrote in message
    news:40425d1b$0$41761$...
    > 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.
    >
    > 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
    >
    > 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
    >
    > After some experimentation and documentation searching,
    > I found that to get at the actual function, the __get__
    > method for the staticmethod descriptor must be called:
    >
    > >>> C.__getattribute__(C,'a').__get__(None, C)

    > <function a at 0x00A981B0>
    > >>> C.__getattribute__(C,'a').__get__(None, C)()

    > static method a
    >
    > If I use an class instance as the first argument
    > it works OK. But I ran into this problem when I tried
    > to use __getattribute__ in the __new__ function of a class
    > -- there is no class instance yet at that point,
    > and calling C() there leads to infinite recursion.
    >
    > Another variant that worked is to call __getattribute__
    > on the metaclass:
    >
    > >>> type(C).__getattribute__(C,'a')

    > <function a at 0x00A981B0>
    > >>> type(C).__getattribute__(C,'a')()

    > static method a
    >
    > But according to section 3.3.2.1 of the Language Reference
    > (More attribute access for new-style classes),
    > __getattribute__ "... should return the (computed) attribute value".
    > This could be interpreted to say that __getattribute__ should
    > return the function, not the staticmethod object.
    >
    > Is there a reason for this difference in behavior?
    >
     
    Ivo, Mar 1, 2004
    #5
  6. Ruud de Jong

    Ruud de Jong Guest

    Shalabh Chaturvedi schreef:
    > 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.


    Erh, hmm, rrriight... Built-in functions. <blush/>
    Completely forgot about that one -- too focussed
    on trying to do everything with object methods and such.
    I really need to pay more attention to those built-in functions.

    Well, that solves my immediate problem.
    I knew there had to be a simple solution :)

    >
    > 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.


    Well, that's not true, at least not on my system (XP, Python 2.3.3):

    >>> class C(object):

    def a():
    print "static method a"
    a = staticmethod(a)


    >>> C.__dict__['a']

    <staticmethod object at 0x00AADD10>

    > [snipped]


    > 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).


    C did not have its own __getattribute__ method. It inherited it
    from object.

    I still find this whole thing slightly ambiguous.
    A class C is itself an object, an instance of 'type',
    just as x = C() leads to x being an instance of class C.
    But x.__getattribute__ and C.__getattribute__ return
    different objects.

    > 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.


    I would also have expected an exception. The strange thing, as I see
    it, is that x.__getattribute__ and type(C).__getattribute__ both give
    the correct result, but that C.__getattribute__ *almost* gives the
    correct result, but stops at calling the __get__ function on the
    desciptor object.

    Anyway, now that you've kindly reminded me of the existance of getattr,
    I'll not spend any more time trying to understand this.

    Thanks,

    Ruud
     
    Ruud de Jong, Mar 1, 2004
    #6
  7. Ruud de Jong wrote:
    > Shalabh Chaturvedi schreef:
    >
    >> 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.

    >
    >
    > Erh, hmm, rrriight... Built-in functions. <blush/>
    > Completely forgot about that one -- too focussed
    > on trying to do everything with object methods and such.
    > I really need to pay more attention to those built-in functions.
    >
    > Well, that solves my immediate problem.
    > I knew there had to be a simple solution :)
    >
    >>
    >> 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.

    >
    >
    > Well, that's not true, at least not on my system (XP, Python 2.3.3):
    >
    > >>> class C(object):

    > def a():
    > print "static method a"
    > a = staticmethod(a)
    >
    >
    > >>> C.__dict__['a']

    > <staticmethod object at 0x00AADD10>
    >
    > > [snipped]


    Sorry, my mistake. In fact it doesn't work for even classmethods. Only
    for functions.

    >> 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).

    >
    >
    > C did not have its own __getattribute__ method. It inherited it
    > from object.


    True. Left out a little bit of information there (for brevity).

    > I still find this whole thing slightly ambiguous.
    > A class C is itself an object, an instance of 'type',
    > just as x = C() leads to x being an instance of class C.
    > But x.__getattribute__ and C.__getattribute__ return
    > different objects.


    Only if you didn't first do x.__getattribute___ = None <wink>. then
    x.__getattribute__ doesn't even return anything. x.__getattribute__ is
    never meant to be called. It is only called on /type/ objects. If you
    want to get an attribute on obj, you call __getattribute__ on type(obj).
    (Well that's what Python does, you can just use getattr(obj, 'attr')).

    >> 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.

    >
    >
    > I would also have expected an exception. The strange thing, as I see
    > it, is that x.__getattribute__ and type(C).__getattribute__ both give
    > the correct result, but that C.__getattribute__ *almost* gives the
    > correct result, but stops at calling the __get__ function on the
    > desciptor object.


    What C.__getattribute__ doesn't do (maybe it should?) is to check that
    the first argument is an instance of C, or at least an instance of
    object. I'm just guessing here, but if it continues with the default
    mechanism of __getattribute__, it is going to get the staticmethod object.

    >
    > Anyway, now that you've kindly reminded me of the existance of getattr,
    > I'll not spend any more time trying to understand this.
    >
    > Thanks,
    >
    > Ruud
    >
     
    Shalabh Chaturvedi, Mar 1, 2004
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sylvain Ferriol

    __getattribute__ for class object

    Sylvain Ferriol, Aug 12, 2005, in forum: Python
    Replies:
    3
    Views:
    284
    Steven Bethard
    Aug 12, 2005
  2. Pedro Werneck
    Replies:
    4
    Views:
    435
    Pedro Werneck
    Aug 8, 2006
  3. Adam Donahue
    Replies:
    8
    Views:
    355
    Michele Simionato
    Oct 27, 2007
  4. bambam

    __getattribute__ meta class?

    bambam, Feb 26, 2008, in forum: Python
    Replies:
    5
    Views:
    430
    bambam
    Feb 28, 2008
  5. Amirouche B.
    Replies:
    5
    Views:
    232
    Amirouche B.
    Aug 23, 2011
Loading...

Share This Page