July 2002
Intermediate to advanced
608 pages
15h 46m
English
Credit: Ken Seehof
You need to modify the class hierarchy of an instance object that has already been instantiated.
A rather unusual application of the mix-in concept lets us perform this task in Python 2.0 or later (with some limitations in Python 2.2):
def adopt_class(klass, obj, *args, **kwds):
're-class obj to inherit klass; call _ _init_ _ with *args, **kwds'
# In Python 2.2, klass and obj._ _class_ _ must be compatible,
# e.g., it's okay if they're both classic, as in the 'demo' function
classname = '%s_%s' % (klass._ _name_ _, obj._ _class_ _._ _name_ _)
obj._ _class_ _ = new.classobj(classname, (klass, obj._ _class_ _), {})
klass._ _init_ _(obj, *args, **kwds)
def demo( ):
class Sandwich:
def _ _init_ _(self, ingredients):
self.ingredients = ingredients
def _ _repr_ _(self):
return ' and '.join(self.ingredients)
class WithSpam:
def _ _init_ _(self, spam_count):
self.spam_count = spam_count
def _ _repr_ _(self):
return Sandwich._ _repr_ _(self) + self.spam_count * ' and spam'
pbs = Sandwich(['peanut butter', 'jelly'])
adopt_class(WithSpam, pbs, 2)
print pbsSometimes class adoption, as illustrated by this recipe, is the cleanest way out of class hierarchy problems that arise when you wish to avoid module interdependencies (e.g., within a layered architecture). It’s more often useful if you want to add functionality to objects created by third-party modules, since modifying those modules’ source code is undesirable. ...