> On May 15, 2019, at 11:02 AM, Rob Gaddi <rgaddi@highlandtechnology.invalid> > wrote: > > On 5/15/19 10:52 AM, Irv Kalb wrote: >> I just saw some code that confused me. The confusion has to do with class >> variables and instance variables. In order to understand it better, I built >> this very small example: >> class Test: >> x = 0 >> def __init__(self, id): >> self.id = id >> self.show() >> def show(self): >> print('ID:', self.id, 'self.x is:', self.x) >> def increment(self): >> self.x = self.x + 1 >> # Create two instances of the Test object, each shows itself >> t1 = Test('first') >> t2 = Test('second') >> # Ask t1 to increment itself twice >> t1.increment() >> t1.increment() >> # Ask each to show themselves >> t1.show() >> t2.show() >> # Let's see what the class has >> print('Test.x is:', Test.x) >> When I instantiate two objects (t1 and t2), the __init__ method calls the >> show method, which prints a value of self.x. I'm not understanding why this >> is legal. I would expect that I would get an error message saying that >> self.x does not exist, since no instance variable named self.x has been >> defined. >> However, this code runs fine, and gives the following output: >> ID: first self.x is: 0 >> ID: second self.x is: 0 >> ID: first self.x is: 2 >> ID: second self.x is: 0 >> Test.x is: 0 >> My guess is that there is some scoping rule that says that if there is no >> instance variable by a given name, then see if there is one in the class. >> If that is the case, then this line in the increment method seems odd: >> self.x = self.x + 1 >> If the self.x on the right hand side refers to the class variable, and >> creates an instance variable called self.x on the left hand side, then how >> does the second call work using the value of the instance variable on the >> right hand side? Can someone explain what's going on here? > > Pretty much exactly like that. The first time you call t1.increment, you > fail to find x in the instance dictionary, fall back and find it equal to 0, > add 1 makes 1, and store x=1 into the instance dictionary. > > The second time, you find x=1 in the instance dictionary, add 1 makes 2, and > overwrite x=2 into the instance dictionary. > > You never call increment on t2, so it never gets an x in its instance > dictionary, so t2.x still refers to Test.x. > >> Disclaimer: I would never write code like this, but I saw this in someone >> else's code and didn't understand how it was working. > > Sometimes when I'm feeling lazy it's a convenient way to set defaults on > instance variables. I don't love it, but I also can't explain what I find > wrong with it. > >> Irv >> >
Thanks for the confirmation. I still think its weird to have: self.x = self.x + 1 and have it refer to two potentially different variables at different times, but at least I understand what's going on. Irv -- https://mail.python.org/mailman/listinfo/python-list