2

I am a bit confused about, changing (mutating or appending) variables from within functions.
For reference, i found this question about functions that mutate the argument. which describes doing just that on an array:

def add_thing(a):
    a.append(2)

my_a = [1]

append_two(my_a)
my_a
>>> [1,2]

and we get the same results using a += [2]

However, if we try the same thing with a string, or an integer:

def add_world (s):
    s += " world"

my_str = "hello"

add_world(my_str)
my_str
>>> "hello"

It doesn't change, and the same goes for integers, like:

def add_one(i):
    i += 1

x = 1
add_one(x)
x
>>> 1

My question is:

  1. How should I recognize which objects I can mutate in a function like an array, and which ones I need to directly assign?

  2. why is the += operator not working as I'd expect? I was fairly sure that it was short hand for my_var = my_var + thing, which aught to work just fine within a function.

Community
  • 1
  • 1
Lundy
  • 663
  • 5
  • 19
  • 1
    possible duplicate of [How do I pass a variable by reference?](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) – Ruggero Turra Sep 18 '15 at 17:19
  • 1
    possible duplicate of [Function changes list values and not variable values in Python](http://stackoverflow.com/questions/17686596/function-changes-list-values-and-not-variable-values-in-python) – Chad S. Sep 18 '15 at 17:20
  • 1
    Read this carefully, preferably twice. It will clear some things up for you. http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/ – Rick Sep 18 '15 at 17:27
  • Thanks all, I'm was pretty sure that this is well covered territory, I just couldn't dig up anything specific. – Lundy Sep 18 '15 at 17:40

2 Answers2

2
  1. You have to look at the documentation. Generally: numbers, strings and tuples are immutable.

    Regarding specific methods, there is a general rule also: if the method returns something then it doesn't modify the argument. Methods that modify the argument return None.

  2. a += b is equivalent to a = a + b if a is immutable. If a is mutable then using += will mutate the object. Basically += is just a method call (to __iadd__). In the case of immutable objects the method returns a new object and doesn't mutate the original value, for mutable object the object is mutate and it returns itself.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
2

How should I recognize which objects I can mutate in a function like an array, and which ones I need to directly assign?

You need to know what kinds of objects you're using and read the documentation for those objects to know which operations, if any, mutate them. Unfortunately in the case of list this is not documented in the most accessible way. The closest thing is this which says:

An augmented assignment expression like x += 1 can be rewritten as x = x + 1 to achieve a similar, but not exactly equal effect. In the augmented version, x is only evaluated once. Also, when possible, the actual operation is performed in-place, meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.

Since lists are mutable, that means the in-place operation is possible.

why is the += operator not working as I'd expect? I was fairly sure that it was short hand for my_var = my_var + thing, which aught to work just fine within a function.

As the quote above shows, a += b is not quite the same as a = a + b. The difference is that the object a has the opportunity to define special behavior for a += b that may be different from the behavior for a + b. Lists do this so that += works in-place.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384