Reputation: 12848
Can I make a class inherit a class "in-program" in Python?
heres what i have so far:
base = list(cls.__bases__)
base.insert(0, ClassToAdd )
base = tuple( base )
cls = type( cls.__name__, base, dict(cls.__dict__) )
Upvotes: 6
Views: 3554
Reputation: 880657
Here is an example, using Greg Hewgill's suggestion:
class Foo(object):
def beep(self):
print('Hi')
class Bar(object):
x = 1
bar = Bar()
bar.beep()
# AttributeError: 'Bar' object has no attribute 'beep'
Bar = type('Bar', (Foo,object), Bar.__dict__.copy())
bar.__class__ = Bar
bar.beep()
# 'Hi'
Upvotes: 9
Reputation: 1100
Here's my solution that does take into account base classes of both the parent and the child classes.
import inspect
def inherit_from(Child, Parent):
# Prepare bases
child_bases = inspect.getmro(Child)
parent_bases = inspect.getmro(Parent)
bases = tuple([item for item in parent_bases if item not in child_bases]) + child_bases
# Construct the new return type
Child = type(Child.__name__, bases, Child.__dict__.copy())
return Child
Upvotes: 1
Reputation: 5527
Another option is not to change the class hierarchy dynamically but to decorate instances of objects with the new functionality. This is generally cleaner and easier to debug, because you only change objects that your code is in controls without having to make a cross cutting change to the whole class hierarchy.
def extend_object(obj):
class ExtensionClass(obj.__class__):
def new_functionality(self):
print "here"
obj.__class__ = ExtensionClass
b = Foo()
extend_object(b)
b.new_functionality()
#prints "here"
Upvotes: 2
Reputation: 994371
Yes, the type()
built-in function has a three argument form that can do this:
type(name, bases, dict)
Return a new type object. This is essentially a dynamic form of the
class
statement. The name string is the class name and becomes the__name__
attribute; the bases tuple itemizes the base classes and becomes the__bases__
attribute; and the dict dictionary is the namespace containing definitions for class body and becomes the__dict__
attribute.
Upvotes: 5