2

I am using Python version 3.7.5

I realized a bug in my code to transform some data, and I've done my best to create a minimum working example of the problem.

First, here is code that works as I expect it to:

a = ['foo','bar']
b = ['spam','eggs']
c = {'glue':a, 'dill':b}

for i in range(23,25):
    c['dill'] = c['dill'] + [i]
print(b)
print(c)
# ['spam', 'eggs']
# {'glue': ['foo', 'bar'], 'dill': ['spam', 'eggs', 23, 24]}

Namely, the code in the for loop does not affect the value of b.

But when I switch to using the increment operator, this is no longer the case:

a = ['foo','bar']
b = ['spam','eggs']
c = {'glue':a, 'dill':b}

for i in range(23,25):
    c['dill'] += [i]
print(b)
print(c)
# ['spam', 'eggs', 23, 24]
# {'glue': ['foo', 'bar'], 'dill': ['spam', 'eggs', 23, 24]}

In using Python, I had always been under the impression that:

  1. a += 1 and a = a + 1 did exactly the same thing
  2. when a variable is defined based on another variable (b=a), subsequent changes to the new variable (b=f(b)) would not affect the original variable

The examples above seems to violate both of those assumptions. What is going on?

  • This answer https://stackoverflow.com/a/823878/7648578 seems to cover it. "`+` always returns a newly allocated object, but `+=` should (but doesn't have to) modify the object in-place if it's mutable (e.g. `list` or `dict`, but `int` and `str` are immutable)." – nocibambi May 22 '20 at 13:56

1 Answers1

2

Your assumption 1 and 2 are true for value types (immutable types, not sure about the right term in Python) like numbers or string, but don't apply for lists.

Both problems are related to the same thing : list (array) variables in Python are references to a mutable object .

a = [1, 2, 3] creates an list.

b = a says that b is now a reference to the same list as a. Any action that mutates the array referenced will "affect both variables".

If you assign a new list to one of the variables, they won't refer to the same object in memory anymore.

See What does += mean in Python? (thanks nocimambi for the link) for details about how += mutates the same array, while + does create a new array.

Pac0
  • 21,465
  • 8
  • 65
  • 74
  • 1
    Thank you! I did not know about *references* in Python. It seems that a simple fix for my actual code is to write `b=a+[]` rather than `b=a` so that `b` does not refer to the same object as `a`. – zandergordan May 22 '20 at 14:32
  • @zandergordan Exactly! – Pac0 May 22 '20 at 15:03