Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python class design (staticmethod vs method)

What's the nicer way for methods that don't need any passed information (object instance or class) because for example they just do a simple conversion. @staticmethod or method ?

class Foo(object):
    def __init__(self, trees):
        self.money = Foo.trees2money(trees)

    @staticmethod
    def trees2money(trees):
        return trees * 1.337

class Quu(object):
    def __init__(self, trees):
        self.money = self.trees2money(trees)

    def trees2money(self, trees):
        return trees * 1.337
like image 213
Tammo B. Avatar asked Mar 06 '11 17:03

Tammo B.


People also ask

Should I use Staticmethod Python?

staticmethods can be used when the code that belongs to a class doesn't use the object itself at all. Python doesn't have to instantiate a bound method for each object we instantiate. Bound methods are objects too, and creating them has a cost. Having a static method avoids that.

What is the point of @staticmethod?

The @staticmethod is a built-in decorator that defines a static method in the class in Python. A static method doesn't receive any reference argument whether it is called by an instance of a class or by the class itself.

What is the difference between Staticmethod and Classmethod in Python?

The static method does not take any specific parameter. Class method can access and modify the class state. Static Method cannot access or modify the class state. The class method takes the class as parameter to know about the state of that class.

Is static method faster than instance method?

They are faster — Static methods are slightly faster than instance methods because in instance methods, you are also working with an implicit this parameter. Eliminating that parameter gives a slight performance boost in most programming languages.


2 Answers

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).

like image 78
Rosh Oxymoron Avatar answered Sep 28 '22 18:09

Rosh Oxymoron


My general rule, for all Object Oriented design, is that if a class has no state, consider using static methods. If the class has state, use instance methods - hands down.

Furthermore, if the class indeed has no state, reflect for a few minutes and see if you cannot move the static behavior closer to the data and thereby eliminate those static methods with an Extract Method refactoring.

like image 45
Mike Avatar answered Sep 28 '22 19:09

Mike