At my current client, we use Python. The other day I needed to wrap a class from the requests library, specifically a response object. I wanted to add a couple of custom methods to the class and have the other methods delegate to the original object in a clean way. Here's a simplified version of what I came up with:
class JSONResponse(object): """Wraps a requests.models.Response.""" def __init__(self, response): self._response = response @property def content(self): """Assumes content is JSON and attempts to parse it. Raises an exception if it cannot be parsed. """ # ... parse JSON in self._response.content def __getattr__(self, name): """Delegate any methods not defined in JSONResponse to underlying requests.models.Response. """ return getattr(self._response, name)
The purpose of the wrapper class shown above is to cleanly handle HTTP responses that are encoded as JSON. The class defines a
content property that attempts to parse the response content. Finally, the key to the pattern is the
__getattr__ method. Whenever a
JSONResponse object is sent a message, it first checks to see if it can respond. In the case of the
content, it will respond with the result of our custom property. If we send it any other message, it will attempt to send it to the wrapped response object. If the wrapped response cannot respond to the message, then it will fail as normal.