Переопределение статического метода в Python - PullRequest
44 голосов
/ 21 мая 2009

Обращаясь к первому ответу о связанных и несвязанных методах Python здесь, у меня есть вопрос:

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

производит вывод:

Called method_one
Called method_two
Called method_two
Called method_two

Есть ли способ переопределить статический метод в python?

Я ожидал, что b_test.method_three() напечатает «T2», но это не так (вместо этого выводится «Called method_two»).

Ответы [ 3 ]

60 голосов
/ 21 мая 2009

В используемой вами форме вы явно указываете, какой класс должен вызывать method_two. Если method_three был метод класса, и вы позвонили cls.method_two, вы получите желаемый результат:

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
3 голосов
/ 21 мая 2009

Поведение, которое вы видите - это ожидаемое поведение. Статические методы ... статические. Когда вы вызываете method_three(), определенный в Test, он обязательно вызовет method_two(), определенный как Test.

Что касается того, как "обойти" это правильное поведение ...

Самый лучший способ - сделать методы виртуальными, когда вам нужно виртуальное поведение. Если вы застряли в каком-то библиотечном коде со статическим методом, который, как вам хотелось бы, был виртуальным, вы могли бы заглянуть глубже, чтобы увидеть, есть ли причина или это просто упущение.

В противном случае вы можете определить новый method_three() в T2, который вызывает T2.method_two().

0 голосов
/ 30 июня 2016

Кроме того, если вы хотите вызвать «виртуальную статическую» функцию без экземпляра, вы можете выполнить следующее:

  1. Объявите функцию в базовом классе нестатической, например:

    class Base:
        def my_fun(self):
            print('my_fun base')
    
    class Derived(Base):
        def my_fun(self):
            print('my_fun derived')
    
  2. Вызовите его, передав тип класса, который не является экземпляром, например:

    Derived.my_fun(Derived)
    

Обратите внимание, это полезно, если у вас есть переменная "class_type", которая известна только во время выполнения.

...