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. 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) 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. > Say you have an > immutable class with a mutable subclass or vice versa. You'd like to > be able to replace a class instance with a subclass instance and not > have the behavior change (Liskov substitution principle), etc. That's easy. You just have to make sure that the subclass implements __iadd__ the same way that the immutable parent class does. You can't expect a class that performs += in place to act the same as a class that doesn't perform += in place. Excessive data abstraction, remember? L = list("Liskov substitution principle") L.sort() # sorts in place print L # prints the sorted list class immutable_list(list): # __init__ not shown, but does the right thing def sort(self): tmp = list(self) tmp.sort() return immutable_list(tmp) L = immutable_list("Liskov substitution principle") L.sort() # throws the sorted list away print L # prints the unsorted list The only way the Liskov substitution principle works is if everything works the same way, which means that all subclasses, all *possible* subclasses, must have no more functionality than the subclass that does the absolute least. Since the least is nothing, well, you work it out. -- Steven. -- http://mail.python.org/mailman/listinfo/python-list