python class design (staticmethod vs method)

后端 未结 3 1101
轻奢々
轻奢々 2021-01-12 10:40

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. @staticmet

相关标签:
3条回答
  • 2021-01-12 11:17

    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.

    0 讨论(0)
  • 2021-01-12 11:18

    Any methods that do not use names from the object namespace should by classmethods, and those that do not use names from the class namespace either - staticmetdods, or even be put on the module level as functions.

    When the actual object method is used, the expected behavior is that some other attrubutes/methods from the same object will be accessed.

    0 讨论(0)
  • 2021-01-12 11:21

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

    0 讨论(0)
提交回复
热议问题