Prothon Prototypes vs Python Classes
Glenn Andreas
gandreas at no.reply
Mon Mar 29 13:48:02 EST 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