[Python-3000] my take on "typeclasses"

tomer filiba tomerfiliba at gmail.com
Tue May 9 22:31:02 CEST 2006


i was having lots of thoughts about types in general, and what they mean
in python, and i came to the conclusion they types are basically useless.
after all, "proper duck typing" is something like:

def myfunc(myarg):
    myarg.mymethod(1,2,3)

RATHER THAN

def myfunc(myarg):
    assert type(myarg) == mytype
    myarg.mymethod(1,2,3)

-----

sorry for spamming on RPyC here, but i feel i need to provide just some
background info on how it works: it gives you a proxy to a remote object, thus
doing x.y() or x+z, etc., invokes the correct methods of the remote object and
returns the result (or exception). this allows you to work with remote objects
just like they were local ones --

but object proxying doesnt work when you "assert type(x) == y" or
isinstance(x,y), as those functions test for properties of the PROXY, not the
remote object. so code like that break RPyC.

assuring type correctness is useless -- you just check the type and raise
an exception. the difference being instead of AttributeError you'll get a
TypeError. one runtime error instead of another... quite meaningless.
perhaps the latter is more descriptive, but if you think about it for a minute,
AttributeError is basically equivalent to TypeError.

and the very essence of types is quite meaningless in dynamic languages.
in compiled languages, they define how casting is done, what operations the
object supports, etc. etc., but in python, they all just narrow down
to "hasattr()",
i.e., "is the object addable?" == "hasattr(obj, '__add__')".

there are only two things types are good for:
* overloading ("generic functions"), i.e.,
if type(x) == int:
    dothis()
else:
    dothat()
* early error reporting -- can be quite useful to raise the exception as early
as possible

for those two features, i'd suggest an "isproto" mechanism, that checks if
the object supports a certain protocol:

iterable_protocol = ["__iter__"]
sequence_protocol = ["__getitem__", "__setitem__",
"__contains__", "__iter__"]
file_protocol = ["write", "read", "close", "fileno"]
sortable_protocol = ["__lt__", "__gt__", "__eq__"]

def f(somefile):
    assert isproto(somefile, file_protocol)
    f.write(...)

and isproto just checks the object has the requested attributes. can be as
simple as

def isproto(obj, attrs):
    for attr in attrs:
        if not hasattr(obj, attr):
            return False
    return True

and of course you don't need to remember all the attributes you'll ever
use --

class x(object):
    def f(self):
        pass

obj = x()
assert isproto(obj, dir(x))

or have isproto acces type objects as well

-------

i'm sure my idea has flaws, but i'm very much pro-changing the type system.
i'm not familiar with haskell, but if i understand Phillip's ideas right, they
woudl allow better object proxying, and i'm very +1 on that.

types are just an ancient relic, an implementation detail if you wish, that
was brought from static languages, but is not appropriate to dynamic
languages. static languages NEED types in order to produce machine
code, dynamic languages don't, so a different mechanism is needed here,
imho.


-tomer


More information about the Python-3000 mailing list