[Types-sig] New article + demo
Gordon McMillan
gmcm@hypernet.com
Mon, 7 Dec 1998 18:17:34 -0500
Just van Rossum writes:
> I've added two graphs (technically: Dumb Art Graphs) to the article.
> They prove either:
>
> - that I'm wrong, since they show that my scheme is just
> as complex as one which does have "real" metaclasses.
>
> - that I'm right, in sofar that my scheme is equivalent to
> one which does have "real" metaclasses.
>
> Or both. ;-)
Well your graphs don't really measure complexity. Nor is complexity
really the major issue. Nor have we found out how complex things
really get.
The important thing is unearthing and discussing (the more violently,
the better <wink>) what we all expect out of a class model.
For example, you get rid of the difference between an instance and a
subclass, then reimpose one simply for the sake of having one.
(Whatsamatta, Just, you chicken? Huh??).
Disposing of that distinction (depending on how it's done) could
have quite a few consequences. Conceptually, current Python
fits with class models that say an intance is fundamentally
different than a class. (Python's dynamic nature does make it
somewhat more difficult to classify than most languages). Classes
hold behavior, instances hold state, and an instance's class can be
regarded as one, unified thing, created by munging together all of
the bases. (The fact that __bases__ is a tuple of a bunch of
different objects is an implementation detail; behavior is pretty
much a done deal once __bases__ has been specified).
You are now holding state all through the hierarchy. Which might
yield some unexpected results:
class A:
def static_modifying_method(...)
#this somehow modifies state
class X(A,B):
#whatever
class Y(C, A):
#whatever
y = Y()
r1=y.whatsit() #results depend on state held in A
x = X()
x.static_modifying_method(...) #state changed
r2=y.whatsit() #hey, wait a minute - results are different!!!
To tell the truth (generally a bad idea on Usenet <wink>) I'm not
quite sure what I'm whining about. Is it:
1) In current Python, all the mutable stuff (in the absence of
sufficient perversity) is confined to the instance, which makes me
feel safe and comfortable, (stop laughing, Tim!).
2) The fact that it appears this proposal will mean that the
inheritance DAG will actually have something to do with the runtime
structure. Coming from the C++ world, I'm used to inheritance being
simply a way to structure code, not objects.
3) Confusion about "static" methods vs. "class" methods; what the
latter are useful for, and if the 2 flavors can co-exist.
This deserves some discussion, actually. "Static" methods are
generally justified as a way to hold code in a sensible place - they
do something related to secret knowledge the class has, but don't
need an instance. This usage registers about a .01 on my personal
Richter scale. I use static methods in C++, but to me they're a "so
what".
I use "static" in C++ to create singletons - make all the state
static, and all the instances you create are really the same
instance. Hee, hee. Very handy. Due to the syntax of C++, if I
subclass one of these guys, I get a completely independent (set of)
singletons.
Is this what "class" methods (with a __class_self__) are for? How do
they behave when subclassed?
I'm also concerned with the installation of __getattr__ hooks. You're
currently looking for *some* __getattr__ hook in the bases, and using
that. But is that a depth first search? Or just a search of
__bases__? If I have:
class A(Trace):
#blah
class B(A)
def mymethod(self, arg): #blah
b = B()
Will "b.mymethod(1)" trace?
And more generally (in anybody's scheme), how do you handle multiple
__getattr__ hooks? Just take the first? The last? Let one wrap the
attribute and hand it to the next to wrap again?
discussing-behaviors-at-the-edge-of-a-black-hole-ly y'rs
- Gordon