Class Variable Access and Assignment

Steven D'Aprano steve at REMOVETHIScyber.com.au
Fri Nov 4 22:37:19 EST 2005


On Sat, 05 Nov 2005 00:25:34 +0000, Bengt Richter wrote:

> On Fri, 04 Nov 2005 02:59:35 +1100, Steven D'Aprano <steve at REMOVETHIScyber.com.au> wrote:
> 
>>On Thu, 03 Nov 2005 14:13:13 +0000, Antoon Pardon wrote:
>>
>>> Fine, we have the code:
>>> 
>>>   b.a += 2
>>> 
>>> We found the class variable, because there is no instance variable,
>>> then why is the class variable not incremented by two now?
> Because the class variable doesn't define a self-mutating __iadd__
> (which is because it's an immutable int, of course). If you want
> b.__dict__['a'] += 2 or b.__class__.__dict__['a'] += 2 you can
> always write it that way ;-)
> 
> (Of course, you can use a descriptor to define pretty much whatever semantics
> you want, when it comes to attributes).
> 
>>
>>Because b.a += 2 expands to b.a = b.a + 2. Why would you want b.a =
> 
> No, it doesn't expand like that. (Although, BTW, a custom import could
> make it so by transforming the AST before compiling it ;-)
> 
> Note BINARY_ADD is not INPLACE_ADD:

Think about *what* b.a += 2 does, not *how* it does it. Perhaps for some
other data type it would make a difference whether the mechanism was
BINARY_ADD (__add__) or INPLACE_ADD (__iadd__), but in this case it does
not. Both of them do the same thing.

Actually, no "perhaps" about it -- we've already discussed the case of
lists.

Sometimes implementation makes a difference. I assume BINARY_ADD and
INPLACE_ADD work significantly differently for lists, because their
results are significantly (but subtly) different:

py> L = [1,2,3]; id(L)
-151501076
py> L += [4,5]; id(L)
-151501076
py> L = L + []; id(L)
-151501428


But all of this is irrelevant to the discussion about binding b.a
differently on the left and right sides of the equals sign. We have
discussed that the behaviour is different with mutable objects, because
they are mutable -- if I recall correctly, I was the first one in this
thread to bring up the different behaviour when you append to a list
rather than reassign, that is, modify the class attribute in place.

I'll admit that my choice of terminology was not the best, but it wasn't
misleading. b.a += 2 can not modify ints in place, and so the
effect of b.a += 2 is the same as b.a = b.a + 2, regardless of what
byte-codes are used, or even what C code eventually implements that
add-and-store.

In the case of lists, setting Class.a = [] and then calling instance.a +=
[1] would not exhibit the behaviour Antoon does not like, because the
addition is done in place. But calling instance.a = instance.a + [1]
would.

My question still stands: why would you want instance.a = <something>
to operate as instance.__class__.a = <something>?


-- 
Steven.




More information about the Python-list mailing list