let's start with a question: ========== >>> class z(object): ... def __init__(self): ... self.blah=5 ... >>> class x(object): ... def __init__(self): ... z.__init__(self) ... >>> y=x() Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in __init__ TypeError: unbound method __init__() must be called with z instance as first argument (got x instance instead) ==========
and the question is -- WHY? what is a type? generally speaking, if everything were an object, the type only defines the MRO (method resolution order) for that object. x.y first looks at the instance, then the class, then the parent classes, etc. (this was changed a little in python2.3 to something more complicated, but it's basically the same). you can see the mro like this: ========== >>> class x(object): pass >>> class y(x): pass >>> class z(y): pass >>> a=z() >>> print a.__class__.mro() [<class '__main__.z'>, <class '__main__.y'>, <class '__main__.x'>, <type 'object'>] ========== after all, if we stay out of builtin types, all python objects are dicts, which support chian-lookup according to the mro. and a method is just a function that takes the instance as a first argument. so why is all this type hassle necessary? if we've taken it that far already, then let's really go over the edge. I WANT TO DERIVE FROM INSTANCES. not only types. why? i'm the developer of rpyc (http://rpyc.sf.net), and i got a request from someone to add support for deriving from remote types. the concrete example he gave was quite silly, but after i thought about it a little, i said why not try? a little intro about rpyc: it gives you proxies (instances) to remote objects, which can be instances, functions, or classes. and that user wanted to do something like this: class my_frame(conn.modules.wx.Frame): ... so the client was actually creates the graphics on the server. not very usable, but why not? all it means is, when he does "my_frame.xyz", python should add the remote type to the mro chain. not too bizar. but __mro__ is a readonly attribute, and deriving from instances is impossible (conn.modules.wx.Frame is a PROXY to the class)... and again -- WHY? these all look like INTENTIONAL limitations. someone went around and added type checks (which are NOT pythonic) into the cPython implementation. argh. why do that? so i thought -- let's be nasty. i created a function that creates a class that wraps an instance. very ugly. small children and peope with heart problems should close their eyes. ============ def derive_from(obj): class cls(object): def __getattr(self, name): return getattr(obj, name) return cls class my_frame(derive_from(conn.modules.wx.Frame)): .... ============ the actual implementation is quite more complex, but that shows the concept. so now i'm experimenting with that little shit. but then i came to the problem that methods check the type of the first argument... ARGH. dont check types. DONT. the whole point of duck-typing is you DONT CHECK THE TYPES. you just work with objects, and instead of TypeError you'd get AttribiuteError, which is much better. AAARRRRRRGGGHH. python is EVIL at the low level. the high-level is just fine, but when you try to go under the hood... you better go with an exorcist. -tomer -- http://mail.python.org/mailman/listinfo/python-list