[Types-sig] Why have two hierarchies? (*EUREKA!*)
Just van Rossum
just@letterror.com
Sat, 5 Dec 1998 20:47:18 +0100
Evan Simpson wrote:
><Applaud!><Whistle!><Cheer!><WooHoo!>
<bow>
(-- sounds of grumbling demi-gods in the back of the room --)
Cool summary, mostly correct. A couple of comments and a question in return.
>2. Objects are based on other objects. This forms an inheritance/delegation
>DAG exactly like current class DAGs.
What is a DAG?
>3. If you give an object a name, you've made a class.
That *could* be a possibility. So far, it makes a lot of sense to me, but
this detail is not very important: as long as there is _some_ way to
distinguish a class form an instance.
>This allows you to search the inheritance DAG by name.
Sorry, I don't follow. What is a DAG?
>6. When a function 'f' is an attribute of a named object, the object's kids
>see 'f' as a method. Named kids see 'f' unbound, unnamed kids see it bound
>to themselves. QUESTION: How do bound methods behave? Do they require an
>unnamed object (an 'instance')?
Not as far as I'm concerned: a bound method will probably automatically
have an im_self attribute of the right class, but if you're calling an
unbound method I strongly feel it's the responsibility of the caller to
pass an object (*whatever* object) that the unbound method can handle.
>7. (Not sure on this one) An object can bind a method to itself before
>handing it to its kids, thus allowing the elusive static class method to be
>realized.
Not sure about this one myself. The easy way is to keep doing what we've
always done:
MyClass.foo(MyClass, ...)
>What about:
>11. "class A2(a):" constructs an object as in #9, but its base is the
>unnamed object from #10.
>Do we allow this, or require bases to be named? If we allow it, do we allow
>"b = a()"?
That maybe a fuzzy part of my scheme indeed. I haven't fully thought this
part through yet.
>How does this mix with __call__?
My demo implementation is broken in this respect. After I posted the stuff
I thought of the obvious solution. Hm, solution is the wrong word: I just
implemented existing Python's call semantics wrongly. It _should_ work like
this:
- if the object we're calling is an instance, search for a
__call__ method
- if the object we're calling is a class, do one of these (don't know
what's better, possibly the latter):
a) construct a new class with (name, (self,), {}) as arguments,
search for an __init__ method, call it if found. (just like
Python Classic)
or
b) search for a __instantiate__ method, let it handle (a)
>12. "a = class (A):" or "a = object (A):" could be a synonym for #2, but
>allow a code suite to execute in the context of 'a's namespace.
I don't quite follow...
>13. "a = class:" or "a = object:" could perform the same function for
>baseless objects.
>We would now have a simple way to spell nested structures:
>
>a = object:
> a1 = 1
> def null(): pass
> a2 = object:
> b = "hi!"
>#a.a2.b == "hi!"
>#a.null is a function, not a method!
Hmmm, not bad... But it is the same as:
class a:
a1 = 1
a1 = 1
def null(): pass
a2 = object:
b = "hi!"
a.__name__ = None
;-)
>14. "5.__base__ is type(5) is Integer", "5" is nameless, and "
>type(5).__name__=='Integer' ".
I don't know what you mean by type... But yes, something in __bases__ makes
it an integer.
>15. The holy grail "class myInt(Integer):" is attainable.
Phew.
>*** last minute thought ***
>
>I am bothered by the need to search the inheritance DAG for attribute
>operators every time you use one. Caching and other possible optimizations
>don't make me feel any better - I can't say exactly why.
I have similar feelings. Right now, my helper method __getattr_from_bases__
uses __getattr__ on each of the bases. Maybe it should just recursively
search their __namespaces__. If you want to override that behaviour: just
define a custom __getattr__ which does what you want.
>Suppose objects could have a __birth_hook__ method, called every time a new
>descendent is created.
Right, this is exactly what I meant with __instantiate__ above.
>Unlike __init__, this would be called on named and
>unnamed objects alike, and before __init__ for unnamed objects.
Erm, confusion: are you creating an unnamed object from a named base or a
named or unnamed object from an unnamed object???
>Objects
>which redefine __init__ have to cooperate with ancestral __init__s by
>calling them explicitly, but __birth_hook__ is forced on them. It would be,
>among other things, a chance to install __*attr__ hooks into the namespace
>of the new object. "Static class methods" could be installed in subclasses
>(kids with names). We could keep the current namespace-then-delegate model,
>but still allow hookers ;-)
At the conference hotel in Houston, there was a bar called "Hookers Nook"...
Just