Overriding a static method in python

Question:

Referring to the first answer about python’s bound and unbound methods here, I have a question:

class Test:
    def method_one(self):
        print "Called method_one"
    @staticmethod
    def method_two():
        print "Called method_two"
    @staticmethod
    def method_three():
        Test.method_two()
class T2(Test):
    @staticmethod
    def method_two():
        print "T2"
a_test = Test()
a_test.method_one()
a_test.method_two()
a_test.method_three()
b_test = T2()
b_test.method_three()

produces output:

Called method_one
Called method_two
Called method_two
Called method_two

Is there a way to override a static method in python?

I expected b_test.method_three() to print “T2”, but it doesn’t (prints “Called method_two” instead).

Asked By: Emma

||

Answers:

In the form that you are using there, you are explicitly specifying what class’s static method_two to call. If method_three was a classmethod, and you called cls.method_two, you would get the results that you wanted:

class Test:
    def method_one(self):
        print "Called method_one"
    @staticmethod
    def method_two():
        print "Called method_two"
    @classmethod
    def method_three(cls):
        cls.method_two()

class T2(Test):
    @staticmethod
    def method_two():
        print "T2"

a_test = Test()
a_test.method_one()  # -> Called method_one
a_test.method_two()  # -> Called method_two
a_test.method_three()  # -> Called method_two

b_test = T2()
b_test.method_three()  # -> T2
Test.method_two()  # -> Called method_two
T2.method_three()  # -> T2
Answered By: lostlogic

The behavior you see is the expected behavior. Static methods are… static. When you call method_three() defined in Test it will certainly call method_two() defined by Test.

As for how to “get around” this proper behavior…

The very best way is to make methods virtual when you want virtual behavior. If you’re stuck with some library code with a static method that you wish were virtual then you might look deeper to see if there’s a reason or if it’s just an oversight.

Otherwise, you can define a new method_three() in T2 that calls T2.method_two().

Answered By: dwc

Additionally, if you want to call the “virtual static” function without an instance, you could proceed like so:

  1. Declare the function in the base class non-static like so:

    class Base:
        def my_fun(self):
            print('my_fun base')
    
    class Derived(Base):
        def my_fun(self):
            print('my_fun derived')
    
  2. Call it by passing the class type, which is not an instance, like so:

    Derived.my_fun(Derived)
    

Note, this is useful if you have a variable “class_type”, which is only known during run time.

Answered By: Ytsen de Boer
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.