On Mon, Jan 14, 2013 at 9:51 PM, Rodrick Brown <rodrick.br...@gmail.com> wrote: > import sys > > PY3K = sys.version_info >= (3,) > > > methods = set([ > "__iter__", > "__len__", > "__contains__", > > "__lt__", > "__le__", > "__eq__", > "__ne__", > "__gt__", > "__ge__", > > "__add__", > "__and__", > "__divmod__", > "__floordiv__", > "__lshift__", > "__mod__", > "__mul__", > "__or__", > "__pow__", > "__rshift__", > "__sub__", > "__truediv__", > "__xor__", > ]) > if PY3K: > methods.add("__next__") > methods.add("__bool__") > else: > methods.add("__div__") > methods.add("__nonzero__") > MAGIC_METHODS = frozenset(methods) > del methods > > def _build_magic_dispatcher(method): > def inner(self, *args, **kwargs): > return self.__dict__[method](*args, **kwargs) > inner.__name__ = method > return inner > > > class stub(object): > _classes_cache = {} > > def __new__(cls, **kwargs): > magic_methods_present = MAGIC_METHODS.intersection(kwargs) > if magic_methods_present not in cls._classes_cache: > attrs = dict( > (method, _build_magic_dispatcher(method)) > for method in magic_methods_present > ) > attrs["__module__"] = cls.__module__ > cls._classes_cache[magic_methods_present] = type("stub", (cls,), > attrs) > new_cls = cls._classes_cache[magic_methods_present] > return super(stub, new_cls).__new__(new_cls, **kwargs) > > def __init__(self, **kwargs): > self.__dict__.update(kwargs)
The stub class is called with keyword arguments where the keys are the names of Python "magic methods" and the values are functions. When called, it builds a new subclass of itself populated with a corresponding set of methods, each of which is built by _build_magic_dispatcher; these look up the method with the same name in the instance dictionary and delegate the call to whatever they find. For some reason that eludes me, the generated methods appear to discard the "self" argument in the process. After the subclass is generated, it constructs and returns an instance of the subclass, and then when the __init__ method is called it simply populates the instance dictionary with the functions that were passed in. The purpose of this appears to be to construct objects with magic methods that are defined on the object itself rather than on the class. Normally, when Python calls a magic method it doesn't look in the instance dictionary at all and only looks in the class dictionary. The subclasses of "stub" side-step that by having the desired magic methods on the class delegate calls to the instance. -- http://mail.python.org/mailman/listinfo/python-list