2014-04-09 38 views
1

據我所知,在Python中父類的方法被覆蓋。 所以所有的類方法默認都是虛擬的,如下面的代碼所示。覆蓋與Python中的虛擬類方法

class Parent(object): 

    def Method1(self): 
     print 'FOO' 

class Child(Parent): 

    def Method1(self): 
     print 'BAR' 

myInstance = Child() 

#Overridden method is called 
myInstance.Method1()        # BAR 

#Is it possible to do the following? 
myInstance.{something}       # FOO 

問題:

  • 是否有可能從實例子類的myInstance調用父類的方法Parent.Method1()

  • 是否有可能使def Parent.Method1(self)由具有相同名稱的方法來覆蓋,但一些不同的參數集def Child.Method1(self,x,y)

回答

2

您可以通過其在MRO下一個方法了super()功能搜索(方法解析順序)調用父方法:

class Child(BaseClass): 
    def Method1(self): 
     print 'BAR' 
     super(Child, self).Method1() # will call BaseClass.Method1 

其中self是實例引用,所以super(type(myInstance), myInstance).Method1()將達到同樣的方法之外的東西。

或者您可以訪問該類上的未綁定方法,並顯式傳遞該實例;你能做到這一點的方法太外:

BaseClass.Method1(myInstance) 

,因爲現在你所引用的方法是直接歸因於類代替,並在實例作爲一個明確的self該方法通過;你會在Child的方法中使用self

Python屬性(方法屬性也是)通過名稱查找,這些查找通過實例,然後搜索實例的類,然後通過每個父類,直到找到匹配;方法的簽名在這裏不起作用。

,您仍然可以覆蓋一個方法在子類中,更改簽名,但通過使用關鍵字參數保持兼容與父類的方法:

class Child(BaseClass): 
    def Method1(self, x=None, y=None): 
     if x is None and y is None: 
      # arguments left at defaults, call base method 
      return super(Child, self).Method1() 

     print 'BAR: {} and {}'.format(x, y) 

現在,如果你調用myInstance.Method1(),不帶任何參數,調用BaseClass.Method1()方法,傳入參數併發生其他事情。

+0

是,這對我來說很明顯。我無法弄清楚如何從子類的實例中調用父方法,因此我可以在程序中選擇要調用的方法(子方法或父方法) – Konstantin

+0

@Konstantin:這正是他的代碼向您展示的方式至。 – BrenBarn

+0

@BrenBarn,我不確定。這是使用'super()'從子類方法調用父方法,沒有問題。我想知道是否有任何方法讓孩子的實例調用它的方法或被覆蓋的父方法 – Konstantin

1

是否有可能調用子類的 實例myInstance的父方法Parent.Method1()?

您可以直接調用該方法,並通過您的實例作爲第一個參數:

>>> class A(object): 
...  def foo(self): 
...   print 'foo' 
... 
>>> class B(A): 
...  def foo(self): 
...   print 'bar' 
... 
>>> b = B() 
>>> A.foo(b) 
foo 

是否有可能使高清Parent.Method1(個體經營)不是通過一種方法來覆蓋 具有相同的名稱,但一些不同的參數集 def Child.Method1(self,x,y)?

是的,你用super並調用父類的直接方法:

>>> class A(object): 
...  def foo(self, bar='bar'): 
...   print bar 
... 
>>> class B(A): 
...  def foo(self): 
...   super(B, self).foo(bar='foo') 
... 
>>> B().foo() 
foo 
>>> A().foo() 
bar 
+0

謝謝你的回覆。是否有可能做類似B()。foo() - >調用父方法,B()。foo(x,y) - >調用子方法?所以參數集防止虛擬函數被覆蓋。 – Konstantin

+1

種。孩子可以將'foo'定義爲'def foo(self,arg1 = None,arg2 = None)',如果'arg1'和'arg2'都是'None',則調用父方法。子方法總是被調用,但是* it *可以決定調用父方法。通常,Python不會查看傳遞給方法的參數,以確定實際調用哪個函數。 (我現在看到的正是Martijn Pieters在他的回答中提出的。) – chepner

1

除了使用super,有一對夫婦的繞過MRO明確的選擇:

# Explicitly call Baseclass.Method1, passing your instance as the argument 
BaseClass.Method1(myInstance) 

# Call Method1 on the (first) base class of the instance. 
# This is ugly; don't actually write code like this 
# x.__class__.__bases__[0] is just another way to get a reference 
# to BaseClass; otherwise, this is identical to the previous option, 
# hence the need to repeat myInstance 
myInstance.__class__.__bases__[0].Method1(myInstance) 
+0

感謝您的回覆。好的補充! – Konstantin