My Adventures in Coding

October 8, 2010

Python – Extending a class with a class method acting as an instance method

Filed under: Python — Brian @ 11:17 pm

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!

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: