[Python-3000] PEP 3124 - Overloading, Generic Functions, Interfaces, etc. (original) (raw)

Steven Bethard steven.bethard at gmail.com
Wed May 9 22:41:14 CEST 2007


On 4/30/07, Phillip J. Eby <pje at telecommunity.com> wrote:

PEP: 3124 Title: Overloading, Generic Functions, Interfaces, and Adaptation [snip] from overloading import overload from collections import Iterable

def flatten(ob): """Flatten an object to its component iterables""" yield ob @overload def flatten(ob: Iterable): for o in ob: for ob in flatten(o): yield ob @overload def flatten(ob: basestring): yield ob [snip] @overload vs. @when ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The @overload decorator is a common-case shorthand for the more general @when decorator. It allows you to leave out the name of the function you are overloading, at the expense of requiring the target function to be in the local namespace. It also doesn't support adding additional criteria besides the ones specified via argument annotations. The following function definitions have identical effects, except for name binding side-effects (which will be described below):: @overload def flatten(ob: basestring): yield ob @when(flatten) def flatten(ob: basestring): yield ob @when(flatten) def flattenbasestring(ob: basestring): yield ob @when(flatten, (basestring,)) def flattenbasestring(ob): yield ob [snip]

+1 on @overload and @when.

Proceeding to the "Next" Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [snip] "Before" and "After" Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [snip] "Around" Methods ~~~~~~~~~~~~~~~~ [snip] Custom Combinations ~~~~~~~~~~~~~~~~~~~

I'd rather see all this left as a third-party library to start with. (Yes, even including proceed.) It shouldn't be a problem to supply these things separately, right?

Interfaces and Adaptation -------------------------

The overloading module provides a simple implementation of interfaces and adaptation. The following example defines an IStack interface, and declares that list objects support it:: from overloading import abstract, Interface class IStack(Interface): @abstract def push(self, ob) """Push 'ob' onto the stack""" @abstract def pop(self): """Pop a value and return it"""

when(IStack.push, (list, object))(list.append) when(IStack.pop, (list,))(list.pop) mylist = [] mystack = IStack(mylist) mystack.push(42) assert mystack.pop()==42 The Interface class is a kind of "universal adapter". It accepts a single argument: an object to adapt. It then binds all its methods to the target object, in place of itself. Thus, calling mystack.push(42) is the same as calling IStack.push(mylist, 42).

+1 on adapters like this.

Interfaces as Type Specifiers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Interface subclasses can be used as argument annotations to indicate what type of objects are acceptable to an overload, e.g.:: @overload def traverse(g: IGraph, s: IStack): g = IGraph(g) s = IStack(s) # etc....

and +1 on being able to specify Interfaces as "types".

Aspects ------- [snip] from overloading import Aspect

class Count(Aspect): count = 0 @after(Target.somemethod) def countaftercall(self, *args, **kw): Count(self).count += 1

Again, I'd rather see this kind of thing in a third-party library.

Summary of my PEP thoughts:

As others have mentioned, the current PEP is overwhelming. I'd rather see Py3K start with just the basics. When people are comfortable with the core, we can look into introducing the extras.

STeVe

I'm not in-sane. Indeed, I am so far out of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy



More information about the Python-3000 mailing list