Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@staticmethod or function outside class?

Assuming I have a class which requires a function (or should I say method) which is:

  • independent from my class instance - doesn't need self argument;
  • is called only inside my class object
  • I won't need access to it at any point (to override it for example);

should I (A) place it inside the class and mark it as a @staticmethod or should I (B) define it outside my class object (but in the same namespace)? Why?

Example:

class A:
    def __init__(self, my_int):
        self.my_int = my_int
    def my_int_and_4(self):
        print(self.adder(self.my_int,4))
    @staticmethod
    def adder(a,b):
        return a+b

or

def adder(a,b):
    return a+b
class B:
    def __init__(self, my_int):
        self.my_int = my_int
    def my_int_and_4(self):
        print(adder(self.my_int,4))

EDIT: maybe the example is a bit oversimplified. I should have added that my version of "adder" is specificly used with my class and in no other case.

like image 220
Siemkowski Avatar asked Nov 19 '17 20:11

Siemkowski


People also ask

Can you call a function outside the class?

Whenever the definition of a class member appears outside of the class declaration, the member name must be qualified by the class name using the :: (scope resolution) operator. The following example defines a member function outside of its class declaration.

Can we write functions outside a class in Python?

Yes you can definitely have functions outside of a class.

Can we call static method outside the class?

Yes. You can use the static method if it is declared as public : public static void f() { // ... } or if it is package-private (no modifier):

Can a static method be called from outside the class Python?

You'll be free to change it in the future, or even delete it, without breaking anything outside that class. And yeah, make it static, because you can. In Python, there is no way to make a method truly private, but by convention, prefixing the method name by a _ means it should be treated as private.

How to define a class method and a static method?

We generally use static methods to create utility functions. How to define a class method and a static method? To define a class method in python, we use @classmethod decorator, and to define a static method we use @staticmethod decorator. Let us look at an example to understand the difference between both of them.

What is @staticmethod function in Java?

Hereis a short article on this question @staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.

Should I put methods outside of a class as functions?

Putting such methods outside of a class, as functions, allows for reusing them by unrelated code. Depending on your current context and predictable future of the project - either can be better solution. Show activity on this post.

What is the difference between @classmethoddecorator and @staticmethod?

@classmethoddecorator can be called with with an instance of a class or directly by the class itself as its first argument. @staticmethodis a way of putting a function into a class (because it logically belongs there), while indicating that it does not require access to the class.


3 Answers

This is a textbook use case for a private static method.

They key point here is that you should make it a private method of that class. That way you're certain nothing else will use it and depend on its implementation. You'll be free to change it in the future, or even delete it, without breaking anything outside that class.

And yeah, make it static, because you can.

In Python, there is no way to make a method truly private, but by convention, prefixing the method name by a _ means it should be treated as private.

    @staticmethod
    def _adder(a,b):  ## <-- note the _
        return a+b

If at some point you suddenly need to use it outside the class, then exposing it will be no trouble at all, e.g. using a public wrapper method.

The reverse, however, isn't true; once exposed, it's difficult to retract that exposure.

like image 116
Jean-François Corbett Avatar answered Oct 19 '22 17:10

Jean-François Corbett


I would definitely use a private static method in this case, for the reasons described by Jean-Francois Corbett. There are two types of methods in Python that belong to the class itself, rather than an instance: class methods and static methods.

The first parameter of a class method (created with @classmethod) references the class in exactly the same manner that the first parameter of an instance method (self) references an instance. It is the equivalent of static methods in most other languages. If your method requires access to other class members, use a class method.

A static method (created with @staticmethod) does not contain a reference to the class, and therefore cannot reference other class members. It's generally used for private helper methods and the like.

For your adder method, I would definitely use a static method. However, in this modified (and rather useless) version, a class method is necessary:

class A:
    x = 1
    def __init__(self, my_int):
        self.my_int = my_int
    def my_int_and_4(self):
        print(self._adder(self.my_int,4))
    @staticmethod
    def _adder(a,b):
        return a+b
    @classmethod
    def _increment(cls, n):
        return n + cls.x
like image 20
Isaac Saffold Avatar answered Oct 19 '22 18:10

Isaac Saffold


Both approaches will work, so it's the matter of readability and following conventions.

  • Does the method need to look at the instance's private attributes? If yes, it's a good reason to keep it in the class.
  • Is the method only used as a helper for one of different methods? If yes, it's a good reason to put it right after the calling method so that the code can be read top-down.
  • Does the method seem to make sense outside of the context of your class? If yes, it's a good reason to make it a free function or even move it to a different file, like utils.
like image 38
Kos Avatar answered Oct 19 '22 17:10

Kos