Function/Operator Overloading Demo for Py3K =========================================== Signature Definition -------------------- Because existing versions of Python don't support argument type annotations, we'll use a ``@signature`` decorator to tack a ``__signature__`` attribute on to functions. Because the final format for ``__signature__`` isn't decided, we'll use a very ad-hoc approach for now:: >>> from overloading import signature >>> @signature(int, int) ... def intadd(a, b): ... return a+b >>> intadd.__signature__ ((, ), {}) We'll assume that it's straightforward to change code based on this ad-hoc approach to use whatever is finally decided on for the ``__signature__`` format. Simple Overloading ------------------ We now need to be able to create overloaded function objects and add methods to them. We'll use Guido's simple timing test cases:: >>> from overloading import overloaded, defop >>> class A(object): pass >>> class B(object): pass >>> class C(A, B): pass >>> def default(x, y): return "default" >>> @overloaded ... def automatic(x, y): ... return default(x, y) >>> automatic(1,2) 'default' >>> @defop(automatic) ... @signature(A, B) ... def methodAB(x, y): return "AB" >>> @defop(automatic) ... @signature(A, C) ... def methodAC(x, y): return "AC" >>> @defop(automatic) ... @signature(B, A) ... def methodBA(x, y): return "BA" >>> @defop(automatic) ... @signature(C, B) ... def methodCB(x, y): return "CB" >>> automatic(A(), B()) 'AB' >>> automatic(B(), C()) 'BA' Operation-based Overloading --------------------------- We can define a signature by reference to an existing overloaded function. For our example, we'll define a generic function for ``iter()``, registering the built-in ``iter()`` function for various types. (Since we don't have a built-in generic function type in Python yet.):: >>> my_iter = overloaded() >>> my_iter[list] = my_iter[str] = my_iter[tuple] = iter >>> @defop(my_iter) ... @signature(list) ... def iter_list(ob): ... return iter(ob) >>> @overloaded ... def flatten(ob): ... yield ob >>> @defop(flatten) ... @signature(my_iter) ... def flatten_iterable(ob): ... for item in ob: ... for item in flatten(item): ... yield item >>> @defop(flatten) ... @signature(basestring) ... def flatten_stringlike(ob): ... yield ob >>> list(flatten(None)) [None] >>> list(flatten(["x", ["y", 1]])) ['x', 'y', 1] Creating Custom Overloading --------------------------- By overloading the ``type_matches()``, ``implies()``, and ``overloads()`` functions, you can create your own specialized versions of @overloaded that use custom dispatch rules.