15

From the docs:

Many operations have an “in-place” version. The following functions provide a more primitive access to in-place operators than the usual syntax does; for example, the statement x += y is equivalent to x = operator.iadd(x, y). Another way to put it is to say that z = operator.iadd(x, y) is equivalent to the compound statement z = x; z += y.

Questions:

  • Why isn't operator.iadd(x, y) equivalent to z = x; z += y?

  • How does operator.iadd(x, y) differ from operator.add(x, y)?

Related question, but I'm not interested in Python class methods; just regular operators on built-in Python types.

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
Leftium
  • 16,497
  • 6
  • 64
  • 99

2 Answers2

32

First, you need to understand the difference between __add__ and __iadd__.

An object's __add__ method is regular addition: it takes two parameters, returns their sum, and doesn't modify either parameter.

An object's __iadd__ method also takes two parameters, but makes the change in-place, modifying the contents of the first parameter. Because this requires object mutation, immutable types (like the standard number types) shouldn't have an __iadd__ method.

a + b uses __add__. a += b uses __iadd__ if it exists; if it doesn't, it emulates it via __add__, as in tmp = a + b; a = tmp. operator.add and operator.iadd differ in the same way.

To the other question: operator.iadd(x, y) isn't equivalent to z = x; z += y, because if no __iadd__ exists __add__ will be used instead. You need to assign the value to ensure that the result is stored in both cases: x = operator.iadd(x, y).

You can see this yourself easily enough:

import operator
a = 1
operator.iadd(a, 2)
# a is still 1, because ints don't have __iadd__; iadd returned 3

b = ['a']
operator.iadd(b, ['b'])
# lists do have __iadd__, so b is now ['a', 'b']
Jegschemesch
  • 11,414
  • 4
  • 32
  • 37
Glenn Maynard
  • 55,829
  • 10
  • 121
  • 131
  • http://docs.python.org/2/reference/datamodel.html#object.__iadd__ Notice that augmented assignments could but does not have to modify object in-place – lig Feb 25 '14 at 16:47
  • 1
    Why is python designed with augmented assignments operating in-place? It's kinda feels counter-intuitive because when we learn the language we usually learn augmented assignments with immutable values first. So it's a bit unexpected that with mutable values augmented assignment behaves differently. Feels rather implicit and bug-prone. – max Nov 29 '16 at 19:21
  • 1
    @max: I don't know why you claim *"when we learn the language we usually learn augmented assignments with immutable values first"*. Strings are immutable, numeric values are mutable, lists are mutable, tuples are immutable. `s = 'foo'` `s += 'bar'` obviously behaves different to `x = 4.2` `x += 2` or `l = [1,5,6]` `l += [2]`. The only room for confusion is when you don't know the type of the LHS value. – smci Nov 12 '19 at 08:33
  • @max that sounds like the fault of whoever designed the learning materials. The purpose of augmented assignment is quite clear: [PEP 203](https://www.python.org/dev/peps/pep-0203/) – juanpa.arrivillaga Nov 18 '21 at 18:37
0

Perhaps because some Python objects are immutable.

I'm guessing operator.iadd(x, y) is equivalent to z = x; z += y only for mutable types like dictionaries and lists, but not for immutable types like numbers and strings.

Leftium
  • 16,497
  • 6
  • 64
  • 99