This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author sjones
Recipients
Date 2003-06-15.13:15:47
SpamBayes Score
Marked as misclassified
Message-id
In-reply-to
Content
Logged In: YES 
user_id=589306

I did some research and thinking on this problem, and here
is what I think is happening.

1. When you print self inside __getattr__, Python calls
repr(self) to figure out how to print that.
2. repr(self) attempts to call self.__repr__().
3. Since you didn't define __repr__ for this class,
__getattr__ is called to look up the name.
4. __getattr__ attempts to print self again, and you are now
in an infinite loop.

For more information, do a Google Groups search for "Obscure
__getattr__ behavior" which should bring you to the thread
at http://tinyurl.com/ecsh (hope that works, heh). It even
mentions the difference bcannon mentioned between old and
new style classes.

You could solve the problem by defining your own __repr__
(and __str__ for similar reasons). Or you can raise
AttributeError in __getattr__ if name is __repr__ or __str__
so that Python reverts back to defaults for these functions.

Here is a way to write your class so that it does what you want:

>>> class B:
...     def __getattr__(self, name):
...             if name == '__repr__' or name == '__str__':
...                     raise AttributeError
...             print self, name
...             return 3
...
>>> b = B()
>>> b.c
<__main__.B instance at 0x81c785c> c
3


I'm leaning toward the opinion that the infinite loop
behavior is not a bug in Python. Even though the result
wasn't expected, Python was doing exactly as told.

However, the Segmentation Fault you got on your system is
probably a bug. That seems related to your OS / build of
Python though. Can anyone duplicate the segfault?

Maybe Python isn't catching the infinite recursion fast
enough and your stack is overflowing (just a wild guess).
Try running some code like this and see if you get a
RuntimeError or a segfault:

def f():
    f()

Then call f() to see what error you get.

History
Date User Action Args
2007-08-23 14:13:51adminlinkissue752221 messages
2007-08-23 14:13:51admincreate