Adding lists

Recall that we can add lists as follows:

In [1]:
L1 = [1, 2]
L2 = [4, 5]
L = L1 + L2

What happens is that we compute L1 + L2 (the result is [1, 2, 4, 5]), place the result in memory, and then assign the address of the result to L.

We can, of course, also assign the result to L1 using L1 = L1 + L2. Let's explore this a little bit:

In [2]:
L1 = [1, 2]
L2 = [4, 5]
print("id(L1) =", id(L1), "L1 =", L1)
L1 = L1 + L2
print("id(L1) =", id(L1), "L1 =", L1)
id(L1) = 140559024051016 L1 = [1, 2]
id(L1) = 140558759954248 L1 = [1, 2, 4, 5]

The address to which L1 refers changed. It should have: we created a new object (a list with the contents [1, 2, 4, 5]), and placed it in a new available location in memory, and then assigned the address of that location back to L1.

Another thing we could do was use list.extend:

In [3]:
L1 = [1, 2]
L2 = [4, 5]
print("id(L1) =", id(L1), "L1 =", L1)
L1.extend(L2)
print("id(L1) =", id(L1), "L1 =", L1)
id(L1) = 140559024050568 L1 = [1, 2]
id(L1) = 140559024050568 L1 = [1, 2, 4, 5]

L1.extend(L2) modifies the contents of L1, but keeps its address the same.

Here is where it matters:

In [4]:
def add_lists_bad(L1, L2):
    #modify what the local variable L1 
    #refers to: won't matter outside the function
    L1 = L1 + L2
    

def add_lists_good(L1, L2):
    #modify the contents of the list that L1
    #refers to. Will make a difference outside
    #the function
    L1.extend(L2)
    
if __name__ == '__main__':
    L1 = [1, 2]
    L2 = [4, 5]
    add_lists_bad(L1, L2)
    print("L1 after add_lists_bad:", L1)

    add_lists_good(L1, L2)
    print("L1 after add_lists_good:", L1)
L1 after add_lists_bad: [1, 2]
L1 after add_lists_good: [1, 2, 4, 5]

If we want the function to have an effect on the global variable, we need to modify its content, not assign something new to its alias.

+= for lists

Even though it seems like L1 += L2 should be equivalent to L1 = L1 + L2, due to a design quirk, it is actually equivalent to L1.extend(L2).