[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