0

Functions in a python class can be either instance methods, class methods or static methods.

The former is characterised by the self as its first (implicit) argument, acts directly on the instance of the class, and does not require any decorators to be treated as such.

The other two, however, need decorators @classmethod and @staticmethod before the name of the method - this is why I refer to the instance method as the "default" one, i.e. the one for which a wrapper is not needed.


My question is:
suppose I am in a class, and I am breaking up my calculation into several functions for readibility. Only one of these methods will need access to the self.something variables that I share instance-wise, but most of the others do not need to know about the class they belong to - they are just there for "housekeeping".

Should make these functions (the ones that do not need any self.something knowledge) all @staticmethod?
Doing so would require a decorator and hence an extra step.
It would be easier (not requiring the extra step of using a decotrator) for every method to just be an instance method, thus inheritig a lot of potential but also waisting it since it is not needed for the scope of the functions in question.

Why is the instance method the "default"?
Why not have every method a static method by default, and give it the extra functionality associated with being a instance method with a wrapper?

7
  • 3
    If it doesn't need the instance, why is it part of the class? And why do you have so many helpers that don't need the instance? Commented Oct 11, 2018 at 23:01
  • Because I am using the class just to bunch functions together, that perform calculations towards the same goal. Commented Oct 11, 2018 at 23:04
  • 3
    "Because I am using the class just to bunch functions together" - well that explains why you're so confused. That's not what classes are for. Commented Oct 11, 2018 at 23:05
  • 2
    @user2357112: Although admittedly, that's basically what @staticmethod is for: "I have helper functions that aid with class functionality, but aren't very useful outside the class, and have no direct reliance on the class or its instances, so we'll namespace them inside the class to make it clear they're class helpers." It's just that that's the unusual case, so there is no reason to make it the default behavior. Commented Oct 11, 2018 at 23:20
  • 3
    @SeanPianka: That said, if the class doesn't have any instance attributes or methods, you could just skip the class-as-namespace and make all the functions top-level functions of a module. If the static methods aren't helping the class instances in some way, they don't need to be on a class at all. Commented Oct 11, 2018 at 23:35

1 Answer 1

2

The reason to default to instance methods is because that's usually what you want when you're doing object oriented programming. I can't think of a single language that claims to support OOP and has methods default to anything but instance methods. Classes are templates for "data with behaviors", so the default is to make methods that provide behaviors to each instantiation of the class. If you just want a collection of functions, you can just define them at the top level of a module and save the unnecessary class after all.

In general, @staticmethod is used to mean "I know this isn't a behavior of the class or its instances, but it helps implement the real behaviors and isn't very useful outside the class, so I'll namespace it inside it." If the features are useful outside the class, you'd just make it a plain top-level function rather putting it inside the class at all. It is advantageous to use @staticmethod where appropriate; it's a little faster to call than an instance method, so if you don't need the instance, @staticmethod will speed up your code a bit (note: This may not be true in 3.7+, where they added an optimization to avoid the creation of bound methods, which may speed up instance/class methods).

@classmethod basically has two use cases:

  1. (Primary) Defining alternate constructors in a subclass friendly way (the cls it receives is the actual subclass, if applicable, not just the class it was defined in)
  2. (Mostly unnecessary) As an alternative to @staticmethod when the method needs to call other static methods and you'd rather not have to refer to the class by name over and over

Point is, @staticmethod is mostly for when you're opting out of OOP, and @classmethods are for niche use cases; instance methods are just more useful, so they're the default. Beyond that, as a historical note, static and class methods were introduced later, so making them the default would have broken all existing Python code, for no real benefit.

The main reason to use @staticmethod over instance methods with an ignored self (when self isn't needed) is that it will continue to work when called on the class itself, not just on instances of the class; if you tried to call MyClass.notreallystatic(), it would die for lack of a self, while MyClass.actuallystatic() would work.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.