Search code examples
pythonstatic-methods

What is "static method" in python


I'm quite new to python, and could not understand what is static method in python(for example __new__()) and what does it do. Can anyone possibly explain it? Thanks a million


Solution

  • Have you already read this?

    https://en.wikipedia.org/wiki/Method_(computer_programming)

    Especially this?

    https://en.wikipedia.org/wiki/Method_(computer_programming)#Static_methods

    Explanation

    In OOP you define classes that you later on instantiate. A class is nothing more than a blueprint: Once you instantiate objects from a class your object will follow exactly the blueprint of your class. That means: If you define a field named "abc" in your class you will later on have a field "abc" in your object. If you define a method "foo()" in your class, you will later on have a method "foo()" to be invoked on your object.

    Please note that this "on your object" is essential: You always instantiate a class and then you can invoke the method. This is the "normal" way.

    A static method is different. While a normal method always requires to have an instance (where you then can invoke this method at) a static method does not. A static method exists independently from your instances (that's why it is named "static"). So a static method is associated with your class definition itself and therefore is always there and therefore can be invoked only at your class itself. It is completely independent from all instances.

    That's a static method.

    Python's implementation is a bit ... well ... simple. In details there are deviations from this description above. But that does not make any difference: To be in line with OOP concepts you always should use methods exactly as described above.

    Example

    Let's give you an example:

    class FooBar:
    
      def someMethod(self):
        print("abc")
    

    This is a regular (instance) method. You use it like this:

    myObj = FooBar()
    myObj.someMethod()
    

    If you have ...

    myObjB = FooBar()
    myObjB.someMethod()
    

    ... you have an additional instance and therefore invoking someMethod() on this second instance will be the invocation of a second someMethod() method - defined at the second object. This is because you instantiate objects before use so all instances follow the blueprint FooBar defined. All instances therefore receive some kind of copy of someMethod().

    (In practice Python will use optimizations internally, so there actually is only one piece of code that implements your someMethod() in memory, but forget about this for now. To a programmer it appears as that every instance of a class will have a copy of the method someMethod(). And that's the level of abstraction that is relevant to us as this is the "surface" we work on. Deep within the implementation of a programming or script language things might be a bit different but this is not very relevant.)

    Let's have a look at a static method:

    class FooBar:
    
      @staticmethod
      def someStaticMethod():
        print("abc")
    

    Such static methods can be invoked like this:

    FooBar.someStaticMethod()
    

    As you can see: No instance. You directly invoke this method in the context of the class itself. While regular methods work on the particular instance itself - they typically modify data within this instance itself - a class method does not. It could modify static (!) data, but typically it does not anyway.

    Consider a static method a special case. It is rarely needed. What you typically want if you write code is not to implement a static method. Only in very specific situations it makes sense to implement a static method.

    The self parameter

    Please note that a standard "instance" method always must have self as a first argument. This is a python specific. In the real world Python will (of course!) store your method only once in memory, even if you instantiate thousands of objects of your class. Consider this an optimization. If you then invoke your method on one of your thousands of instances, always the same single piece of code is called. But for it to distinguish on which particular object the code of the method should work on your instance is passed to this internally stored piece of code as the very first argument. This is the self argument. It is some kind of implicit argument and always needed for regular (instance) methods. (Not: static methods - there you don't need an instance to invoke them).

    As this argument is implicit and always needed most programming languages hide it to the programmer (and handle this internally - under the hood - in the correct way). It does not really make much sense to expose this special argument anyway.

    Unfortunately Python does not follow this principle. Python does not hide this argument which is implicitly required. (Python's incorporation of OOP concepts is a bit ... simple.) Therefore you see self almost everywhere in methods. In your mind you can ignore it, but you need to write it explicitly if you define your own classes. (Which is something you should do in order to structure your programs in a good way.)

    The static method __new__()

    Python is quite special. While regular programming languages follow a strict and immutable concept of how to create instances of particular classes, Python is a bit different here. This behavior can be changed. This behavior is implemented in __new__(). So if you do this ...

    myObj = FooBar()
    

    ... Python implicitly invokes FooBar.__new__() which in turn invokes a constructor-like (instance) method named __init__() that you could (!) define in your class (as an instance method) and then returns the fully initialized instance. This instance is then what is stored in myObj in this example her.

    You could modify this behavior if you want. But this would requires a very very very particularly unusual use case. You will likely never have anything to do with __new__() itself in your entire work with Python. My advice: If you're somehow new to Python just ignore it.