On Sat, May 25, 2013 at 8:08 AM, Łukasz Langa <luk...@langa.pl> wrote: > The most important > change in this version is that I introduced ABC support and completed > a reference implementation.
Excellent! A couple of thoughts on the implementation... While the dispatch() method allows you to look up what implementation would be *selected* for a target type, it does not let you figure out whether a particular method has been *registered* for a type. That is, if I have a class MyInt that subclasses int, I can't use dispatch() to check whether a MyInt implementation has been registered, because I might get back an implementation registered for int or object. ISTM there should be some way to get at the raw registration info, perhaps by exposing a dictproxy for the registry. Second, it should be possible to memoize dispatch() using a weak key dictionary that is cleared if new ABC implementations have been registered or when a call to register() is made. The way to detect ABC registrations is via the ABCMeta._abc_invalidation_counter attribute: if its value is different than the previous value saved with the cache, the cache must be cleared, and the new value stored. (Unfortunately, this is a private attribute at the moment; it might be a good idea to make it public, however, because it's needed for any sort of type dispatching mechanism, not just this one particular generic function implementation.) Anyway, doing the memoizing in the wrapper function should bring the overall performance very close to a hand-written type dispatch. Code might look something like: # imported inside closure so that functools module # doesn't force import of these other modules: # from weakref import ref, WeakKeyDictionary from abc import ABCMeta cache = WeakKeyDictionary() valid_as_of = ABCMeta._abc_invalidation_counter def wrapper(*args, **kw): nonlocal valid_as_of if valid_as_of != ABCMeta._abc_invalidation_counter: cache.clear() valid_as_of = ABCMeta._abc_invalidation_counter cls = args[0].__class__ try: impl = cache.data[ref(cls)] except KeyError: impl = cache[cls] = dispatch(cls) return impl(*args, **kw) def register(typ, func=None): ... cache.clear() ... This would basically eliminate doing any extra (Python) function calls in the common case, and might actually be faster than my current simplegeneric implementation on PyPI (which doesn't even do ABCs at the moment). _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com