Python 2.2a* getattr suggestion and question

Well, now every attr access goes thru __getattr__-method, so this could cause situations which give not so clear diagnostics:
-----------------------------------------------------------------
Python 2.2a3 (#1, Sep 26 2001, 22:42:46) [GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2 Type "help", "copyright", "credits" or "license" for more information. HELP loaded. Readline loaded. History loaded.
class A:
... def aa(self): ... print self ...
class B(A):
... def __getattr__(self, x): ... print "getattr:", x ...
b = B() b.aa
getattr: __repr__ Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: object is not callable: None -----------------------------------------------------------------
The problem above is that __repr__ can't be called because __getattr__ intercepts it's call, giving None.
Could something be done with this to make it easy to trace such kinds of problems?
Also, the question is what is the proper way (1 and only 1 way) to check if attribute exists inside __getattr__ method? How can it be done by one simple check like:
def __getattr__(self, attr): if hasattr(self, attr): ....
Or do I need some other tricks?
Sincerely yours, Roman Suzi

Well, now every attr access goes thru __getattr__-method, so this could cause situations which give not so clear diagnostics:
Please update to 2.2a4. Every new-style instance attribute access goes throuh __getattribute__; __getattr__ does the same as for classic classes.
It's true that if you screw with __getattribute__, you'll still break your objects; but that's hard to avoid given how things work.
--Guido van Rossum (home page: http://www.python.org/~guido/)

On Sun, 30 Sep 2001, Guido van Rossum wrote:
Well, now every attr access goes thru __getattr__-method, so this could cause situations which give not so clear diagnostics:
Please update to 2.2a4. Every new-style instance attribute access goes throuh __getattribute__; __getattr__ does the same as for classic classes.
That is good to hear! I forgot to upgrade to latest version before posting complains, sorry.
It's true that if you screw with __getattribute__, you'll still break your objects; but that's hard to avoid given how things work.
Sure. Still, I think interpreter diagnostics should be pointing to the exact place of trouble. At least, __getattribute__ must appear somewhere in the traceback to give a hint where from __repr__ was attempted to be called.
Sincerely yours, Roman Suzi

Sure. Still, I think interpreter diagnostics should be pointing to the exact place of trouble. At least, __getattribute__ must appear somewhere in the traceback to give a hint where from __repr__ was attempted to be called.
When you write a faulty __getattribute__ that returns None instead of raising AttributeError, it's not realistic to expect __getattribute__ to be in the stack trace.
--Guido van Rossum (home page: http://www.python.org/~guido/)

On Sun, Sep 30, 2001 at 02:37:00PM -0400, Guido van Rossum wrote:
Sure. Still, I think interpreter diagnostics should be pointing to the exact place of trouble. At least, __getattribute__ must appear somewhere in the traceback to give a hint where from __repr__ was attempted to be called.
When you write a faulty __getattribute__ that returns None instead of raising AttributeError, it's not realistic to expect __getattribute__ to be in the stack trace.
PyChecker might want to give an error if flow in __getattr[ibute]__ doesn't either pass through a return or a 'raise AttributeError'. Even if the intent is to have attributes default to None, an explicit 'return None' could be added.
Jeff

Roman Suzi wrote:
Well, now every attr access goes thru __getattr__-method, so this could cause situations which give not so clear diagnostics:
Python 2.2a3 (#1, Sep 26 2001, 22:42:46) [GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2 Type "help", "copyright", "credits" or "license" for more information. HELP loaded. Readline loaded. History loaded. >>> class A: ... def aa(self): ... print self ... >>> class B(A): ... def __getattr__(self, x): ... print "getattr:", x ...
b = B() >>> b.aa getattr: __repr__ Traceback (most recent
call last): File "<stdin>", line 1, in ? TypeError: object is not callable: None
Hmm. If that last line you typed into the interp was, in fact, "b.aa()", then there's nothing new here. The "print" asked for __repr__ and got None. You'll get something very similar in any version of Python.
If you really typed "b.aa", then something's really strange, because you didn't ask to call anything, yet B's __getattr__ was asked for "__repr__", not "aa". Since I doubt Guido has adopted VB's call-with-no-args-doesn't-need-parens, I bet you misquoted your session.
- Gordon

On Sun, 30 Sep 2001, Gordon McMillan wrote:
Hmm. If that last line you typed into the interp was, in fact, "b.aa()", then there's nothing new here. The "print" asked for __repr__ and got None. You'll get something very similar in any version of Python.
If you really typed "b.aa", then something's really strange, because you didn't ask to call anything, yet B's __getattr__ was asked for "__repr__", not "aa". Since I doubt Guido has adopted VB's call-with-no-args-doesn't-need-parens, I bet you misquoted your session.
No, I have it right. It was my intention to try b.aa. Every Python object has ability to represent itself as string. That is what I wanted here.
Sincerely yours, Roman Suzi

If you really typed "b.aa", then something's really strange, because you didn't ask to call anything, yet B's __getattr__ was asked for "__repr__", not "aa". Since I doubt Guido has adopted VB's call-with-no-args-doesn't-need-parens, I bet you misquoted your session.
For Gordon: the repr() call was implied when the value retrieved was about to be printed by the interactive interpreter.
No, I have it right. It was my intention to try b.aa. Every Python object has ability to represent itself as string. That is what I wanted here.
For Roman: *most* objects have this ability, but a bug in a program may cause this to fail. It's not a guarantee.
--Guido van Rossum (home page: http://www.python.org/~guido/)
participants (4)
-
Gordon McMillan
-
Guido van Rossum
-
Jeff Epler
-
Roman Suzi