I'm new to Python and am perplexed by some behavior I'm seeing. If I define
class Obj():
a = 1
b = 2
and then create an instance
x = Obj()
all is well:
print(Obj.__dict__)
print(x.__dict__)
print(x.a,Obj.a)
produces
{'a': 1, '__module__': '__main__', 'b': 2, '__doc__': None}
{}
(1, 1)
But if I
x.a = 20
I get
{'a': 1, '__module__': '__main__', 'b': 2, '__doc__': None}
{'a': 20}
(20, 1)
I understand that, initially, a is the class variable Foo.a, and that initially there is no instance variable a. I also understand that, at that point. x.a simply refers to Obj.a. I also understand that, when I assign to x.a, I create an instance variable x.a that masks the class variable Obj.a. But, while I understand that this is (at least partially) consistent with the rest of Python's declaration on assignment, I'm perplexed about why this is allowed for classes? Naively, I'd have expected that either the assignment to x.a should change Foo.a (since that's what it has referred to up to that point) or that referring to x.a prior to the assignment should be an error (e.g., "There's no instance attribute 'a'.").
Why is this behavior allowed. What — for those of us new to Python — does this kind of behavior correspond to in other OO paradigms?
Put another way: I can't think of any where you can say x.a and have it mean Obj.a and then, in the next line, say x.a = ... and have it no longer mean Obj.a. It's possible though that I'm just not remembering, and an example of that -- or confirmation that there's no such thing -- would be a perfect answer.
x.ato mutate the class ofx. In reality it mutates the instancex, but not the class; any new instances ofObjwill conform to the template in the class. Could you go into a little more detail to explain the logic that led you to this assumption?