I recently started spending a lot of time modifying
an existing Python codebase. If you are not familiar
with Python, Python is a scripting language with many
nice touches that make your life as a programmer
easier. I found one of such niceties while trying
to modify an existing Python module: the
@classmethod decorator. (If you are familiar
with Python decorators, jump here to skip
@classmethod decorator, is a builtin
that, according to the Python docs, has existed since
Python 2.2. A function decorator is basically
an expression that gets evaluated after your
function is defined. The result of that
evaluation shadows your function definition.
If you are a programmer with a Java or Scala background, like me, you may be tempted to believe that they are just like Java annotations (after all, they look the same) however do not be fooled by this similarity. Python annotations create new functions that replace the function that you just created.
So what does the
@classmethod decorator do? Let me show
you how I learned about it:
I had to modify an existing python module that looked like this:
def do_someting(): data = getdata() return something(data) def do_something_else(): data = getdata() return something_else(data) def getdata(): return read_some_source()
My goal was to have the exact same transformations
but with a new data source. That is, I wanted to
add a new
My first instinct was to try to add the
as a parameter of the other functions. This approach
turned out to be unwieldy: now I had
over the place in my code. There had to better way.
That is when I bumped into the
The @classmethod decorator
@classmethod decorator, will shadow your function
with another function that passes the
class as the first parameter to
So for example the following code:
class One(object): @classmethod def class_method(cls, x): print "My class is: %s " %(cls) One.class_method(3)
My class is: <class '__main__.One'>
This means that your method, through the
cls parameter, can
access other fields from the class you are part of.
This becomes useful when, for example, you have a bunch of related methods and you want to shadow one of them (which was my case).
You can shadow one method by doing the following:
class One(object): @classmethod def do_someting(cls): data = cls.getdata() return something(data) @classmethod def getdata(): return read_some_source() class Another(One): @classmethod def getdata(): return read_new_source()
With the help of
@classmethod if you import
One and you
do_something() you will get one data source. If you import
Another and call
do_something() you will get a new source.
@classmethod decorator happily solved my problem
without many code changes.
@classmethoddecorator allows you to have a reference to your enclosing class in your function, without the need of instantiating an object.