On Sun, 06 Nov 2005 15:17:18 +1100, Steven D'Aprano <[EMAIL PROTECTED]> wrote:
>On Sat, 05 Nov 2005 18:14:03 -0800, Paul Rubin wrote: > >>> instance.attribute sometimes reading from the class attribute is a feature >>> of inheritance; instance.attribute always writing to the instance is a >>> feature of OOP; instance.attribute sometimes writing to the instance and >>> sometimes writing to the class would be, in my opinion, not just a wart >>> but a full-blown misfeature. >> >> But that is what you're advocating: x.y+=1 writes to the instance or >> the class depending on whether x.y is mutable or not. > >Scenario 1: > >Pre-conditions: class.a exists; instance.a exists. >Post-conditions: class.a unchanged; instance.a modified. > >I give that a big thumbs up, expected and proper behaviour. > >Scenario 2: > >Pre-conditions: class.a exists and is immutable; instance.a does not >exist. >Post-conditions: class.a unchanged; instance.a exists. > >Again, expected and proper behaviour. > >(Note: this is the scenario that Antoon's proposed behaviour would change >to class.a modified; instance.a does not exist.) > >Scenario 3: > >Pre-conditions: class.a exists and is mutable; instance.a exists. >Post-conditions: class.a unchanged; instance.a is modified. > >Again, expected and proper behaviour. > >Scenario 4: > >Pre-conditions: class.a exists and is mutable; instance.a does >not exist. >Post-conditions: class.a modified; instance.a does not exist. > Are you saying the above is what happens or what should happen or not happen? It's not what happens. Post-conditions are that class.a is modified AND instance.a gets a _separate_ reference to the same result. Note: Python 2.4b1 (#56, Nov 3 2004, 01:47:27) [GCC 3.2.3 (mingw special 20030504-1)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> class A(object): ... a = [] ... >>> b=A() >>> id(A.__dict__['a']) 49230700 >>> b.a += [123] >>> id(A.__dict__['a']) 49230700 >>> id(b.__dict__['a']) 49230700 >>> (b.__dict__['a']) [123] >>> (A.__dict__['a']) [123] Let's eliminate the inheritable class variable A.a: >>> del A.a >>> b.a [123] >>> id(b.__dict__['a']) 49230700 >>> vars(b) {'a': [123]} Make sure we did eliminate A.a >>> vars(A) <dictproxy object at 0x02E817AC> >>> vars(A).keys() ['__dict__', '__module__', '__weakref__', '__doc__'] Is that the "wart" you were thinking of, or are you actually happier? ;-) >Well, that is a wart. It is the same wart, and for the same reasons, as >the behaviour of: > >def function(value=[]): > value.append(None) IMO that's not a wart at all, that's a direct design decision, and it's different from the dual referencing that happens in Scenario 4. > >I can live with that. It is a familiar wart, and keeps inheritance of >attributes working the right way. And who knows? If your attributes are >mutable, AND you want Antoon's behaviour, then you get it for free just by >using b.a += 1 instead of b.a = b.a + 1. Not quite, because there is no way to avoid the binding of the __iadd__ return value to b.a by effective setattr (unless you make type(b).a a descriptor that intercepts the attempt -- see another post for example). Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list