Is it possible to add a base class to an object instance (not a class!) at runtime? Something along the lines of how Object#extend
works in Ruby:
class Gentleman(object): def introduce_self(self): return "Hello, my name is %s" % self.name class Person(object): def __init__(self, name): self.name = name p = Person("John") # how to implement this method? extend(p, Gentleman) p.introduce_self() # => "Hello, my name is John"
What is a mixin in Python. A mixin is a class that provides method implementations for reuse by multiple related child classes. However, the inheritance is not implying an is-a relationship. A mixin doesn't define a new type. Therefore, it is not intended for direction instantiation.
Python Code can be dynamically imported and classes can be dynamically created at run-time. Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object. Syntax: type(object) The above syntax returns the type of object.
Mixins are sometimes described as being "included" rather than "inherited". In short, the key difference from an inheritance is that mix-ins does NOT need to have a "is-a" relationship like in inheritance. From the implementation point of view, you can think it as an interface with implementations.
Mixins are an alternative class design pattern that avoids both single-inheritance class fragmentation and multiple-inheritance diamond dependencies. A mixin is a class that defines and implements a single, well-defined feature. Subclasses that inherit from the mixin inherit this feature—and nothing else.
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.name class Person(object): def __init__(self, name): self.name = name p = 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.name class Base(object):pass class Person(Base): def __init__(self, name): self.name = name p = 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),{})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With