Mixins For PythonRecipe for MixIns in PythonLanguage which allows in-place runtime mixing and unmixing. As a bonus, there is a 'functional-style' mixin function, which preserves the base class.
def mixIn (base, addition):
"""Mixes in place, i.e. the base class is modified.
Tags the class with a list of names of mixed members.
"""
assert not hasattr(base, '_mixed_')
mixed = []
for item, val in addition.__dict__.items():
if not hasattr(base, item):
setattr(base, item, val)
mixed.append (item)
base._mixed_ = mixed
def unMix (cla):
"""Undoes the effect of a mixin on a class. Removes all attributes that
were mixed in -- so even if they have been redefined, they will be
removed.
"""
for m in cla._mixed_: #_mixed_ must exist, or there was no mixin
delattr(cla, m)
del cla._mixed_
def mixedIn (base, addition):
"""Same as mixIn, but returns a new class instead of modifying
the base.
"""
class newClass: pass
newClass.__dict__ = base.__dict__.copy()
mixIn (newClass, addition)
return newClass
Old recipe
def mixin (existingClass, mixinClass): for item, val in mixinClass.__dict__.items(): if not hasattr(existingclass, item): setattr(existingclass, item, val)This copies not just functions, but any class members.
Example usage:
class addSubMixin: def add(self, value): return self.number + value def subtract(self, value): return self.number - value class myClass: def __init__(self, number): self.number = numberThen, at runtime, you can mix any class into any other with:
mixin(myClass, addSubMixin) myInstance = myClass(4) myInstance.add(2) myInstance.subtract(2)
why not do it like this:
class myClass(myClass, myMixin) pass
because it is not at runtime.
Person.__bases__ assignment can be made at runtime, for e.g. driver selection.
CAUTION the assignment is to the class.
Good examples of MixIns in the PythonLanguage are in SocketServer module from standard library.
such as:
class ForkingUDPServer(ForkingMixIn, UDPServer): pass class ForkingTCPServer(ForkingMixIn, TCPServer): pass class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass class ThreadingTCPServer(ThreadingMixIn, TCPServer): passYou just choose the flavors and add them in. Wants forking? add ForkingMixIn.
see also Twisted Python and wxPython for a lot of MixIn uses.
--JuneKim
This does not work for new-style classes, right?
See MixIn.
EditText of this page
(last edited June 12, 2012)
or FindPage with title or text search