pondering about the essence of types in python

gangesmaster tomerfiliba at gmail.com
Sat Mar 25 15:29:07 EST 2006


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




More information about the Python-list mailing list