Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: add a parent class to a class after initial evaluation

General Python Question

I'm importing a Python library (call it animals.py) with the following class structure:

class Animal(object): pass

class Rat(Animal): pass

class Bat(Animal): pass

class Cat(Animal): pass

...

I want to add a parent class (Pet) to each of the species classes (Rat, Bat, Cat, ...); however, I cannot change the actual source of the library I'm importing, so it has to be a run time change.

The following seems to work:

import animals

class Pet(object): pass

for klass in (animals.Rat, animals.Bat, animals.Cat, ...): 
    klass.__bases__ = (Pet,) + klass.__bases__

Is this the best way to inject a parent class into an inheritance tree in Python without making modification to the source definition of the class to be modified?

Motivating Circumstances

I'm trying to graft persistence onto the a large library that controls lab equipment. Messing with it is out of the question. I want to give ZODB's Persistent a try. I don't want to write the mixin/facade wrapper library because I'm dealing with 100+ classes and lots of imports in my application code that would need to be updated. I'm testing options by hacking on my entry point only: setting up the DB, patching as shown above (but pulling the species classes w/ introspection on the animals module instead of explicit listing) then closing out the DB as I exit.

Mea Culpa / Request

This is an intentionally general question. I'm interested in different approaches to injecting a parent and comments on the pros and cons of those approaches. I agree that this sort of runtime chicanery would make for really confusing code. If I settle on ZODB I'll do something explicit. For now, as a regular user of python, I'm curious about the general case.

like image 669
Finn Avatar asked Sep 13 '11 20:09

Finn


1 Answers

Your method is pretty much how to do it dynamically. The real question is: What does this new parent class add? If you are trying to insert your own methods in a method chain that exists in the classes already there, and they were not written properly, you won't be able to; if you are adding original methods (e.g. an interface layer), then you could possibly just use functions instead.

I am one who embraces Python's dynamic nature, and would have no problem using the code you have presented. Make sure you have good unit tests in place (dynamic or not ;), and that modifying the inheritance tree actually lets you do what you need, and enjoy Python!

like image 177
Ethan Furman Avatar answered Oct 21 '22 20:10

Ethan Furman