On 24 April 2013 23:41, Alan Gauld <alan.ga...@btinternet.com> wrote: > On 24/04/13 20:32, Oscar Benjamin wrote: >> >> On 24 April 2013 20:07, Alan Gauld <alan.ga...@btinternet.com> wrote: >>> >>> On 24/04/13 16:52, Dave Angel wrote: >>> >>>>> Does it mean? ; totalViruses[i] = totalViruses[i]/float(numTrials) >>>>> >>>> As the others have said, that's exactly right, at least if >>>> totalViruses[i] is immutable, like an int or a float. >>> >>> What difference does immutability make here? > >> The subtle distinction that Dave is referring to is about modifying an >> object in place vs rebinding a name to a newly created object. > > Sure, the bejhaviour with regard to the objects after the opreation is > slightly different. But it makes noi dsifference to the duality of > > x += n > v > x = x + n > > The mutability issues are identical.
Mutability of Python objects is a convention rather than any hard property of the object itself. One part of that convention is whether or not __iadd__ returns a new object or mutates in place. > >> Which behaviour occurs is entirely up to the author of the __iadd__ >> method of the class in question. This method can modify and return >> self or it can return a different object. > > This does make a difference because iadd (etc) can make a difference and I > had forgotten that there are a separate set of operator methods for the ixxx > operations, I was assuming that ixxx called the standard xxx. It does if __ixxx__ is not defined: >>> class A(object): ... def __add__(left, right): ... print('Add called') ... return 'whatever' ... >>> a = A() >>> a + 1 Add called 'whatever' >>> b = a+1 Add called >>> b 'whatever' >>> a += 1 # Calls __add__ Add called >>> a 'whatever' >>> class B(object): ... def __add__(left, right): ... print('Add called') ... return 'whatever' ... def __iadd__(self, right): ... print('iAdd called') ... return 'something else' ... >>> b = B() >>> b + 1 Add called 'whatever' >>> b += 1 iAdd called >>> b 'something else' > So in the > special case of a user type implementing xxx differently to ixxx the > behaviour might differ. But for all other cases I can think of the duality > will still work? Apart from this exception > > x += y > > will yield the same result as > > x = x + y > > I think.... By convention mutable types always implement __ixxx__ differently from __xxx__. For lists __iadd__ is the same as extend and mutates the existing list. For numpy arrays __ixxx__ modifies elements in place so that array+=val will add val to all elements of array in-place, rather then creating a new array. This always makes a difference if there are other references to the object (as in the example I gave). And here's another example: >>> c = ([],) >>> c ([],) >>> c[0] = c[0] + [1] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> c ([],) >>> c[0] += [1] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> c ([1],) Oscar _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor