[解決済み】多重継承で親クラスの__init__を呼び出す、正しい方法は?
質問
多重継承のシナリオがあるとします。
class A(object):
# code for A here
class B(object):
# code for B here
class C(A, B):
def __init__(self):
# What's the right code to write here to ensure
# A.__init__ and B.__init__ get called?
の書き方には、2つの典型的なアプローチがあります。
C
's
__init__
:
-
(旧スタイル)
ParentClass.__init__(self)
-
(新型)
super(DerivedClass, self).__init__()
ただし、いずれの場合も、親クラス(
A
と
B
)
が同じ規則に従わない場合、このコードは正しく動作しません。
(いくつかは見逃されたり、何度も呼ばれたりすることがあります)。
では、正しい方法とは何でしょうか? 一貫性を保つために、どちらかに従いなさいというのは簡単ですが、もし
A
または
B
がサードパーティライブラリから来たものである場合、どうすればよいのでしょうか? すべての親クラスのコンストラクタを確実に呼び出す(しかも正しい順序で、一度だけ)アプローチはあるのでしょうか?
編集:もしそうなら、私が言いたいことを見るために。
class A(object):
def __init__(self):
print("Entering A")
super(A, self).__init__()
print("Leaving A")
class B(object):
def __init__(self):
print("Entering B")
super(B, self).__init__()
print("Leaving B")
class C(A, B):
def __init__(self):
print("Entering C")
A.__init__(self)
B.__init__(self)
print("Leaving C")
すると、こうなる。
Entering C
Entering A
Entering B
Leaving B
Leaving A
Entering B
Leaving B
Leaving C
なお
B
のinitは2回呼ばれます。 そうすると
class A(object):
def __init__(self):
print("Entering A")
print("Leaving A")
class B(object):
def __init__(self):
print("Entering B")
super(B, self).__init__()
print("Leaving B")
class C(A, B):
def __init__(self):
print("Entering C")
super(C, self).__init__()
print("Leaving C")
すると、こうなる。
Entering C
Entering A
Leaving A
Leaving C
注意点
B
のinitが呼ばれることはありません。 つまり、私が継承するクラスの init を知っているか制御していない限り、 (
A
と
B
) 私が書いているクラスでは無難な選択はできない(
C
).
解決方法は?
どちらの方法でも問題ありません。 を使用する方法
super()
は、サブクラスに対してより大きな柔軟性をもたらします。
直接呼出し方式では
C.__init__
の両方を呼び出すことができます。
A.__init__
と
B.__init__
.
を使用する場合
super()
を使用する場合、クラスは協調的な多重継承ができるように設計する必要があります。
C
を呼び出す
super
を呼び出し、それが
A
のコードも呼び出されます。
super
を呼び出す。
B
のコードです。 参照
http://rhettinger.wordpress.com/2011/05/26/super-considered-super
で何ができるのか、詳しくは
super
.
[後日編集された回答質問]
ということで、自分が使っているクラスのinitがわからない/コントロールできない限りは AとBを継承したクラスでは、安全な選択をすることができません。 を書きます(C)。
参照記事では、この状況に対処するために、ラッパー・クラスを周囲に追加する方法を紹介しています。
A
と
B
. 非協力的なクラスを組み込む方法" と題されたセクションに、実践的な例があります。
多重継承がもっと簡単で、CarクラスとAirplaneクラスを組み合わせてFlyingCarを作ることができればと思うかもしれませんが、現実には別々に設計されたコンポーネントがシームレスにフィットするまでにアダプターやラッパーが必要になることがよくあります :-)。
もうひとつ、多重継承による機能合成に不満がある場合は、コンポジションを使って、どのメソッドがどの場面で呼ばれるかを完全にコントロールすることも可能です。
関連
-
PythonによるLeNetネットワークモデルの学習と予測
-
ピローによる動的キャプチャ認識のためのPythonサンプルコード
-
[解決済み】なぜ「LinAlgError: Grangercausalitytestsから「Singular matrix」と表示されるのはなぜですか?
-
[解決済み】numpyの配列連結。"ValueError:すべての入力配列は同じ次元数でなければならない"
-
[解決済み】 AttributeError("'str' object has no attribute 'read'")
-
[解決済み】Python - "ValueError: not enough values to unpack (expected 2, got 1)" の修正方法 [閉店].
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。
-
[解決済み] Pythonで型をチェックする標準的な方法は何ですか?
-
[解決済み] Pythonのsuper()は多重継承でどう動くのか?
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
python call matlab メソッドの詳細
-
Python 可視化 big_screen ライブラリ サンプル 詳細
-
Pythonの学習とデータマイニングのために知っておくべきターミナルコマンドのトップ10
-
Python入門 openを使ったファイルの読み書きの方法
-
[解決済み】「RuntimeError: dictionary changed size during iteration」エラーを回避する方法とは?
-
[解決済み】csv.Error:イテレータはバイトではなく文字列を返すべき
-
[解決済み】Pythonでgoogle APIのJSONコードを読み込むとエラーになる件
-
[解決済み】LogisticRegression: Pythonでsklearnを使用して、未知のラベルタイプ: '連続'を使用しています。
-
[解決済み】Python: SyntaxError: キーワードは式になり得ない
-
[解決済み】ValueError: xとyは同じサイズでなければならない