__getattr__ and __setattr__ troubles
Michael Hudson
mwh21 at cam.ac.uk
Tue Jun 6 16:11:28 EDT 2000
=?ISO-8859-1?Q?Fran=E7ois_Pinard?= <pinard at iro.umontreal.ca> writes:
> "Adam Ruth" <aruth at intercation.com> writes:
>
> > The __str__ and __coerce__, etc, will all be sent to __getattr__ because
> > they are *not* defined in the class. If they were, then __getattr__
> > would never be called.
>
> But would not this get fairly tedious? For example:
>
[snip]
> which is convenient enough for me. While a simple:
^^^^^^
Overriding __getattr__ is not a simple business; it's probably unwise
to pretend it is.
Have you caused Python to crap out by infinite looping with
__getattr__ yet?
> ---------------------------------------------------------------------->
> class See:
>
> def __getattr__(self, key):
> print '**', key
> return None
>
> print See()
> ----------------------------------------------------------------------<
>
> will yield:
>
> ---------------------------------------------------------------------->
> pinard at titan:~ $ python see.py
> ** __str__
> Traceback (innermost last):
> File "see.py", line 7, in ?
> print See()
> TypeError: call of non-function (type None)
> ----------------------------------------------------------------------<
>
> * By the way, and a bit unrelated, why the space before the two asterisks?
Probably to do with softspace. Not sure.
> * The diagnostic would be rather cryptic, if the program was not so short.
> Usability studies could be driven to show that the diagnostic should rather
> be changed to something more informative :-).
Your wish is my command:
Index: classobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v
retrieving revision 2.86
diff -u -r2.86 classobject.c
--- classobject.c 2000/05/03 23:44:34 2.86
+++ classobject.c 2000/06/06 20:06:24
@@ -766,6 +766,10 @@
return PyString_FromString(buf);
}
res = PyEval_CallObject(func, (PyObject *)NULL);
+ if (res == NULL && !PyCallable_Check(func)) {
+ PyErr_SetString(PyExc_TypeError,
+ "lookup for '__repr__' returned an uncallable object");
+ }
Py_DECREF(func);
return res;
}
Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.70
diff -u -r2.70 object.c
--- object.c 2000/05/03 23:44:35 2.70
+++ object.c 2000/06/06 20:06:24
@@ -290,6 +290,10 @@
return PyObject_Repr(v);
}
res = PyEval_CallObject(func, (PyObject *)NULL);
+ if (res == NULL && !PyCallable_Check(func)) {
+ PyErr_SetString(PyExc_TypeError,
+ "lookup for '__str__' returned an uncallable object");
+ }
Py_DECREF(func);
}
if (res == NULL)
Not sure it's a sufficiently common error to justify this though.
I'll send it to patches at python.org and see what they think of it.
> * May I least get the default string representation, which was satisfying?
>
> * So, as soon as I use `__getattr__', I suddenly get a lot of other things to
> define as well? This would make `__getattr__' less attractive.
This is a good thing, as I tried to point out above. It does horrible
things to performance too. Overriding __getattr__ is good for "oo,
ain't that cool" value, but it is probably best to try to avoid it -
if you need it, fine, but consider alternatives first.
getting-worryingly-familiar-with-Python-internals-ly y'rs
Michael
--
incidentally, asking why things are "left out of the language" is
a good sign that the asker is fairly clueless.
-- Erik Naggum, comp.lang.lisp
More information about the Python-list
mailing list