2016-09-14 18 views
1

私は4つの異なるクラスを持っています。メインの基底/親クラス、この親クラスから継承する2つのメインクラス、およびこれらのメインクラスの両方から継承する別のクラスがあります。同じ名前で親クラスと異なる数の引数を持つメソッドがある場合は、TypeErrorを取得します。同じメソッド名でも異なる引数を持つ複数の継承はTypeErrorを作成します

# Example 

class Parent(object): 
    def check(self, arg): 
     tmp = { 
      'one': False, 
      'two': False 
     } 

     try: 
      if 'one' in arg: 
       tmp['one'] = True 

      if 'two' in arg: 
       tmp['two'] = True 
     except TypeError: 
      pass 

     return tmp 

class Child(Parent): 
    def check(self, arg): 
     return Parent.check(self, arg)['one'] 

    def method(self, arg): 
     if self.check(arg): 
      print 'One!' 

class ChildTwo(Parent): 
    def check(self, arg): 
     return Parent.check(self, arg)['two'] 

    def method(self, arg): 
     if self.check(arg): 
      print 'Two!' 

class ChildThree(Child, ChildTwo): 
    def check(self, arg, arg2): 
     print arg2 
     return Child.check(self, arg) 

    def method(self, arg): 
     if self.check(arg, 'test'): 
      print 'One!' 

     ChildTwo.method(self, arg) 

test = ChildThree() 
test = test.method('one and two') 

runfile('untitled6.py', wdir='./Documents')
test
One!
Traceback (most recent call last):
File "< stdin >", line 1, in < module >
File "C:\Users\py\AppData\Local\Continuum\Anaconda2\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 714, in runfile
execfile(filename, namespace)
File "C:\Users\py\AppData\Local\Continuum\Anaconda2\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 74, in execfile
exec(compile(scripttext, filename, 'exec'), glob, loc)
File "untitled6.py", line 49, in
test = test.method('one and two')
File "untitled6.py", line 46, in method
ChildTwo.method(self, arg)
File "untitled6.py", line 34, in method
if self.check(arg):

TypeError: check() takes exactly 3 arguments (2 given)

私は 'ChildThree' の 'チェック' メソッドから二番目の引数を削除する場合しかし、正常に動作するようです:

class ChildThree(Child, ChildTwo): 
    def check(self, arg): 
     return Child.check(self, arg) 

    def method(self, arg): 
     if self.check(arg): 
      print 'One!' 

     ChildTwo.method(self, arg) 

runfile('untitled6.py', wdir='./Documents')
One!
Two!

私はにかなり新しいですクラス/継承のため、単一の引数で親クラスメソッドを呼び出すにもかかわらず、余分な引数が原因でTypeErrorが発生する理由がわかりません。

答えて

1

は、この行を考えてみましょう:

ChildTwo.method(self, arg) 

あなたが明示的selfに渡されました。 selfは、ChildThreeインスタンスへの参照です。その後、ChildTwo.methodのボディに:

if self.check(arg): 

それは私たちがここで話している同じselfです。 selfはまだChildThreeインスタンスの参照です。

selfは何か魔法をかけると予想されていますが、そうではありません。それは単純な古い名前です。 ChildTwoインスタンスを参照するには、バインドされたメソッドのように呼び出さなければなりませんでした。比較対照:

  • my_child_two.method(arg) < - 「自己」が記述プロトコル
  • ChildTwo.method(self, arg) <によって暗黙的に渡される - 「自己」とは、それは継承のこのタイプが呼び出され
+0

ああ、それは理にかなっています!私は(私は3分待つと言うことができます)私は答えを受け入れるよ。これを修正する良い/ Pythonの方法はありますか?または 'ChildTwo.method'の本文で 'selfTho.check(self、arg)'に 'self.check(arg):'を変更するだけですか? – PyNoob

+0

私がお勧めする方法は、継承の状況で、同じ名前と異なる引数の仕様を持つメソッドを避けることです。それは不必要に複雑に聞こえるだけであり、「ピジョンソニック」の大部分はシンプルさです。 – wim

1

は何でもちょうどです"The Diamond Problem"。それは、自分自身のためのトピックですので、私は単純なケースで説明します:

class C1(object): 
    def check(self, arg): 
     return 1 

    def method(self, arg): 
     return self.check(arg) 

class C2(C1): 
    def check(self, arg1, arg2): # this overrides C1.check! 
     return x + C1.check(self, arg1) 

c2 = C2() 
c2.method(55) # fails 

C2.checkオーバーライドすべてのC2インスタンス上C1.check。したがって、self.check(arg)methodから呼び出されると、C2のインスタンスに対してC2.checkが呼び出されます。 C2.checkは2つの引数を取るので失敗します。

解決方法メソッドをオーバーライドするときは、シグネチャ(受信した引数の数と型、戻り値の型)を変更しないでください。そうしないと、問題が発生します。

[詳細]*args and **kwargsの機能で自由度を増やすことができます。


はそれに加えて、私は見ることChildThree.check通話Parent.checkを呼び出しますが、誰もがChildTwo.checkを呼び出しChild.check。それは正しいことではありません。 すべての基本クラスのメソッドを呼び出すか、親実装を2回呼び出しても安全です(これはここでも可能です)。super()を使用してください。

関連する問題