SuperCiocia
SuperCiocia

Reputation: 1971

Python - why are instance methods the "default" methods in a class?

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?

Upvotes: 0

Views: 1416

Answers (1)

ShadowRanger
ShadowRanger

Reputation: 155428

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.

Upvotes: 2

Related Questions