6

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__) )
1
  • 1
    Do you want to create a new class definition, or add a parent to an existing class definition, or add a parent to an existing instance? Commented May 6, 2010 at 20:10

4 Answers 4

9

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'
Sign up to request clarification or add additional context in comments.

3 Comments

This approach didn't work for me when Foo was a child class as well. The attributes on Foo inherited from it's parents were ignored.
Check below for how I fixed this specific issue
5

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.

Comments

2

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"

Comments

1

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.