1

I've got a project where there is a list that contains a large number of user-defined objects. Each object itself has a variable that contains a list of its own. Why is it that when I append something to the list inside of each object, it gets applied to every object in the master list?

Take the following code for example:

class Example:
    inner_arr = []
    def __init__(self,name):
        self.name = name

class_list = []
for i in range(10):
    class_list.append(Example("Trial #:{i}".format(i=i)))

for i in range(len(class_list)):
    if i % 3 == 0:
        class_list[i].inner_arr.append("Divisible by 3")

for i in class_list:
    print(i.inner_arr)

In theory, the ".append('Divisible by 3')" should only be applied to the 1st, 4th, 7th, and 9th objects in the class_list, so the expected result should look like this:

['Divisible by 3']
[]
[]
['Divisible by 3']
[]
[]
['Divisible by 3']
[]
[]
['Divisible by 3']

But instead we get this mess:

['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']
['Divisible by 3', 'Divisible by 3', 'Divisible by 3', 'Divisible by 3']

I've tried rewriting this using dictionaries, using every possible method for updating lists. Strangely enough this behavior only occurs when the object's variable is a list. If the object's variable is a string, it works exactly as expected. I'm sure this is user error, but I cannot figure out what I am missing in all of this. Any help or advice is appreciated. Thanks in advance.

2

3 Answers 3

2

When you declare an attribut directly in the class scope, not to self inside a method, this becomes a class variable, all instances will share it, you need to instanciate in the constructor and assign it to self to get an instance variable :

class Example:
    def __init__(self,name):
        self.name = name
        self.inner_arr = []

You can read more at Class&Instance Variable, that contains the exact example of your problem

Sign up to request clarification or add additional context in comments.

3 Comments

Whats weird to me is why is 'Divisible by 3' added to each list element 4 times?
@Ahmet 0 is divisible by 3
@Ahmet the normal solution gives 4 list with 1 element, if it is the same list : one list with 4 items (0,3,6,9 are ok)
1

Wonderful you discovered the difference between visibility for variables in classes!

class A:
    a = [] # this is variable common to the class

# each instance of A will share the same list!

class B:
    def __init__(self, b):
        self.b = b # see how we use self, these is bounded to the object!

# each instance of B instead will have its private instance of the list
# available as the attribute b

Comments

0

try this. If you declare variable inside class and it doesn't start with "self." then the varible has same value for every instance and if you change it in one instance, it changes in every.

class Example:
    def __init__(self,name):
        self.name = name
        self.inner_arr = []

class_list = []
for i in range(10):
    class_list.append(Example("Trial #:{i}".format(i=i)))

for i in range(len(class_list)):
    if i % 3 == 0:
        class_list[i].inner_arr.append("Divisible by 3")

for i in class_list:
    print(i.inner_arr)

4 Comments

Please always also write down an explanation why the OP's code doesn't work, and this does.
Wonderful! Thank you! Is there a particular reason why this happens though? Just for my own future reference.
In your method, inner_arr belongs to the class, while here inner_arr belongs to the instance of the class.
the variable has same value no, this is just the same variable that's it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.