Automatic attribute delegation in Python composition
While trying to avoid inheritance in an API that I was working on, I came across this neat trick to perform attribute delegation on composed classes. Let's say there's a class called Engine and you want to put an engine instance in a Car. In this case, the car has a classic 'has a' (inheritance usually refers to 'is a' relationships) relationship with the engine. So, composition makes more sense than inheritance here. Consider this example:
Ideally, you'd to use the classes as a good citizen as follows:
This will print the following:
However, I wanted free attribute access, just like we get in inheritance. We should be able to do car.name, not car.engine.name, and get the name of the engine instance. With a little bit of getattr magic, it's easy to do so:
This snippet is exactly the same as before and the only thing that was added here is the getattr method in the Car class. Whenever you'll try to access an attribute or a method on an instance of the Car class, the getattr will intervene. It'll first look for the attribute in the instance of the Car class and if it can't find it there, then it'll look for the attribute in the instance of the Engine class; just like type inheritance. This will work in case of method access as well. So now you can use the classes as below:
This will print:
While this was all fun and dandy, I don't recommend putting it in any serious code as it can obfuscate the program's intent and can make obvious things not-so-obvious. Also, in case of attributes and methods with the same names in different classes, this can get hairy. I just found this gymnastics intellectually stimulating.
Complete example with tests
Discussion in the ATmosphere