user232343
user232343

Reputation: 2118

Python list append causes strange result

I have really strange problem. Here is the sample code:

class SomeClass(object):
    a = []
    b = []
    def __init__(self, *args, **kwargs):
        self.a = [(1,2), (3,4)]
        self.b = self.a
        self.a.append((5,6))
        print self.b

SomeClass()

Print outputs [(1, 2), (3, 4), (5, 6)], but why, why result isn't [(1,2), (3,4)] ? Do you know how can I have the old value of self.a in self.b?

Thank you!

Upvotes: 0

Views: 338

Answers (5)

viraptor
viraptor

Reputation: 34145

self.b = self.a isn't copying the list. It's assigning the reference to that list, so both attributes point at the same object. If you modify it via one reference, you'll see the change via the other one too.

You can use copy.copy(the_list) to get the proper copy. Or copy.deepcopy(the_list) if you need the references below also updated.

Upvotes: 2

Sylvain Leroux
Sylvain Leroux

Reputation: 51990

As many have already mentioned it, you end up having two references on the same list. Modifying the list by one reference of by the other just modify the list.

Here is an illustration to make things more clear if needed:

Shared reference

  • Step "A" is just after

    self.a = [(1,2), (3,4)]
    
  • Step "A" is just after

    self.b = self.a
    
  • Step "C" is just after

    self.a.append((5,6))
    

Upvotes: 7

Martijn Pieters
Martijn Pieters

Reputation: 1121476

You are assigning the same list to self.b, not a copy.

If you wanted self.b to refer to a copy of the list, create one using either list() or a full slice:

self.b = self.a[:]

or

self.b = list(self.a)

You can test this easily from the interactive interpreter:

>>> a = b = []  # two references to the same list
>>> a
[]
>>> a is b
True
>>> a.append(42)
>>> b
[42]
>>> b = a[:]  # create a copy
>>> a.append(3.14)
>>> a
[42, 3.14]
>>> b
[42]
>>> a is b
False

Upvotes: 6

neuront
neuront

Reputation: 9612

Because self.a and self.b are actually references to the same list object.

If you want to modify one without changing the other, try this

class SomeClass(object):
    # a = []
    # b = [] # these two class member not necessary in this code
    def __init__(self, *args, **kwargs):
        self.a = [(1,2), (3,4)]
        self.b = list(self.a) # copy to a new list
        self.a.append((5,6))
        print self.b

SomeClass()

Upvotes: 1

zidsal
zidsal

Reputation: 587

dicts in python share the same memory space when you assign them to each other.

for more information on this see: http://henry.precheur.org/python/copy_list

Upvotes: 1

Related Questions