0

To demonstrate my question, I have the following code:

class Base(object):

    def __init__(self):
        self._base = [1,3]

    @property
    def base(self):
        return self._base

gp = Base()

class Parent1(object):

    def __init__(self):
        self.gp = gp.base

    def appendx(self):
        self.gp.append(4)
        return self.gp

class Parent2(object):

    def __init__(self):
        self.gp = gp.base

    def appendx(self):
        self.gp.append(7)
        return self.gp

class First(Parent1, Parent2):

    def __init__(self):
        super(First, self).__init__()

class Second(Parent2, Parent1):

    def __init__(self):
        super(Second, self).__init__()


f = First()
s = Second()

# [First]
f.appendx()
print "f.gp = %s" %f.gp      # f.gp = [1, 3, 4]
print "s.gp = %s" %s.gp      # s.gp = [1, 3, 4]    

# [Second]
a = s.appendx()
print "f.gp = %s" %f.gp      # f.gp = [1, 3, 4, 7]
print "s.gp = %s" %s.gp      # s.gp = [1, 3, 4, 7]
print "a = %s" %a            # a = [1, 3, 4, 7]

# [Third]
gp.base[0] ="a"
print "f.gp = %s" %f.gp      # f.gp = ['a', 3, 4, 7]
print "s.gp = %s" %s.gp      # s.gp = ['a', 3, 4, 7]
print "a = %s" %a            # a = ['a', 3, 4, 7]

# [Fourth] Confused from here on
a[0] ="b"
print "f.gp = %s" %f.gp      # f.gp = ['b', 3, 4, 7]
print "s.gp = %s" %s.gp      # s.gp = ['b', 3, 4, 7]
print "a = %s" %a            # a = ['b', 3, 4, 7]
print "type(a) = %s" %type(a) # type(a) = <type 'list'>

I can wrap my head around the first three sections, but I just don't understand, why would updating a list update everything else. Some explanation would help.

Amey
  • 8,470
  • 9
  • 44
  • 63

2 Answers2

2

That's how assigning a variable referencing an array works in python

a = [1, 2, 3]
b = a
b.append(4)

both a and b will now be [1, 2, 3, 4]. The second line only copies the reference to an array but it doesn't copy the array. The same happens in your program when it executes self.gp = gp.base, and in all the places where you return a reference to the array. There is only ever one array in your program.

If you don't want all your objects to share the same array, you have to copy the array in some way. It's up to you if you want to use a shallow or deep copy. There is a long explanation at How to clone or copy a list? .

Community
  • 1
  • 1
roeland
  • 5,349
  • 2
  • 14
  • 28
1

Describing why this error happens.

a = [1]
b = a
>>>print id(a), id(b)
3072113580 3072113580

That is both a and b are referencing to same object. If modification for any list causes for every refferenced variables.

To overcome this:

a = [1]
b = a[:] # copy list a to b
>>>print a, b
3053445164 3053960492

Hope this helps

itzMEonTV
  • 19,851
  • 4
  • 39
  • 49