Could someone explain to me the meaning of @classmethod and @staticmethod in python? I need to know the difference and the meaning.

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
6  
I found this useful stackoverflow.com/questions/136097/… – Mene Aug 29 '12 at 13:42
21  
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
1  
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
4  
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
38  
this is my first day with Python - wow, I sure didn't get to decorators on my first day! – joshreesjones Jul 21 '15 at 16:29
up vote 1720 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):

    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

    # usage:
    is_date = Date.is_date_valid('11-09-2012')

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
46  
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
3  
@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
2  
@hayden, about self. instancemethod (which are not class- of static- methods) must have 1 required argument (which is substituted by instance). Though "self" is an argument name by convention, you are free to use any valid Python identifier you like (but don't recommend to do that as it can cause confusion for other developers reading your code). – Rostyslav Dzinko Aug 30 '12 at 11:07
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

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 will 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
23  
Other answers illustrate a difference between static and class methods. This answer illustrates why there is a difference. – Brian Yeh Jul 29 '14 at 17:44
    
Very nice addition. Would it be fair to say that cls is to a class (or subclass) what self is to an instance? – MikeiLL Oct 14 '14 at 17:19
1  
Thanks @Yaw, I was struggling to understand the practical difference between the two because, like you said, most examples I've seen work if you replace cls with the name of the class. It makes sense when you use it with potential subclasses in mind. – nemec Dec 13 '14 at 5:27
    
@YawBoakye What does "unlike self, the name of the variable could be anything" mean? The name self can also be anything and is also conventional. It's just the conventional name given when the supplied first argument is the instance, rather than the class! – Two-Bit Alchemist Mar 16 '15 at 21:51
    
Can't I return return Date(month, day, 2000) in a @classmethod funciton ? In that case also DateTime.millenium(10, 10) would be an instance of Date() class. What was the role of @staticmethod then ? – akki Feb 8 '16 at 21:38

@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
6  
This one helped me understand the difference between using @classmethod, @staticmethod, and not using any decorator on the method. – jjj Apr 14 '15 at 17:45
2  
Access to class attributes and class methods does not differentiate a @classmethod since you can access both class methods and class attributes from inside an instance method using the class name itself. It's more the other way around: you can't use the instance attributes or instance methods (assuming you don't pass the instance along with the class) inside of @classmethod. This is what makes the constructor examples a solid use-case, since you likely don't need access to a pre-existing instance to create a new instance. – conner.xyz Feb 8 '16 at 16:51
    
concise and to the point – Jingguo Yao Mar 16 at 17:51
    
This should be the answer. simple and clear. – Nayana Adassuriya Jun 18 at 3:37

@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

A little compilation

@staticmethod A way to write a method inside a class without reference to the object it is being called on. So no need to pass implicit argument like self or cls. It is written exactly the same how written outside the class, but it is not of no use in python because if you need to encapsulate a method inside a class since this method needs to be the part of that class @staticmethod is comes handy in that case.

@classmethod It is important when you want to write a factory method and by this custom attribute(s) can be attached in a class. This attribute(s) can be overridden in the inherited class.

A comparison between these two methods can be as below

Table

share|improve this answer

One would use @classmethod when he/she would want to change the behaviour of the method based on which subclass is calling the method. remember we have a reference to the calling class in a class method.

While using static you would want the behaviour to remain unchanged across subclasses

Example:

class Hero:

  @staticmethod
  def say_hello():
     print("Helllo...")

  @classmethod
  def say_class_hello(cls):
     if(cls.__name__=="HeroSon"):
        print("Hi Kido")
     elif(cls.__name__=="HeroDaughter"):
        print("Hi Princess")

class HeroSon(Hero):
  def say_son_hello(self):
     print("test  hello")



class HeroDaughter(Hero):
  def say_daughter_hello(self):
     print("test  hello daughter")


testson = HeroSon()

testson.say_class_hello() #Output: "Hi Kido"

testson.say_hello() #Outputs: "Helllo..."

testdaughter = HeroDaughter()

testdaughter.say_class_hello() #Outputs: "Hi Princess"

testdaughter.say_hello() #Outputs: "Helllo..."
share|improve this answer
    
Nicely succinct. The names could benefit by being more generic. – Tom Russell Mar 10 '16 at 6:37
    
What if I pass self and get class name like self.__class__.__name__ What is use of class method then ? – Kamesh Jungi Jan 31 at 12:39
    
This answer would greatly benefit from giving the output with each function call – Brian C Jun 14 at 18:19

A slightly different way to think about it that might be useful for someone... A class method is used in a superclass to define how that method should behave when it's called by different child classes. A static method is used when we want to return the same thing regardless of the child class that we are calling.

share|improve this answer

I'm a beginner on this site, I have read all above answers, and got the information what I want. However, I don't have the right to upvote. So I want to get my start on StackOverflow with the answer as I understand it.

  • @staticmethod doesn't need self or cls as the first parameter of the method
  • @staticmethod and @classmethod wrapped function could be called by instance or class variable
  • @staticmethod decorated function impact some kind 'immutable property' that subclass inheritance can't overwrite its base class function which is wrapped by a @staticmethod decorator.
  • @classmethod need cls (Class name, you could change the variable name if you want, but it's not advised) as the first parameter of function
  • @classmethod always used by subclass manner, subclass inheritance may change the effect of base class function, i.e. @classmethod wrapped base class function could be overwritten by different subclasses.
share|improve this answer
    
I'm not sure what you mean by immutable in this context? – Philip Adler Jul 23 at 11:59
    
@PhilipAdler Thank you for your helpful point, I have modified my answer. – Yi Chen Jul 23 at 23:58
    
@garfbradaz Thank you for your helpful modification, I have got so much useful Information, such as where to highlight and how to use markdown to highlight. – Yi Chen Jul 25 at 23:17

Your Answer

 
discard

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