Переопределение статического метода в python
Ссылаясь на первый ответ о связанных с 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" ).
Ответы
Ответ 1
В том виде, который вы там используете, вы явно указываете, какой класс static method_two
должен вызывать. Если method_three
был classmethod, и вы вызвали 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
Ответ 2
Поведение, которое вы видите, - это ожидаемое поведение. Статические методы... статические. Когда вы вызываете method_three()
, определенный в Test
, он обязательно вызовет method_two()
, определяемый Test
.
Что касается того, как "обойти" это правильное поведение...
Самый лучший способ - сделать методы виртуальными, когда вы хотите виртуального поведения. Если вы застряли в некотором библиотечном коде со статическим методом, который, по вашему желанию, был виртуальным, вы могли бы глубже понять, есть ли причина или если это просто надзор.
В противном случае вы можете определить новый method_three()
в T2
, который вызывает T2.method_two()
.
Ответ 3
Кроме того, если вы хотите вызвать функцию "виртуальный статический" без экземпляра, вы можете продолжить так:
-
Объявить функцию в базовом классе нестатической, как показано ниже:
class Base:
def my_fun(self):
print('my_fun base')
class Derived(Base):
def my_fun(self):
print('my_fun derived')
-
Вызовите его, передав тип класса, который не является экземпляром, например:
Derived.my_fun(Derived)
Обратите внимание: это полезно, если у вас есть переменная "class_type", которая известна только во время выполнения.