2

私はPythonでクラスB、Aのサブクラスを定義しようとしています。これは、非常に柔軟になるようにインスタンス化する複数の方法を受け入れることができます。A はメンバーが少ない単純なクラスです。A を記述して、位置/キーワード引数の組み合わせを許可し、一部の引数が省略された場合にデフォルト値を持つ方法を知っています。

私の問題はクラス B にあります。B は単に A に追加のメンバーが追加されたものです。しかし、B のインスタンスを作成するときは、次のいずれかを選択したいと考えています。

  • 位置引数/キーワード引数の組み合わせから作成されたインスタンス (A によく似ています)
  • 追加のメンバーと A の既存のインスタンス (またはコピー) を指定して作成されたインスタンス
  • A の既存のインスタンスのみを使用して作成され、余分なメンバーはデフォルト値を取得します。
  • A の既存のインスタンスと位置/キーワード引数の使用を相互に排他的にする

編集:このようなもの

class A:
    def __init__(self, x1=1, x2='a', x3=4.0)
        self.x1=x1
        self.x2=x2
        self.x3=x3

class B(A):
    def __init__(self, x1=1, x2='a', x3=4.0, x4='t')
        self.x4=x4
        A.__init__(x1,x2,x3)

しかし、次のように使用したいと思います。

a1=A()
b1=B()         # takes all defaults
b2=B(x4='r')   # x1,x2,x3 gets defaults from A
b3=B(a1,x4='z')  # use a1, an instance of A
b4=B(x1,x2,x3,x4) # defines manually all arguments
b5=B(a1,x1=2) # this one should not work because x1 can come from the instance a1 or x1
4

2 に答える 2

2

最も簡単なことは、おそらく、usesとB同じシグネチャを持つ単純な初期化子を使用して定義しA、次に、より複雑なシナリオを実行するためのクラスメソッドとして定義された追加のファクトリ関数を使用することです。そうすれば、2つの異なる構築方法が実際にまったく区別できない引数をとるときに、混乱することはありません。

だから次のようなもの:

class B(A):
    def __init__(self, some, args):
        A.__init__(self, some, args)

    @classmethod
    def fromA(cls, theA, extra=some_default):
        newB = cls(theA.some, theA.args)
        newB.extra = extra
        return newB
于 2012-10-29T13:36:41.660 に答える
0

私の経験では、このような複雑なケースを処理する最良の方法は*args, **kwargs、一連の条件を使用して手動で処理することです。たとえば、次のようになりB.__init__ます。

if isinstance(arg[0], A):
    if has_other_args:
        raise TypeError
    else:
        do_something()
else:
    do_something_else()

ただし、これはまだ非常に複雑になる可能性があるため、(Duncan によって提案されているように) ファクトリ関数がおそらく最良のアプローチです。

補足: この種の機能が必要な場合は、通常、設計に問題があることを示しています。実装したとしても、通常は全体の構造をよりきちんとしたものに置き換えることになります。

于 2012-10-29T13:41:29.433 に答える