[BangPypers] Classmethod, Decorators and staticmethod

Senthil Kumaran orsenthil at gmail.com
Fri Mar 6 14:40:12 CET 2009

On Thu, Mar 5, 2009 at 6:29 PM, VIJAY KUMAR <vnbang2003 at yahoo.com> wrote:
>        Can some one please explain me with example about
>        1) classmethod
>        2) staticmethod
>        3) Decorators

Well Vijay, you have asked a sweeping question. That's why you are
finding so many unrelated responses.
Let me try to give it a dig and see if you can follow through.
Otherwise, you might have to do a lot of homework and understand it.

In Object Oriented Programming, you create a method which gets
associated either with  a class or with an instance of the class,
namely an object.  This is concept is the first thing to understand.

And most often in our regular practice, we always create methods to be
associated with an object. Those are called instance methods.

For e.g.

class Car:
	def cartype(self):
		self.model = "Audi"
mycar = Car()
print mycar.model

Here cartype() is an instance method, it associates itself with an
instance (mycar) of the class (Car) and that is defined by the first
argument ('self').

When you want a method not to be associated with an instance, you call
that as a staticmethod.

How can you do such a thing in Python?

The following would never work:

>>> class Car:
... 	def getmodel():
... 		return "Audi"
... 	def type(self):
... 		self.model = getmodel()

Because, getmodel() is defined inside the class, Python binds it to
the Class Object.
You cannot call it by the following way also, namely: Car.getmodel()
or Car().getmodel() , because in this case we are passing it through
an instance ( Class Object or a Instance Object) as one of the
argument while our definition does not take any argument.

// Are you so far so good? If not just try the above example.  Repeat
the steps (mycar= Car() ... ) I showed for the first example for this
class to understand what I mean.

As you can see, there is a conflict here and in effect the case is, It
is an "unbound local **method**" inside the class.

Now comes Staticmethod.

Now, in order to call getmodel(), you can to change it to a static method.
>>> class Car:
... 	def getmodel():
... 		return "Audi"
...     getmodel = staticmethod(getmodel)
... 	def cartype(self):
... 		self.model = Car.getmodel()
>>> mycar = Car()
>>> mycar.cartype()
>>> mycar.model

Now, I have called it as Car.getmodel() even though my definition of
getmodel did not take any argument. This is what staticmethod function
did.  getmodel() is a method which does not need an instance now, but
still you do it as Car.getmodel() because getmodel() is still bound to
the Class object.

// This is bit confusing here and details are gory. Forget it for the
time-being and if you try the code, you might get it and it requires a
bit of deeper study as well.

** Decorators **

getmodel = staticmethod(getmodel)

If you look at the previous code example, the function staticmethod
took a function as a argument and returned a function which we
assigned to a variable (named as SAME functionname) and made it a
function. Correct?

staticmethod() function thus wrapped our getmodel function with some
extra features and this wrapping is called as Decorator.

The same code can be written like this.

>>> class Car:
... 	@staticmethod
... 	def getmodel():
... 		return "Audi"
... 	def cartype(self):
... 		self.model = Car.getmodel()
>>> mycar = Car()
>>> mycar.cartype()
>>> mycar.model

For a better explaination on what is decorator, I would suggest you to
read this:


Please remember that this concept of Decorator is independent of
staticmethod and classmethod.

Now, what is a difference between staticmethod and classmethod?

In languages like Java,C++, both the terms denote the same :- methods
for which we do not require instances. But there is a difference in
Python. A class method receives the class it was called on as the
first argument. This can be useful with subclasses.

We can see the above example with the classmethod and a decorator as:
>>> class Car:
... 	@classmethod
... 	def getmodel(cls):
... 		return "Audi"
... 	def gettype(self):
... 		self.model = Car.getmodel()
>>> mycar = Car()
>>> mycar.gettype()
>>> mycar.model

Was this okay to get started with?

The following are the references in order to understand further:
1) Alex-Martelli explaining it with code:
2)  Decorators: http://personalpages.tds.net/~kent37/kk/00001.html


More information about the BangPypers mailing list