Welcome, guest | Sign In | My Account | Store | Cart

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.

Python, 48 lines
 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

2 comments

Robert K 17 years, 4 months ago  # | flag

1 bug. remove "dict.pop(name)", or at least remove it with "dict.pop(name, None)".

James Taylor 16 years, 3 months ago  # | flag

Pickling. Unfortunately, pickle isn't fooled. It raises a TypeError exception

:(

Created by tomer filiba on Fri, 22 Sep 2006 (PSF)
Python recipes (4591)
tomer filiba's recipes (12)

Required Modules

  • (none specified)

Other Information and Tasks