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.
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.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:
@classmethod
@classmethod
may be compared with__init__
. You could think it is another__init__()
. It is the way python realize class constructor overloading in c++.notice they both has a reference for class as first argument in definitioin while
__init__
useself
butconstruct_from_func
usecls
conventionally.@staticmethod
@staticmethod
may be compared withobject method
self
) as the implicit first argument.cls
) as the implicit first argument.You don't need either decorator. But on the principle that you should minimize the number of arguments to functions (see Clean Coder), they are useful for doing just that.
For both instance methods and class methods, not accepting at least one argument is a TypeError, but not understanding the semantics of that argument is a user error.
(Define
some_function
's, e.g.:and this will work.)
dotted lookups on instances and classes:
A dotted lookup on an instance is performed in this order - we look for:
__dict__
Note, a dotted lookup on an instance is invoked like this:
and methods are callable attributes:
instance methods
The argument,
self
, is implicitly given via the dotted lookup.You must access instance methods from instances of the class.
class methods
The argument,
cls
, is implicitly given via dotted lookup.You can access this method via an instance or the class (or subclasses).
static methods
No arguments are implicitly given. This method works like any function defined (for example) on a modules' namespace, except it can be looked up
Each of these are progressively more restrictive in the information they pass the method versus instance methods.
Use them when you don't need the information.
This makes your functions and methods easier to reason about and to unittest.
Which is easier to reason about?
or
or
The functions with fewer arguments are easier to reason about. They are also easier to unittest.
These are akin to instance, class, and static methods. Keeping in mind that when we have an instance, we also have its class, again, ask yourself, which is easier to reason about?:
Builtin examples
Here are a couple of my favorite builtin examples:
The
str.maketrans
static method was a function in thestring
module, but it is much more convenient for it to be accessible from thestr
namespace.The
dict.fromkeys
class method returns a new dictionary instantiated from an iterable of keys:When subclassed, we see that it gets the class information as a class method, which is very useful:
My advice - Conclusion
Use static methods when you don't need the class or instance arguments, but the function is related to the use of the object, and it is convenient for the function to be in the object's namespace.
Use class methods when you don't need instance information, but need the class information perhaps for its other class or static methods, or perhaps itself as a constructor. (You wouldn't hardcode the class so that subclasses could be used here.)
Rostyslav Dzinko's answer is very appropriate. I thought I could highlight one other reason you should choose
@classmethod
over@staticmethod
when you are creating additional constructor.In the example above, Rostyslav used the
@classmethod
from_string
as a Factory to createDate
objects from otherwise unacceptable parameters. The same can be done with@staticmethod
as is shown in the code below:Thus both
new_year
andmillenium_new_year
are instances ofDate
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 theDate
class is subclassed, the subclasses will still create plainDate
object (without any property of the subclass). See that in the example below:datetime2
is not an instance ofDateTime
? 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)ensures that the
class
is not hard-coded but rather learnt.cls
can be any subclass. The resultingobject
will rightly be an instance ofcls
. Let's test that out.The reason is, as you know by now,
@classmethod
was used instead of@staticmethod
In short, @classmehtod turns a normal method to a factory method.
Let's explore it with an example:
Without a @classmethod,you should labor to creat instances one by one and they are scartted.
As for example with @classmethod
Test it:
See? Instances are successfully created inside a class definition and they are collected together.
In conclusion, @classmethod decorator convert a conventional method to a factory method,Using classmethods makes it possible to add as many alternative constructors as necessary.