On 02/02/2012 10:53, Hrvoje Niksic wrote:
Steven D'Aprano<steve+comp.lang.pyt...@pearwood.info> writes:
Perhaps you are thinking that Python could determine ahead of time
whether x[1] += y involved a list or a tuple, and not perform the
finally assignment if x was a tuple. Well, maybe, but such an approach
(if possible!) is fraught with danger and mysterious errors even
harder to debug than the current situation. And besides, what should
Python do about non-built-in types? There is no way in general to
predict whether x[1] = something will succeed except to actually try
it.
An alternative approach is to simply not perform the final assignment if
the in-place method is available on the contained object. No prediction
is needed to do it, because the contained object has to be examined
anyway. No prediction is needed, just don't. Currently,
lhs[ind] += rhs is implemented like this:
item = lhs[ind]
if hasattr(item, '__iadd__'):
lhs.__setitem__(ind, item.__iadd__(rhs))
else:
lhs.__setitem__(ind, item + rhs)
# (Note item assignment in both "if" branches.)
It could, however, be implemented like this:
item = lhs[ind]
if hasattr(item, '__iadd__'):
item += rhs # no assignment, item supports in-place change
else:
lhs.__setitem__(ind, lhs[ind] + rhs)
This would raise the exact same exception in the tuple case, but without
executing the in-place assignment. On the other hand, some_list[ind] += 1
would continue working exactly the same as it does now.
In the same vein, in-place methods should not have a return value
(i.e. they should return None), as per Python convention that functions
called for side effect don't return values.
The alternative behavior is unfortunately not backward-compatible (it
ignores the return value of augmented methods), so I'm not seriously
proposing it, but I believe it would have been a better implementation
of augmented assignments than the current one.
>
[snip]
Could it not perform the assignment if the reference returned by
__iadd__ is the same as the current reference?
For example:
t[0] += x
would do:
r = t[0].__iadd__(x)
if t[0] is not r:
t[0] = r
Should failed assignment be raising TypeError? Is it really a type
error?
--
http://mail.python.org/mailman/listinfo/python-list