Guido van Rossum wrote: > > > We are actually trying to turn classes into types here :-) > > Yes! Wait till you see my next batch of checkins. :-) Looking forward to them :) BTW, can you give a good starting point into all this (code wise and concept wise) ? I'd like to play around these new concepts a litte to get a beeter feeling for the possible issues (I should have done the same for the coercion stuff a year ago: implementing mxNumber I now find that some important hooks are missing :-(). > > Really, I think that we could resolve this issue by not inheriting > > from meta-classes. DictType is a creation of the meta-class > > TypeType. I'm not calling these instances to prevent additional > > confusion. The root of the problem is that for some reason there > > is belief that DictType should implicitly inherit attributes and > > methods from TypeType. If we simply say that there is no implicit > > inheritance (only explicit one), then these problems should go > > away. > > Sorry, you still seem to be confused about this. I think it has to do with terminology: when I say "inherit" I actually mean "the lookup is forwarded to the another object". In that sense, instances inherit from their classes and classes from their base-classes: meta-class M -> o base-class A o class B o instance x = B() Meta-class M control this "inheritance scheme" and can modify it depending on its needs. Here's a scenario of what I have in mind: In the above picture, say A defines an attribute A.a which is not defined in B or as instance attribute of B(). Querying x.a would then launch this process: 1. x.a -> fails 2. M.__findattr__(x, 'a') is called to find and return the attribute 3. M.__findattr__ asks B for an attribute 'a' -> fails 4. -- " -- asks A -- " -- -> success 5. -- " -- returns the found attribute I know that this is somewhat different under the covers than what's happening now, but the Python programmer will not notice this. It most probably does not work well with the Don Beaudry hook though... so maybe I'm simply on the wrong track here. > As I tried to > explain before, DictType does not *inherit* from TypeType, but it is > an *instance* of TypeType. TypeType defines a __repr__() method for > all its instances. This is needed so that repr(DictType) returns > "<type 'DictType'>". It is *not* inherited from TypeType! > > If DictType were to inherit from something, it would inherit from the > (not yet existing) ObjectType. ObjectType would have a __repr__ > method too: it returns "<foo object at 0x......>". > > But this method is overridden by DictType, so doesn't come into play. > > Requiring explicit inheritance (whatever that may be) won't fix the > problem. With "explicit inheritance" I meant that the programmer has to take care of passing the lookup on to the meta-class, rather than applying some magic which hooks together class and meta- class. > > Some of these ideas are burried in the "super" part of this > > thread. Unfortunately this concept doesn't go very far since > > Python has multiple inheritance and thus the term "super" > > (referring to the class' single base class) is not well-defined. > > Not true. While super can't always refer to a single class, the use > of super can be completely well-defined in an unambiguous way. Given > > class D(A, B, C): > def foo(self): > super.foo(self) > > "super.foo" is whatever would be called in D1 if we changed the class > hierarchy as follows: > > class D1(A, B, C): pass > class D(D1): > def foo(self): > D1.foo(self) Nice trick -- much like the "+0" trick in math ;-) > The problem with super is not that it isn't well-defined. Its problem > is that it's not enough to do what you want. In some situations > involving multiple inheritance, it can be essential to be able to > "merge" methods of the sane name defined in each of the base classes, > e.g. > > class C(A, B): > def save(self): > A.save(self) > B.save(self) > > So we can't use super as an argument to abandon explicitly naming the > base class of base methods. Out of the proposed spellings that I can > remember: > > B.save(self) # current Python > B.__dict__['save'](self) # ditto, butt ugly > B::save(self) # C++ > B._.save(self) # Don Beaudry > B.instanceMethods.save(self) # ??? > > I still like current Python best! But it doesn't help us in the very common case of mixin classes since there the method and sometimes even not the programmer will know where the basemethod to call lives. This is why I wrote the basemethod() helper: it looks up the right method at run-time and thus allows writing mixin-classes which override methods of other classes which are only known to the programmer using the mixin and not necessarily to the one writing the mixin. > > As Jim mentioned in his reply to Thomas' question, SmallTalk > > has two parallel hierarchies. One for the classes and one for > > the meta-classes. If we follow the same path in Python and > > keep the two well separated, I think we can resolve many of > > the issues which are currently showing up. > > Yeah, but this is not the path that Python has already taken (and > which has been beaten further by Jim Fulton's ExtensionClasses). > Python's path is "turtles all the way down". See also my old > head-exploding metaclasses paper. I know... I was under the impression, though, that a little breakage under the covers is allowed when moving from type/classes to all types. > > To link the two hierarchies together we don't need a "super" > > concept, but instead a way to reach the meta-class in charge > > of a class, say "klass.__creator__". > > Your confusion between the "isInstanceOf" and "isInheritedFrom" > relationships seems really deep! Super relates to inheritance. > Metaclasses relate to instantiation (of the class, as an instance of > the metaclass). See above... I don't like implicitely binding creation of objects with lookup paths. These two concepts don't belong together, IMHO, since they introduce restrictions which are not really necessary. (I have made some great experience with loosly coupled object systems and don't want to miss their flexibility anymore.) > > Note that there's another issue hiding in all this and again > > this is due to multiple inheritance: which meta-class is in > > charge of a class which is derived from two classes having > > different meta-classes ? > > > > meta1 --> o klass1 > > o klass1a > > o klass1b > > meta2 --> o klass2 > > o klass2a > > o klass2b > > > > class klass3(klass1a, klass2b): > > ... > > > > I think there's no clean way to resolve this, so I'd suggest > > to simply rule this out and declare it illegal (class can > > only be based on classes having the same meta-class). > > Unfortunately, again thanks to Jim Fulton, we can't rule this out, > because this is actually used by ExtensionClasses. The rule (as I > interpret it) gives the first base class control; if the first base > class is a standard class, it looks if any of the other base classes > are not standard classes, and if so, gives control to the first such > base class. Another way to say this is that the first base class that > has a non-standard metaclass gets control. Ouch. Still, since Jim's in control of ExtensionClass -- wouldn't it be possible to adapt ExtensionClass to an altered scheme ? > (ExtensionClasses implements an additional rule where it requires all > except one of the base classes to define no instance variables. This > is an example of the importance of metaclasses done right: the > metaclass has control over such issues. I don't think that > Smalltalk's metaclasses have this much control -- you pretty much have > a 1-1 correspondence between class and metaclass. Right: more power to the meta-class :-) -- Marc-Andre Lemburg ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.lemburg.com/python/
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4