Re:WTFPython: Exploring and understanding Python through sur...
by masklinn on Tuesday May 31, 2022 @02:54PM
(#31573370)
> The value of A.b can, incidentally be accessed via obj.b because obj.b does not exist and the lookup path for instance attributes includes the class. [...] the += operator, which calls the __iadd__ method on the left value or acts as add and then assign to the name on the left, if that name doesn't reference a value that supports __iadd__.
That is not correct. += will always perform the assignment, hence the classic oddball concatenation:
>>> v = ([],)
>>> v
([],)
>>> v[0] += [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> v
([1],)
So `obj.b += [2]` desugars to something along the lines of:
l = obj.b
l.extend(2)
obj.b = l
Hence if you call vars() on the instance or access its __dict__, you will see that the instance does have an intrinsic "b" attribute:
>>> class A: b = [1]
...
>>> a = A()
>>> a.b += (2,)
>>> vars(a), a.__dict__
({'b': [1, 2]}, {'b': [1, 2]})
And if you re-set the attribute on the class, it won't affect the instance, which it would if the instance delegated to the class:
That is not correct. += will always perform the assignment, hence the classic oddball concatenation:
So `obj.b += [2]` desugars to something along the lines of: Hence if you call vars() on the instance or access its __dict__, you will see that the instance does have an intrinsic "b" attribute: And if you re-set the attribute on the class, it won't affect the instance, which it would if the instance delegated to the class: