2017-08-01 10 views
2

子クラス用のclassmethodコンストラクタを作成しようとしていますが、インスタンスを正しく初期化できません。super()を使用する子クラスのコンストラクタ - アンバインドメソッドを取得する__init __()

私はこのサイトで多くのブログと回答を読んだことがあり、他の人が投稿した内容を正確に試してみましたが、まだ役に立たないものです。うまくいけば、本当にシンプルなものが欠けていると思います私がしようとしているものの基本的な例:

class A(object): 
    def __init__(self, foo): 
     self.foo = foo 

class B(A): 

    @classmethod 
    def make_new(cls): 
     super(B, cls).__init__('bar') 

foobar = B.make_new() 

私は得続ける結合していない方法でのエラー:

TypeError: unbound method __init__() must be called with B instance as first argument (got str instance instead) 
+0

を私はあなたが私を取ってくれてうれしいです新たな質問に挑戦した後に新しい質問をするアドバイス。私はあなたがそれを達成するだろうと思った;)、質問のためのプラス、私は時間で答えることができなかった場合は申し訳ありません –

答えて

2

__init__方法は、通常のインスタンスメソッドではなく、クラスメソッドです。初期化するインスタンスが呼び出されたときにすでに作成されているインスタンスが必要です。 A.__init__("foo")が失敗するのとまったく同じ方法で現在のコードが失敗しています(これはsuperの障害ではありません)。

__init__ではなく__new__に電話したかったと思います。 __new__メソッドは、インスタンスを作成する実際の "コンストラクタ"メソッドです(通常、実際の作成ステップをobject.__new__に委任します)。継承した__new__メソッドをオーバーライドしていないため、のどちらかを使用する必要はありません(Aはそれをオーバーライドしないため、objectから)。

しかし、あなたは実際にそれを行う必要はありません。あなたのclassmethodが渡されたcls引数を呼び出すことができます。クラスを呼び出すと、インスタンスを構築するための通常の方法である:

class B(A): 
    @classmethod 
    def make_new(cls): 
     return cls("bar") # note that you also need to `return` the instance you create! 

クラスメソッドの目的はB.__init__を実行しないように設定されている場合は、のようなものをお勧めします:

class B(A): 
    @classmethod 
    def make_new(cls): 
     self = cls.__new__(cls) 
     super(B, self).__init__('bar') 
     return self 
+0

ありがとう、これは意味をなさないと私は問題があったと思ったが、私が作業しているコード)、私はクラスBの基本クラスのinitをオーバーライドしました。私はまだBインスタンスですが、Bのinitプロセスに従わない代替のコンストラクタとしてこのクラスメソッドを使用しようとしています。具体的には、JSONとして保存された以前のインスタンスの状態をロードし、それをオブジェクトのフォームに再構成するためのものです。これは別のプロセスに続いて、最初から新しいオブジェクトを作成します。 – iceblueorbitz

+0

ああ、おそらくあなたは 'self = cls .__ new __()'の後に 'super(B、self).__ init __()'(必要な引数をつけて)をしたいでしょう。もし 'B'がバイパスしたい独自の' __new__'メソッドを持っていれば 'cls .__ new__'の代わりに' super(B、cls).__ new __(cls) 'を呼びたいでしょうが、オーバーライドされた '__init__'メソッドをバイパスする必要がある場合のみ必要です。 – Blckknght

+0

ありがとう、これは完璧な意味合いがあり、私が見た他の多くの投稿やトピックから重要な情報が欠落しているようです。私は '__new__'はしばしば悩まされますが、JSON dictから履歴を再読み込みしてオブジェクトを再構築するための別のロジックが必要な場合にはうまくいきます。 – iceblueorbitz

関連する問題