0

I do not understand what goes wrong with the following code:

class MyClass:
    def __init__(self, val = [0, 1]):
        self.val = val
    def giveout(self):
        print(self.val)
    def swap(self):
        inter = self.val[0]
        self.val[0] = self.val[1]
        self.val[1] = inter
        

a = MyClass()
a.swap()
a.giveout()
b = MyClass()
b.giveout()

Output:

[1, 0]
[1, 0]

Why is the output not:

[1, 0]
[0, 1]

When b gets initialised without a parameter, should it not get [0, 1] as default parameter? When I replace swap() by:

 def swap(self):
        self.val = [self.val[1], self.val[0]]

Then the output is as I would expect.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437

1 Answers1

1

This is a very common problem of initialization the default. So describe what happens is that when python sees your class it creates a single val list which every other object refers to. So to get rid of this issue, never give [] or {} as default argument, use None then inside __init__ initialize.

class MyClass:
    def __init__(self, val = None):
        self.val = [0, 1] if val is None else val
    def giveout(self):
        print(self.val)
    def swap(self):
        inter = self.val[0]
        self.val[0] = self.val[1]
        self.val[1] = inter
        

a = MyClass()
a.swap()
a.giveout()
b = MyClass()
b.giveout()
Epsi95
  • 8,832
  • 1
  • 16
  • 34
  • Thank you. Let me link another answer to a similar question: https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – Yelemiz Aug 25 '21 at 13:57
  • +1. Holy crap! I never realized that you had to be that careful about intializing variables in __init__. Yikes. Makes me wonder how many times I've made this mistake. – bfris Aug 25 '21 at 16:40