Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I know there are many resources on this topic, but since English is not my native language and this is my first day with Python, I need some help: could someone explain to me the meaning of @classmethod and @staticmethod? I need to know not only the difference but also the meaning. I've read through some documentation, but I literally could not understand it. If someone could give me a clear definition and an example, that would be great - I learn best from example.

As far as I understand, @classmethod tells a class that it's a method which should be inherited into subclasses, or... something. However, what's the point of that? Why not just define the class method without adding @classmethod or @staticmethod or any @ definitions?

tl;dr: when should I use them, why should I use them, and how should I use them?

I'm pretty advanced with C++, so using more advanced programming concepts shouldn't be a problem. Feel free giving me a corresponding C++ example if possible.

share|improve this question
3  
I found this useful stackoverflow.com/questions/136097/… –  Mene Aug 29 '12 at 13:42
3  
And for you as C++ developer: @classmethod is similar to a static method in C++ and a @staticmethod is similar to a function (like you'd declare it outside the class) –  Mene Aug 29 '12 at 13:45
    
thanks, I think you should write those in an answer, would've accepted it, but got it :) Not sure how come I didn't find that topic by search, it's first in the results now O.o –  user1632861 Aug 29 '12 at 13:52
2  
Here is a post the best clearly explanation I have been read. rapd.wordpress.com/2008/07/02/… –  firo Dec 30 '12 at 7:45

4 Answers 4

up vote 652 down vote accepted

Though classmethod and staticmethod are quite similar, there's a slight difference in usage for both entities: classmethod must have a reference to a class object as the first parameter, whereas staticmethod can have no parameters at all.

Let's look at all that was said in real examples.

Boilerplate

Let's assume an example of a class, dealing with date information (this is what will be our boilerplate to cook on):

class Date(object):

    day = 0
    month = 0
    year = 0

    def __init__(self, day=0, month=0, year=0):
        self.day = day
        self.month = month
        self.year = year

This class obviously could be used to store information about certain dates (without timezone information; let's assume all dates are presented in UTC).

Here we have __init__, a typical initializer of Python class instances, which receives arguments as a typical instancemethod, having the first non-optional argument (self) that holds reference to a newly created instance.

Class Method

We have some tasks that can be nicely done using classmethods.

Let's assume that we want to create a lot of Date class instances having date information coming from outer source encoded as a string of next format ('dd-mm-yyyy'). We have to do that in different places of our source code in project.

So what we must do here is:

  1. Parse a string to receive day, month and year as three integer variables or a 3-item tuple consisting of that variable.
  2. Instantiate Date by passing those values to initialization call.

This will look like:

day, month, year = map(int, string_date.split('-'))
date1 = Date(day, month, year)

For this purpose, C++ has such feature as overloading, but Python lacks that feature- so here's when classmethod applies. Lets create another "constructor".

    @classmethod
    def from_string(cls, date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        date1 = cls(day, month, year)
        return date1

date2 = Date.from_string('11-09-2012')

Let's look more carefully at the above implementation, and review what advantages we have here:

  1. We've implemented date string parsing in one place and it's reusable now.
  2. Encapsulation works fine here (if you think that you could implement string parsing as a single function elsewhere, this solution fits OOP paradigm far better).
  3. cls is an object that holds class itself, not an instance of the class. It's pretty cool because if we inherit our Date class, all children will have from_string defined also.

Static method

What about staticmethod? It's pretty similar to classmethod but doesn't take any obligatory parameters (like a class method or instance method does).

Let's look at the next use case.

We have a date string that we want to validate somehow. This task is also logically bound to Date class we've used so far, but still doesn't require instantiation of it.

Here is where staticmethod can be useful. Let's look at the next piece of code:

    @staticmethod
    def is_date_valid(date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        return day <= 31 and month <= 12 and year <= 3999

So, as we can see from usage of staticmethod, we don't have any access to what the class is- it's basically just a function, called syntactically like a method, but without access to the object and it's internals (fields and another methods), while classmethod does.

share|improve this answer
8  
Wow you really spent some time on this, would be a shame not to accept... Thanks alot man, I understood most of it already from comments and earlier answers, but this one nailed it. Just one question, the Classmethod example was good, but I kinda missed the whole point of "from_string", since it's not returning anything? shouldn't it just be return cls(day, month, year) (you really don't even need the day, month and year vars either) instead of date1 = cls(day, month, year) ? Or am I still not getting it :D Edit: Nvm, you noticed it already, thanks for your answer :) –  user1632861 Aug 29 '12 at 14:08
2  
This is a great answer. I have one question: is a non-staticmethod, non-classmethod, function within a class required to have self as the first argument? (Aside: why do you use a try/except with asserts, rather than just returning 0<=day<=31 and 0<=month<=12 and 0<=year<=3999?) –  Andy Hayden Aug 30 '12 at 10:59
2  
@hayden, I'll agree with you that using logical expression is more beautiful, but that's not the point of the question, so I didn't focused much on the implementation quality, but tried to make code as much obvious as it could be for a C++ developer, that OP is. –  Rostyslav Dzinko Aug 30 '12 at 11:03
4  
Ah ha, that was the bit I was missing! (I can't write a non-static method without referring to "self".) –  Andy Hayden Aug 30 '12 at 11:27
2  
date_as_string == string_date, my bad, will fix that :) ...and thanks for careful reading. –  Rostyslav Dzinko Mar 5 '13 at 12:41

Rostyslav Dzinko's answer is very appropriate. I thought I could highlight one other reason you should choose @classmethod over @staticmethod.

In the example above, Rostyslav used the @classmethod from_string as a Factory to create Date objects from otherwise unacceptable parameters. The same can be done with @staticmethod as is shown in the code below:

class Date:
  def __init__(self, month, day, year):
    self.month = month
    self.day   = day
    self.year  = year


  def display(self):
    return "{0}-{1}-{2}".format(self.month, self.day, self.year)


  @staticmethod
  def millenium(month, day):
    return Date(month, day, 2000)

new_year = Date(1, 1, 2013)               # Creates a new Date object
millenium_new_year = Date.millenium(1, 1) # also creates a Date object. 

# Proof:
new_year.display()           # "1-1-2013"
millenium_new_year.display() # "1-1-2000"

isinstance(new_year, Date) # True
isinstance(millenium_new_year, Date) # True

Thus both new_year and millenium_new_year are instances of Date class.

But if you observe closely, the Factory process is hard-coded to create Date objects no matter what. What this means is that even if the Date class is subclassed, the subclasses will still create plain Date object (without any property of the subclass). See that in the example below:

class DateTime(Date):
  def display(self):
      return "{0}-{1}-{2} - 00:00:00PM".format(self.month, self.day, self.year)


datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)

isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # False

datetime1.display() # returns "10-10-1990 - 00:00:00PM"
datetime2.display() # returns "10-10-2000" because it's not a DateTime object but a Date object. Check the implementation of the millenium method on the Date class

datetime2 is not an instance of DateTime? WTF? Well that's because of the @staticmethod decorator used.

In most cases, this is undesired. If what you want is a Factory method that is aware of the class that called it, then @classmethod is what you need.

Rewriting the Date.millenium as (that's the only part of the above code that changes)

@classmethod
def millenium(cls, month, day):
    return cls(month, day, 2000)

ensures that the class is not hard-coded but rather learnt. cls can be any subclass. The resulting object would rightly be an instance of cls. Let's test that out.

datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)

isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # True


datetime1.display() # "10-10-1990 - 00:00:00PM"
datetime2.display() # "10-10-2000 - 00:00:00PM"

The reason is, as you know by now, @classmethod was used instead of @staticmethod

share|improve this answer
10  
Way better example than the accepted answers'. –  Droogans May 21 '13 at 17:47
1  
thanks for the awesome example! –  Zhe Jun 11 '13 at 15:04
    
@Yaw - good point! –  Clara Dec 2 '13 at 10:48
2  
Combined with the accepted answer this answer becomes the best resource to understand the concept. –  vivi Aug 28 '14 at 9:16
1  
Sure. But unlike self, the name of the variable could be anything. cls is the convention btw. @MikeiLL –  Yaw Boakye Oct 17 '14 at 16:44

@classmethod means: when this method is called, we pass the class as the first argument instead of the instance of that class (as we normally do with methods). This means you can use the class and its properties inside that method rather than a particular instance.

@staticmethod means: when this method is called, we don't pass an instance of the class to it (as we normally do with methods). This means you can put a function inside a class but you can't access the instance of that class (this is useful when your method does not use the instance).

share|improve this answer

@staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.

  • Python does not have to instantiate a bound-method for object.
  • It eases the readability of the code: seeing @staticmethod, we know that the method does not depend on the state of object itself;

@classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance, can be overridden by subclass. That’s because the first argument for @classmethod function must always be cls (class).

  • Factory methods, that are used to create an instance for a class using for example some sort of pre-processing.
  • Static methods calling static methods: if you split a static methods in several static methods, you shouldn't hard-code the class name but use class methods

here is good link to this topic.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.