0

I have the following minimal working example, where UpdateSequnce objects are supposed to have their internal list initialized to the empty list:

class UpdateSequence():
    def __init__(self, seq=[]):
        self.ups = seq
        #self.ups = []

    def append(self, update):
        self.ups.append(update)

    def __str__(self):
        return str(self.ups)


us = UpdateSequence()

for i in range(1,5):
    us.append(i)

us2 = UpdateSequence()

for i in range(5,10):
    us2.append(i)

print(us)
print(us2)

The printed output is:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

If I change

self.ups = seq

to

self.ups = []

I get the following output:

[1, 2, 3, 4]
[5, 6, 7, 8, 9]

which is what I expect the output to be.

What is going on? Must be something really simple but I can't see it.

User
  • 229
  • 3
  • 11
  • You have been bitten by this Python feature: https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – Jussi Nurminen Feb 12 '21 at 14:56

1 Answers1

1

A mutable default parameter causes that kind of issue. You can change your init() method to this:

def __init__(self, seq=None):
    self.ups = [] if seq is None else seq  # shared storage when seq is provided

or this:

def __init__(self, seq=[]):
    self.ups = seq.copy() # distinct storage systematically
Alain T.
  • 40,517
  • 4
  • 31
  • 51