2009-05-21 2 views
38

Обращаясь к first answer о связанных и несвязанных методах 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»).

ответ

49

В форме, которую вы используете там, вы явно указываете, какой статический класс класса 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 
+0

Спасибо большое! Это то, чего я хотел. – Emma

+3

Действительно полезно. В моем случае мне нужно было получить доступ к классу экземпляра. Я сделал это следующим образом: 'instance .__ class __. My_method()' – Caumons

3

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

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

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

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

0

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

  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», которая известна только во время выполнения.

+0

В этот момент почему бы просто не сделать его методом класса? Затем он может быть переопределен и все еще называется статически (нет необходимости передавать параметр класса). –

Смежные вопросы