1. ホーム
  2. python

[解決済み] superの正しい使い方(引数渡し)

2022-07-21 12:22:54

質問

ということで、私は以下のように Pythonのスーパーは有害であると考えられている を読んでいて、彼の例を試しに行ってみました。

しかし 例 1-3 を呼び出す正しい方法を示すことになっています。 super を処理する際に __init__ メソッドを処理する場合、全くうまくいきません。

これは私が得たものです。

~ $ python example1-3.py 
MRO: ['E', 'C', 'A', 'D', 'B', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B
Traceback (most recent call last):
  File "Download/example1-3.py", line 27, in <module>
    E(arg=10)
  File "Download/example1-3.py", line 24, in __init__
    super(E, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 14, in __init__
    super(C, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 4, in __init__
    super(A, self).__init__(*args, **kwargs)
  File "Download/example1-3.py", line 19, in __init__
    super(D, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 9, in __init__
    super(B, self).__init__(*args, **kwargs)
TypeError: object.__init__() takes no parameters

どうやら object を使うメソッドは、このドキュメントで言及されているベストプラクティスのひとつに違反しているようです。 super を使うメソッドは *args**kwargs .

さて、明らかにナイト氏は自分の例がうまくいくことを期待していたわけですが、これは最近のPythonのバージョンで変更されたものなのでしょうか?2.6と2.7を確認しましたが、両方で失敗しています。

では、この問題に対処する正しい方法は何でしょうか?

どのように解決するのか?

2つのクラスが共通のパラメータ名を持っていることがあります。このような場合、キーと値のペアを **kwargs から削除したり *args . その代わりに Base クラスを定義します。 object とは異なり、引数を吸収/無視します。

class Base(object):
    def __init__(self, *args, **kwargs): pass

class A(Base):
    def __init__(self, *args, **kwargs):
        print "A"
        super(A, self).__init__(*args, **kwargs)

class B(Base):
    def __init__(self, *args, **kwargs):
        print "B"
        super(B, self).__init__(*args, **kwargs)

class C(A):
    def __init__(self, arg, *args, **kwargs):
        print "C","arg=",arg
        super(C, self).__init__(arg, *args, **kwargs)

class D(B):
    def __init__(self, arg, *args, **kwargs):
        print "D", "arg=",arg
        super(D, self).__init__(arg, *args, **kwargs)

class E(C,D):
    def __init__(self, arg, *args, **kwargs):
        print "E", "arg=",arg
        super(E, self).__init__(arg, *args, **kwargs)

print "MRO:", [x.__name__ for x in E.__mro__]
E(10)

イールド

MRO: ['E', 'C', 'A', 'D', 'B', 'Base', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B

なお、これが動作するためには Base は MRO の最後にあるクラスでなければなりません。