views:

38

answers:

2

Hi, I'm trying to create a class which must be superclass of others, tracing their attribute requests. I thought of using "getattribute" which gets all attribute requests, but it generates recursion:

class Mixin(object):
 def __getattribute__ (self, attr):
  print self, "getting", attr
         return self.__dict__[attr]

I know why I get recursion: it's for the self.dict call which recalls getattribute recursively. I've tryied to change last line in "return object.__getattribute__(self,attr)" like suggested in other posts but recursion is recalled.

+4  A: 

Try this:

class Mixin(object):
    def __getattribute__ (self, attr):
        print self, "getting", attr
        return object.__getattribute__(self, attr)

If you are still getting recursion problems, it is caused by code you haven't shown us

>>> class Mixin(object):
...     def __getattribute__ (self, attr):
...         print self, "getting", attr
...         return object.__getattribute__(self, attr)
...
>>> Mixin().__str__
<__main__.Mixin object at 0x00B47870> getting __str__
<method-wrapper '__str__' of Mixin object at 0x00B47870>
>>> Mixin().foobar
<__main__.Mixin object at 0x00B47670> getting foobar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __getattribute__
AttributeError: 'Mixin' object has no attribute 'foobar'
>>>

And here is the result when combined with Bob's Mylist

>>> class Mylist(Mixin):
...     def __init__ (self, lista):
...         if not type (lista) == type (""):
...             self.value = lista[:]
...     def __add__ (self,some):
...         return self.value + some
...     def __getitem__ (self,item):
...         return self.value[item]
...     def __getslice__ (self, beg, end):
...         return self.value[beg:end]
...
>>> a=Mylist([1,2])
>>> a.value
<__main__.Mylist object at 0x00B47A90> getting value
[1, 2]
gnibbler
Um... "I've tryied to change last line in `return object.__getattribute__(self,attr)` like suggested in other posts but recursion is recalled." -- OP
delnan
I've already tried that
Bob_Bib
@delnan, Bob_Bib, the code I posted is correct. If you are still seeing recursion, please post all the code you are using and the traceback
gnibbler
since someone was so lazy to downvote this answer without even trying it, I've added some sample output from the console
gnibbler
Okay, obviously the flaw is in Bob_Bib's code - undownvote + upvote + apologies.
delnan
@delnan, thanks ;o) now I just have to convince Bob too
gnibbler
A: 

This is the code:

from Es123 import Mixin
class Mylist(Mixin):
    def __init__ (self, lista):
        if not type (lista) == type (""):
            self.value = lista[:]
    def __add__ (self,some):
        return self.value + some
    def __getitem__ (self,item):
        return self.value[item]
    def __getslice__ (self, beg, end):
        return self.value[beg:end]
a = Mylist ([1,2])
a.value

Then python returns "RuntimeError: maximum recursion depth exceeded"

Bob_Bib
That should work fine with the Mixin class from my answer. Check that `Es123.py` has the correct version of the class. If it still doesn't work, post the whole traceback
gnibbler
Yes, it works! Sorry I left the wrong version so it didn't work. Thank you. Could you explain to me why it works with object.__getattribute__(...) but not with only __getattribute__(...) please?
Bob_Bib
`self.__getattribute__` calls `Mixin`'s `__getattribute__` method, which calls itself recursively. `object.__getattribute__` calls `object`'s `__getattribute__` method which is wholey different than `Mixin`'s method of the same name. Hence, no recursion.
unutbu
Thank you all, bye
Bob_Bib