Home > Back-end >  Python class variables and methods visibility
Python class variables and methods visibility

Time:01-06

Gents,

I'm a very beginner in Python classes, so probably the question is a super dummy. Nevertheless, I didn't find the answer.

So, I have a Python class (I cut some code to simplify):

class c_DOT:
    color = 0

class c_TAIL:

    dot = c_DOT()
    
    tails = []

    def __init__(self) -> None:
      
        for i in range(10):
            self.tails.append(self.dot)
            self.tails[i].color = i
            print(self.tails[i].color)
            #here I see array with different values 0..9 - everything is ok.
    
    def test(self):        
        for i in range(0, 10): 
            print(self.tails[i].color)
        #here a I see only 9,9,..9


then:

t = c_TAIL()

t.test()
    

As a result of the code above I got these lines:

0 1 2 3 4 5 6 7 8 9

9 9 9 9 9 9 9 9 9 9

but why only 9,9,9??

Thanks.

CodePudding user response:

You are appending the same object therefore every element in the array appear to have the same value as it is the reference to the same object.

Instead of self.tails.append(self.dot) you should do:

dot = c_DOT()
dot.color = i;
self.tails.append(dot).

or add a constructor to c_DOT class to set color upon object creation, so that you could do this: self.tails.append(C_DOT(i)).

Take a look at this. You will see that all array elements will always have the last index value on each iteration:

import pprint 

pp = pprint.PrettyPrinter(indent=4)

class c_DOT:
    color = 0

    def __repr__(self):
        return str(self.color);

class c_TAIL:
    dot = c_DOT()
    tails = []

    def __init__(self) -> None:
        for i in range(10):
            self.tails.append(self.dot)
            self.tails[i].color = i
            pp.pprint(self.tails)

        print("---")
    
    def test(self):
        pp.pprint(self.tails);

obj = c_TAIL()
obj.test()

CodePudding user response:

The problem is, is that you keep appending the same object c_DOT, and changing the color of that same object. This means that the color of c_DOT is the last color you set it to, thus 9, and having made a list of references to the same c_DOT 9 times. What you would want to do is define a new c_DOT object to append to your tails list:

class c_DOT:
    color = 0

class c_TAIL:
    
    tails = []

    def __init__(self) -> None:
      
        for i in range(10):
            dot = c_DOT()
            self.tails.append(dot)
            self.tails[i].color = i
            print(self.tails[i].color)
            #here I see array with different values 0..9 - everything is ok.
            
    def test(self):        
        for i in range(0, 10): 
            print(self.tails[i].color)
        #here a I see only 9,9,..9
        
t = c_TAIL()

t.test()

CodePudding user response:

When __init__ is running and you are printing. The color value are changing in there instances hence you find output as 1,2,3.. so on. but they are all referencing to the same c_Dot instance see below image.

enter image description here

but when test function is running. the c_Dot instance has value 9 and all the list values are refrencing to that c_Dot instance. hence everytime you call any index the value 9 printed. see below image.

enter image description here

CodePudding user response:

you are appending same obj every time thats why when you are writing self.tails[i].color = i you are overwriting class variable by instance variable for your instance if you print(c_Dot.color) you will see your variable value is 0.

you can do this for your ideal result

class c_DOT:
    color = 0

class c_TAIL:

        # dot = c_DOT()

        tails = []

        def __init__(self) -> None:

            for i in range(10):
                self.dot = c_DOT() # for creating new obj every time 
                self.tails.append(self.dot)
                self.tails[i].color = i
                print(self.tails[i].color)

                #here I see array with different values 0..9 - everything is ok.

        def test(self):        
            for i in range(0, 10): 
                print(self.tails[i].color, "hello")
            #here a I see only 9,9,..9

    x = c_TAIL()
    x.test()
  • Related