0

I'm writing a simple script in Python, that creates a list of 10000 instances of test class. Then I'm looping through every element in the list and changing value of variable x to random string generated using id_generator method.

import string
import random


def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

class test:
    x = None
    y = None

d = test

lista = [d] * 10000

w = 0
while (w < 10000):
    lista[w].x = id_generator()
    w = w + 1

print(lista[3].x)
print(lista[40].x)
print(lista[1999].x)

Why do I get 3 same values on the output? Shouldn't I get 3 different values generated using id_generator()

5
  • Because you got list of 10000 references for the test class. To create list like this: lista = [test() for _ in xrange(10000)]. While loop is ugly too, replace it with for in... Commented Aug 16, 2016 at 9:50
  • lista[1] is lista[1493] returns True. That is because you create only a single object that is 10000 times in your list. Commented Aug 16, 2016 at 9:51
  • I downvoted because you "should have understood" what this code d = test; lista = [d] * 10000 is supposed to do. Commented Aug 16, 2016 at 9:53
  • Yes, that is a single object, but then I'm changing the value of x in one of its instance. Does it change the value of all of the objects in the list? Putting print(lista[w].x) inside the loop gives me 10000 different strings. Commented Aug 16, 2016 at 9:55
  • No, you are referencing a class attribute of the very same class in all the iterations, so at the end of the loop you end up having updated the very same attribute. You see 10000 different values if you print inside the loop because you are printing the single update on the class attribute (which is overwriting the previous one, for every iteration). Commented Aug 16, 2016 at 10:01

2 Answers 2

6

Because you are not creating an instance of your class and you are directly referencing the class attribute x of the test class. You also have to declare your attributes as instance attributes, hence defining them inside __init__():

import string
import random

def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

class test:

    def __init__(self):
        self.x = None
        self.y = None

# Create 10000 instances of the test class
lista = [test() for _ in range(10000)]

w = 0
while (w < 10000):
    lista[w].x = id_generator()
    w = w + 1

print(lista[3].x)
print(lista[40].x)
print(lista[1999].x)
Sign up to request clarification or add additional context in comments.

Comments

1

You are making three different mistakes:

  1. You should use instance attributes, and not class attributes:

    class test:
        def __init__(self):
            self.x = None
            self.y = None
    
  2. You should instantiate the test class. You should write:

     d = test()
    
  3. By writing [d]*10000 you are actually storing 10000 copies of the same object. Write instead:

    # notice that you can get rid of the 'd' object
    lista = [test() for i in range(0, 10000)]
    

Comments

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.