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.
You have perfectly summarized the semantics. It works this way because:
Looking up an attribute on an object has to return object attributes, how could it not?
Looking up an attribute on an object has to find a class attribute if it doesn't exist on the object, because that's how objects get methods, as well as anything else defined on the class.
Setting an attribute on an object has to create an object attribute.
Because there are no declarations in Python, the only way to create an attribute is to actually set it, so #3 has to set the attribute on the object.
I don't see a way to make 1 through 4 work without having the behavior you describe.
I'm not sure how to describe this in terms of other languages. You say, "how to think about this in OO terms." Don't fall in the trap of assuming that some other language "defines" OO. Object Orientation is done differently in all languages.
Added: You say,
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'.").
Because Python has no declarations, attributes don't exist in any way until they are assigned to. How would you ever create an object attribute if assigning to an attribute on an object didn't create it? That is, work through the example of a class with no x
attribute, and an instance of that class, what would o.x = 17
do?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With