This code here creates real mixed-in classes: it actually merges one class into another (c-python specific), taking care of name-mangling, some complications with __slots__, and everything else. As a side-effect, you can also use it to mix modules into classes. Similar to ruby's include statement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import inspect
def mixin(cls):
"""
mixes-in a class (or a module) into another class. must be called from within
a class definition. `cls` is the class/module to mix-in
"""
locals = inspect.stack()[1][0].f_locals
if "__module__" not in locals:
raise TypeError("mixin() must be called from within a class definition")
# copy the class's dict aside and perform some tweaking
dict = cls.__dict__.copy()
dict.pop("__doc__", None)
dict.pop("__module__", None)
# __slots__ hell
slots = dict.pop("__slots__", [])
if slots and "__slots__" not in locals:
locals["__slots__"] = ["__dict__"]
for name in slots:
if name.startswith("__") and not name.endswith("__"):
name = "_%s%s" % (cls.__name__, name)
dict.pop(name)
locals["__slots__"].append(name)
# mix the namesapces
locals.update(dict)
#
# example
#
>>> class SomeMixin(object):
... def f(self, x):
... return self.y + x
...
>>> class AnotherMixin(object):
... def g(self):
... print "g"
...
>>>
>>> class Foo(object):
... mixin(SomeMixin)
... mixin(AnotherMixin)
...
... def h(self):
... print "h"
...
|
see http://sebulba.wikispaces.com/recipe+real+mixins for more info and code snippet
Tags: extending
1 bug. remove "dict.pop(name)", or at least remove it with "dict.pop(name, None)".
Pickling. Unfortunately, pickle isn't fooled. It raises a TypeError exception
:(