Prothon Prototypes vs Python Classes

Glenn Andreas gandreas at no.reply
Mon Mar 29 20:48:02 CEST 2004


In article <slrnc6gc7a.i1i.joe at gate.notcharles.ca>,
 Joe Mason <joe at notcharles.ca> wrote:

> In article <mailman.55.1080568422.20120.python-list at python.org>, Jeff Epler 
> wrote:
> >> BTW, I've got three pure-python solutions now (four when this one's
> >> fixed) but it turns out they all suffer from a flaw:
> >> 
> >> >>> class TestProto: l = []
> >> ... 
> >> >>> class Test2(TestProto): pass
> >> ... 
> >> >>> TestProto.l
> >> []
> >> >>> Test2.l
> >> []
> >> >>> Test2.l.append(0)
> >> >>> Test2.l
> >> [0]
> >> >>> TestProto.l
> >> [0]
> >> 
> >> We really need copy-on-write lists and dicts - and large objects in
> >> general - for this to work.
> > 
> > Can't you just follow the Python rule for classes with a little
> > difference?
> > * if you want some data to be shared by reference among the Prototype
> >   and all its children, declare it at 'prototype' ('class') scope
> > * if you don't, create it in __init__
> 
> Possibly.  You need something, at least - full copy-on-write seems like
> the most transparent, but also the most work to set up.  (I'm still
> reading up on Self and others to find out how they handle these things.)

copy-on-write wouldn't handle the above issue though, since you aren't 
writing Test2.l, you are sending a message to Test2.l (which may, or may 
not, mutate Test2.l).  You could provide some formalization of "mutable" 
vs "immutable" and make copy-on-mutate, but even that is subtle - at 
what point does something count as being "mutated"?  If you've got an 
immutable array of object and you call a mutating method of one of those 
objects, does the original mutate (and invoke copy-on-mutate)?

Or even simpler, even if you can catch:

   Test2.l.append(0)

to be copy-on-mutate, what about:

   x = Test2.l
   x.append(0)

Since that would be identical to:

   x = TestProto.l
   x.append(0)

how would you tell the difference?


Self basically provides two different methods for getting & setting 
instance variables, both of which can be replaced independantly.  The 
"setter" part is more interest for this since "foo.bar = 5" is just 
synatic sugar for "foo x: 5" (which by default will simply set the "x" 
slot equal to the value, so when you then execute "foo x" you get that 
new value).

It does take a while to wrap your brain around the subtle edge cases 
here, especially when combined with multiple inheritance (since the 
setter and getter might both come from a different parent then), but 
"Organizing Programs Without Classes" [Ungar, Chambers, Chang, Holzle] 
is well worth reading, re-reading, and digging out an reading again 
every couple of years.



More information about the Python-list mailing list