[Python-Dev] buglet in unary ops on classes.
Guido van Rossum
guido@beopen.com
Sun, 30 Jul 2000 11:39:57 -0500
> While poking around looking for something else, I found this little buglet:
>
> >>> class X:
> ... def __getattr__(self, val):
> ... print "getattr:", val
> ... raise AttributeError
>
> >>> x = X()
> >>> ~x
> getattr: __invert__
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> File "<stdin>", line 4, in __getattr__
> AttributeError
>
> The unary ops all do this (raising AttributeError), but the binary ops do
> not:
>
> >>> x+1
> getattr: __coerce__
> getattr: __add__
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: __add__ nor __radd__ defined for these operands
>
> Shouldn't this translation be done for unary ops as well ? Is it safe to
> assume that instance_getattr() only returns NULL if the attribute is not
> found ? PyInstance_DoBinOp() takes this assumption wrt. PyObject_GetAttr(),
> and I don't really see a problem with it.
In general, I'm against changing exceptions. There are situations
conceivable where an AttributeError from a custom __getattr__ is
caused by a bug in that __getattr__ or in something it calls, and it's
important not to destroy the traceback in that case.
The TypeError for a binary operator violates this principle. This is
because the coercion process has to try several things that may fail
with an AttributeError. Saving the tracebacks is just too much work.
--Guido van Rossum (home page: http://www.pythonlabs.com/~guido/)