0

I have a list of class instances, and I want to append separate items to an attribute for each. However, I ended up appending each item to the attribute on every instance in the list. Example code below:

class example:
    def __init__(self):
        example.xlist = []

classes = [example(), example(), example()]
i=0
for instnce in classes:
    instnce.xlist.append(i)
    i+=1
print("1st list:", classes[0].xlist)
print("2nd list:", classes[1].xlist)
print("3rd list:", classes[2].xlist) 

I want the output to be:

1st list: [0]  
2nd list: [1]  
3rd list: [2]

but instead I get:

1st list: [0, 1, 2]  
2nd list: [0, 1, 2]  
3rd list: [0, 1, 2]

any ideas on what is happening / what I can change to get the desired output?

name
  • 1
  • 3
    You should assign `self.xlist`, not `example.xlist`, in the `__init__()` method. `example.xlist` is shared by all instances. – Barmar Apr 07 '22 at 20:07
  • Your `__init__()` method should contain: `self.xlist = []`. The code you have keeps assigning a new empty list to the one class attribute and so the call to `append()` operates on that one list. – quamrana Apr 07 '22 at 20:07

1 Answers1

1

The problem is in your constructor when you create the new list. Instead of creating example.xlist, you should try using self.xlist instead. In Python, the self keyword, refers to the specific instance and not the general object.

If we apply this change to your sample code, we get:

class example:
    def __init__(self):
        self.xlist = []

classes = [example(), example(), example()]
i=0
for instnce in classes:
    instnce.xlist.append(i)
    i+=1
print("1st list:", classes[0].xlist)
print("2nd list:", classes[1].xlist)
print("3rd list:", classes[2].xlist) 

This code produces the correct output.

  • 1
    Note that `self` isn't a keyword, but only the conventional name we give to the first parameter of the methods, which will receive the instance as first argument. Also, `__init__` isn't really a constructor, see https://stackoverflow.com/questions/28791639/initializer-vs-constructor . – Thierry Lathuille Apr 07 '22 at 20:18
  • Whoops, that was a typo just in my example code, though your changes do solve that. My actual code gives the attribute a default value, like this: ```class example: def __init__(self,xl=[]): self.xlist = xl``` That seems to be causing my issues, perhaps because the same blank list gets assigned to each? – name Apr 07 '22 at 20:23
  • Got it! Could you please edit your question to fix the typo in your code so that someone can answer it fully instead of as a comment that might not be visible? – Akilan Manivannan Apr 07 '22 at 21:01
  • But to answer your question, you should use `self.xlist = xl.copy()` instead to create a new instance of a list that has the same value. – Akilan Manivannan Apr 07 '22 at 21:04