The choice of the type of method depends on other factors.
You have two cases. The first case is when the method has to be part of the class interface - e.g. it has to be called by users, or it has to be overridable in subclasses, or it uses the information in self, or it's likely that in a future version of the software you might need any of those.
In this first case you'd often either use a normal method (this is when the method relates to the instances and not to the class) or a classmethod
(when the method relates to the class, e.g. it's an alternative constructor, a method for discovering class features, etc.). In both cases you can use a staticmethod
instead if no information from the class/instance is used by the method, but you don't gain anything from doing so. And it would also break your ability to do cls.method(instance, *args)
which is already too much for gaining nothing.
The second case is when the method isn't a part of the class in any way. Then it is generally advisable to use a function - the method is not really part of the interface, so it has no place there. Your example seems to be that case unless you want to override the tree/money calculator in subclasses, but that largely depends on what you're doing with it.
A special case is private methods - then you might want to use a method even if it's not really related to the class, private methods aren't part of the interface so it doesn't matter where you put them. Using a staticmethod
still doesn't gain you much but there isn't any reason not to use it either.
There's actually one case where staticmethod
is very helpful - when you're putting external functions (or other objects) in the class.
class Foo(object):
trees2money = staticmethod(calculators.trees2money)
foo = staticmethod(calculators.bar)
But when you have a static definition of the class, that's not really great, because you can always do the following instead.
class Foo(object):
def trees2money(self, trees):
"""Calculator for trees2money, you can override when subclassing"""
return calculators.trees2money(trees)
@property
def foo(self):
"""The foo of the object"""
return calculators.bar
Which gives you a better idea what these objects do when reading the source and even allows you to add documentation. But it might still come in handy when you're building classes dynamically, or you're adding them in a metaclass (creating a wrapper method manually isn't very convenient).
@staticmethod
because whatever you want to do via a static method should propably be done via a free function or class method. – Reinaldo