Recently I had a problem where I wanted to extend a class in an external library to add an additional method. I wanted to ensure that the usage of the extended version of the class would not require any code changes, just changing of an import statement. The new method we were adding to the class required that some information be retained in the object from when it was constructed. The problem was that the method in the existing library that is used to create an instance of the object is a class method (@classmethod) so it is called on the class and returns the object. Unfortunately any parameters used in that method, which included the parameter we wanted to store, could not be stored for later use in the object.
In order to make this work we would need to add an __init__ method to our new extended version of the class and use that init method rather than the existing class method to create the object. However, if we did this we would not be maintaining the existing API of the class so using our modified class would not be seamless.
It turns out there is a simple way to do this in Python (Thanks to Chris for pointing out this pattern!).
For this example let’s say we have a class called “carslib” that contains “Car” that we want to extend with a new method called “get_top_speed”:
New Wrapper Class for carslib called new_carslib
So what happens here is when the new version of carslib is used and the class method some_class_method is called it calls the __init__ method where we then store which then stores our parameter. Create the following Python file called “new_carslib.py”.
from carslib.car import Car as mycartoextend Class new_carslib(object) """"Warpper for carslib to allow for a new method to be added called get_top_speed()"""" def __init__(self): self._topspeed = topspeed self._car = mycartoextend.some_class_method(topspeed, **kw) @classmethod def some_class_method(cls, topspeed, **kw): return cls(uri, **kw) def get_top_speed(self): return self._topspeed Car = new_carslib
Usage of the old class
import carslib car = carslib.Car.some_class_method(180)
Usage of the new class
import new_carslib as carslib car = carslib.Car.some_class_method(180) results = car.get_top_speed()
Notice that the only change we make here, is updating the import statement, since we took the extra care to maintain the existing api of carslib. Now we are able to use our new method with no other code changes being required!