On Fri, 04 Nov 2005 02:59:35 +1100, Steven D'Aprano <[EMAIL PROTECTED]> 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: >>> def foo(): # for easy disassembly ... b.a += 2 ... b.a = b.a + 2 ... >>> import dis >>> dis.dis(foo) 2 0 LOAD_GLOBAL 0 (b) 3 DUP_TOP 4 LOAD_ATTR 1 (a) 7 LOAD_CONST 1 (2) 10 INPLACE_ADD 11 ROT_TWO 12 STORE_ATTR 1 (a) 3 15 LOAD_GLOBAL 0 (b) 18 LOAD_ATTR 1 (a) 21 LOAD_CONST 1 (2) 24 BINARY_ADD 25 LOAD_GLOBAL 0 (b) 28 STORE_ATTR 1 (a) 31 LOAD_CONST 0 (None) 34 RETURN_VALUE And BINARY_ADD calls __add__ and INPLACE_ADD calls __iadd__ preferentially. About __ixxx__: """ These methods are called to implement the augmented arithmetic operations (+=, -=, *=, /=, %=, **=, <<=, >>=, &=, ^=, |=). These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self). If a specific method is not defined, the augmented operation falls back to the normal methods. For instance, to evaluate the expression x+=y, where x is an instance of a class that has an __iadd__() method, x.__iadd__(y) is called. If x is an instance of a class that does not define a __iadd() method, x.__add__(y) and y.__radd__(x) are considered, as with the evaluation of x+y. """ ><something> to correspond to b.__class__.a = <something>? > >I'm not saying that it couldn't, if that was the model for inheritance you >decided to use. I'm asking why would you want it? What is your usage case >that demonstrates that your preferred inheritance model is useful? It can be useful to find-and-rebind (in the namespace where found) rather than use separate rules for finding (or not) and binding. The tricks for boxing variables in closures show there is useful functionality that is still not as convenient to "spell" as could be imagined. It is also useful to find and bind separately. In fact, IMO it's not separate enough in some cases ;-) I've wanted something like x := expr to spell "find x and rebind it to expr" (or raise NameError if not found). Extending that to attributes and augassign, b.a +:= 2 could mean find the "a" attribute, and in whatever attribute dict it's found, rebind it there. Or raise an Exception for whatever failure is encountered. This would be nice for rebinding closure variables as well. But it's been discussed, like most of these things ;-) Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list