74

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).

2
  • 2
    It would work if you put self.method_two() instead of Test.method_two(). And this should be the correct answer of the question. Commented Aug 9, 2019 at 12:31
  • 4
    @seahawk self is not defined inside a static or class method. Commented Mar 5, 2020 at 15:52

3 Answers 3

99

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
Sign up to request clarification or add additional context in comments.

1 Comment

Really useful. In my case, I needed to access an instance's class. I did it like this: instance.__class__.my_method()
3

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().

Comments

0

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.

1 Comment

At that point, why not just make it a class method? Then it can be overridden and still called statically (no need to pass the class parameter).

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.