[issue5135] Expose simplegeneric function in functools module

Phillip J. Eby report at bugs.python.org
Sat Mar 26 02:37:33 CET 2011


Phillip J. Eby <pje at telecommunity.com> added the comment:

Just as an FYI, it *is* possible to do generic functions that work with Python's ABCs (PEAK-Rules supports it for Python 2.6), but it requires caching, and a way of handling ambiguities.  In PEAK-Rules' case, unregistering is simply ignored, and ambiguity causes an error at call time.  But simplegeneric can avoid ambiguities, since it's strictly single-dispatch.  Basically, you just have two dictionaries instead of one.

The first dictionary is the same registry that's used now, but the second is a cache of "virtual MROs" you'll use in place of a class' real MRO.  The virtual MRO is built by walking the registry for classes that the class is a subclass of, but which are *not* found in the class's MRO, e.g.:

    for rule_cls in registry:
        if issubclass(cls, rule_cls) and rule_cls not in real_mro:
            # insert rule_cls into virtual_mro for cls

You then insert those classes (abcs) in the virtual MRO at the point just *after* the last class in the MRO that says it's a subclass of the abc in question.

IOW, you implement it such that an abc declaration appears in the MRO just after the class that was registered for it.  (This has to be recursive, btw, and the MRO cache has to be cleared when a new method is registered with the generic function.)

This approach, while not trivial, is still "simple", in that it has a consistent, unambiguous resolution order.  Its main downside is that it holds references to the types of objects it has been called with.  (But that could be worked around with a weak key dictionary, I suppose.)  It also doesn't reset the cache on unregistration of an abc subclass, and it will be a bit slower on the first call with a previously-unseen type.

The downside of a PEP, to me, is that it will be tempting to go the full overloading route -- which isn't necessarily a bad thing, but it won't be a *simple* thing, and it'll be harder to get agreement on what it should do and how -- especially with respect to resolution order.

Still, if someone wants to do a PEP on *simple* generics -- especially one that can replace pkgutil.simplegeneric, and could be used to refactor things like copy.copy, pprint.pprint, et al to use a standardized registration mechanism, I'm all in favor -- with or without abc registration support.

Btw, the current patch on this issue includes code that is there to support classic classes, and metaclasses written in C.  Neither should be necessary in 3.x.  Also, a 3.x version could easily take advantage of type signatures, so that:

@foo.register
def foo_bar(baz: bar):
    ...

could be used instead of @foo.register(bar, foo_bar).

But all that would be PEP territory, I suppose.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue5135>
_______________________________________


More information about the Python-bugs-list mailing list