Mingyi Wang
Mingyi Wang

Reputation: 19

Why a function does not change a list correctly in Python

A python script like the following. The list 'a' cannot be updated correctly:

   def test(b, a):
        print(a)
        a.append(10)
        a = b
        print(a)
            
    a = [1, 2, 3]
    b = [4, 5, 6]
    test(b, a)
    print(a)

The results were printed out like below. The list 'a' was changed as [1, 2, 3, 10] NOT [4, 5, 6]. Why?

Upvotes: 1

Views: 580

Answers (4)

MYousefi
MYousefi

Reputation: 1008

This is a scope issue. Within test the variable a, b are local references to objects a and b outside of test. Thus a and b in the context of test can be named anything.

Here's the code with some printouts that'll help explain this better:

def test(test_b, test_a):
    print('test_a references object in memory {} with values {}'.format(id(test_a), test_a))
    print('append(10)')
    test_a.append(10)
    print('test_a references object in memory {} with values {}'.format(id(test_a), test_a))
    print('assign reference test_a = test_b # new value {}'.format(id(test_b)))
    test_a = test_b
    print('test_a references object in memory {} with values {}'.format(id(test_a), test_a))

outside_a = [1, 2, 3]
outside_b = [4, 5, 6]
test(outside_b, outside_a)
print('outside_a references object in memory {} with values {}'.format(id(outside_a), outside_a))

A sample output of this would be like:

test_a references object in memory 140058884752448 with values [1, 2, 3]
append(10)
test_a references object in memory 140058884752448 with values [1, 2, 3, 10]
assign reference test_a = test_b # new value 140058887943936
test_a references object in memory 140058887943936 with values [4, 5, 6]
outside_a references object in memory 140058884752448 with values [1, 2, 3, 10]

Upvotes: 0

Tomasz Kalisiak
Tomasz Kalisiak

Reputation: 146

This is because by sending the variables a and b to the function, you created copies of them.

They point to the same data and you can modify it but when you assign a completely different list to the variable in the function, the original variable outside the function stays unchanged.

I would recommend returning the new lists from the function if you want to change the original variables. Like this:

def test(b, a):
        print(a)
        a.append(10)
        a = b
        print(a)
        return b, a

        
a = [1, 2, 3]
b = [4, 5, 6]
b, a = test(b, a)
print(a)

Upvotes: 0

Cameron
Cameron

Reputation: 377

You need to use a return statement to update a. Set a equal to the return value of the function.

def test(b, a):
        print(a)
        a.append(10)
        a = b
        return a
            
    a = [1, 2, 3]
    b = [4, 5, 6]
    a = test(b, a)
    print(a)

Upvotes: 1

Joran Beasley
Joran Beasley

Reputation: 113948

you simply created a new local variable a that was equal to b, that shadowed the a you passed in

you can do inplace replacement with slice notation

a[:] = b

would replace the value of a that you passed in

Upvotes: 1

Related Questions