classmethod
and staticmethod
return descriptor objects, not functions. Most decorators are not designed to accept descriptors.
Normally, then, you must apply classmethod
and staticmethod
last when using multiple decorators. And since decorators are applied in "bottom up" order, classmethod
and staticmethod
normally should be top-most in your source.
Like this:
class My_class(object):
@classmethod
@print_function_name
def get_dir(cls):
return dir(cls)
@staticmethod
@print_function_name
def get_a():
return 'a'
The most straightforward way to think about it is to think in terms of what type of object the method needs in order to do its work. If your method needs access to an instance, make it a regular method. If it needs access to the class, make it a classmethod. If it doesn't need access to the class or the instance, make it a function. There is rarely a need to make something a staticmethod, but if you find you want a function to be "grouped" with a class (e.g., so it can be overridden) even though it doesn't need access to the class, I guess you could make it a staticmethod.
I would add that putting functions at the module level doesn't "pollute" the namespace. If the functions are meant to be used, they're not polluting the namespace, they're using it just as it should be used. Functions are legitimate objects in a module, just like classes or anything else. There's no reason to hide a function in a class if it doesn't have any reason to be there.
Best Answer
Maybe a bit of example code will help: Notice the difference in the call signatures of
foo
,class_foo
andstatic_foo
:Below is the usual way an object instance calls a method. The object instance,
a
, is implicitly passed as the first argument.With classmethods, the class of the object instance is implicitly passed as the first argument instead of
self
.You can also call
class_foo
using the class. In fact, if you define something to be a classmethod, it is probably because you intend to call it from the class rather than from a class instance.A.foo(1)
would have raised a TypeError, butA.class_foo(1)
works just fine:One use people have found for class methods is to create inheritable alternative constructors.
With staticmethods, neither
self
(the object instance) norcls
(the class) is implicitly passed as the first argument. They behave like plain functions except that you can call them from an instance or the class:Staticmethods are used to group functions which have some logical connection with a class to the class.
foo
is just a function, but when you calla.foo
you don't just get the function, you get a "partially applied" version of the function with the object instancea
bound as the first argument to the function.foo
expects 2 arguments, whilea.foo
only expects 1 argument.a
is bound tofoo
. That is what is meant by the term "bound" below:With
a.class_foo
,a
is not bound toclass_foo
, rather the classA
is bound toclass_foo
.Here, with a staticmethod, even though it is a method,
a.static_foo
just returns a good 'ole function with no arguments bound.static_foo
expects 1 argument, anda.static_foo
expects 1 argument too.And of course the same thing happens when you call
static_foo
with the classA
instead.