{
  "$type": "site.standard.document",
  "canonicalUrl": "https://rednafi.com/python/attribute-delegation-in-composition/",
  "description": "Implement automatic attribute delegation in Python composition using __getattr__ magic method for inheritance-like attribute access patterns.",
  "path": "/python/attribute-delegation-in-composition/",
  "publishedAt": "2021-11-28T00:00:00.000Z",
  "site": "at://did:plc:fgtm2c26vfcj74rfmeggbyqj/site.standard.publication/3mnl6f7ob462z",
  "tags": [
    "Python",
    "TIL"
  ],
  "textContent": "While trying to avoid inheritance in an API that I was working on, I came across this neat\ntrick to perform attribute delegation on composed classes. Let's say there's a class called\nEngine and you want to put an engine instance in a Car. In this case, the car has a\nclassic 'has a' (inheritance usually refers to 'is a' relationships) relationship with the\nengine. So, composition makes more sense than inheritance here. Consider this example:\n\nIdeally, you'd to use the classes as a good citizen as follows:\n\nThis will print the following:\n\nHowever, I wanted free attribute access, just like we get in inheritance. We should be able\nto do car.name, not car.engine.name, and get the name of the engine instance. With a\nlittle bit of __getattr__ magic, it's easy to do so:\n\nThis snippet is exactly the same as before and the only thing that was added here is the\n__getattr__ method in the Car class. Whenever you'll try to access an attribute or a\nmethod on an instance of the Car class, the __getattr__ will intervene. It'll first look\nfor the attribute in the instance of the Car class and if it can't find it there, then\nit'll look for the attribute in the instance of the Engine class; just like type\ninheritance. This will work in case of method access as well. So now you can use the classes\nas below:\n\nThis will print:\n\n> While this was all fun and dandy, I don't recommend putting it in any serious code as it\n> can obfuscate the program's intent and can make obvious things not-so-obvious. Also, in\n> case of attributes and methods with the same names in different classes, this can get\n> hairy. I just found this gymnastics intellectually stimulating.\n\nComplete example with tests",
  "title": "Automatic attribute delegation in Python composition"
}