0

すべての A が AorB であり、すべての B が AorB であり、これらがすべて AorB であるように、クラス AorB を定義したいと考えています。もちろん、A と B は AorB のサブクラスでなければなりません。問題は、AorB.__init__私が自分自身を納得させることができないとき、それは別のものであるべきです。AorB ファクトリを定義することはできますが、できれば AorB コンストラクタを使用したいと考えています。

class AorB:
    def __init__(self,par):
        if par: self=A(par) #!
        else: self=B()      #!
    @staticmethod
    def from_par(par):
        if par: return A(par)
        else: return B()
class A(AorB):
    def __init__(self,par):
        self.par=par
class B(AorB):
    def __init__(self):
        pass
print(
    AorB.from_par(5),
    AorB.from_par(0),
    AorB(5),
    AorB(0),
    sep="\n")

ここでは自己への割り当てが機能しないことは知っていますが、意図を示したかっただけです。AorB私が言ったように、工場 (from_par) は正常に動作します。 asではなく asと呼びたいだけですAorB.from_par

PS。私は知っています、__init__おそらく手遅れです、自己のタイプはすでに決定されています。回答にメタクラスを自由に使用してください。それらについて何か役立つことを学ぶ時が来ました。:-)

4

1 に答える 1

3

ではできません__init__。が__init__呼び出されると、インスタンスはすでに作成されています

代わりにファクトリ関数が必要です。

class AorB: pass

class A(AorB):
    def __init__(self,par):
        self.par=par

class B(AorB):
    def __init__(self):
        pass

def AorB(par):
    return A(par) if par else B()

API の観点からは、違いはありません。またはインスタンスAorBのいずれかを生成する callable です。A()B()

もう 1 つの可能なルートは、__new__代わりに関数を定義することです。これはクラス コンストラクターです。

class AorB:
    def __new__(cls, par=None):
        if cls is not AorB: return super().__new__(cls)
        return super().__new__(A) if par else super().__new__(B)

class A(AorB):
    def __init__(self, par):
        self.par = par

class B(AorB):
    def __init__(self, par=None):
        pass

これは、実際には、より複雑なファクトリ関数です。このメソッドは、に基づくサブクラスの 1 つの__new__結果を返すことに注意してください。そのため、必要かどうかにかかわらず、と の両方にパラメータが渡されます。super().__new__parABpar

インスタンス化または直接if cls is not AorBを許可するには、この行が必要です。それが要件ではなく、ファクトリ クラスのみが使用されている場合は、その行を省略できます。A()B()AorB

于 2013-06-24T23:41:07.500 に答える