Dynamically mixin a base class to an instance in Python Dynamically mixin a base class to an instance in Python python python

Dynamically mixin a base class to an instance in Python


This dynamically defines a new class GentlePerson, and reassigns p's class to it:

class Gentleman(object):  def introduce_self(self):    return "Hello, my name is %s" % self.nameclass Person(object):  def __init__(self, name):    self.name = namep = Person("John")p.__class__ = type('GentlePerson',(Person,Gentleman),{})print(p.introduce_self())# "Hello, my name is John"

Per your request, this modifies p's bases, but does not alter p's original class Person. Thus, other instances of Person are unaffected (and would raise an AttributeError if introduce_self were called).


Although it was not directly asked in the question, I'll add for googlers and curiosity seekers, that it is also possible to dynamically change a class's bases but (AFAIK) only if the class does not inherit directly from object:

class Gentleman(object):  def introduce_self(self):    return "Hello, my name is %s" % self.nameclass Base(object):passclass Person(Base):  def __init__(self, name):    self.name = namep = Person("John")Person.__bases__=(Gentleman,object,)print(p.introduce_self())# "Hello, my name is John"q = Person("Pete")print(q.introduce_self())# Hello, my name is Pete


Slightly cleaner version:

def extend_instance(obj, cls):    """Apply mixins to a class instance after creation"""    base_cls = obj.__class__    base_cls_name = obj.__class__.__name__    obj.__class__ = type(base_cls_name, (base_cls, cls),{})


Although it's already answered, here is a function:

def extend(instance, new_class):    instance.__class__ = type(          '%s_extended_with_%s' % (instance.__class__.__name__, new_class.__name__),           (instance.__class__, new_class),           {},          )