5

クラス階層とコンストラクターは関連しています。子クラスからのパラメーターは、親に渡す必要があります。

したがって、Python では、次のようになります。

class Parent(object):
    def __init__(self, a, b, c, ka=None, kb=None, kc=None):
        # do something with a, b, c, ka, kb, kc

class Child(Parent):
    def __init__(self, a, b, c, d, e, f, ka=None, kb=None, kc=None, kd=None, ke=None, kf=None):
        super(Child, self).__init__(a, b, c, ka=ka, kb=kb, kc=kc)
        # do something with d, e, f, kd, ke, kf

多数の子クラスと多数のパラメーターがあると想像してください。新しいパラメータを追加するのは非常に面倒です。

もちろん、名前付きパラメーターを完全に省略して *args と **kwargs を使用することもできますが、それではメソッド宣言があいまいになります。

Python (2.6) でこれをエレガントに処理するためのパターンはありますか?

「エレガントに」とは、パラメーターの出現回数を減らしたいという意味です。a、b、c、ka、kb、kc はすべて、Child コンストラクター、Parent への super() 呼び出し、および Parent コンストラクターで 3 回出現します。

理想的には、親のinitのパラメーターを一度指定し、子のinitでは追加のパラメーターのみを指定したいと思います。

私はこのようなことをしたいと思います:

class Parent(object):
    def __init__(self, a, b, c, ka=None, kb=None, kc=None):
        print 'Parent: ', a, b, c, ka, kb, kc

class Child(Parent):
    def __init__(self, d, e, f, kd='d', ke='e', kf='f', *args, **kwargs):
        super(Child, self).__init__(*args, **kwargs)
        print 'Child: ', d, e, f, kd, ke, kf

x = Child(1, 2, 3, 4, 5, 6, ka='a', kb='b', kc='c', kd='d', ke='e', kf='f')

残念ながら、4、5、6 が kd、ke、kf に割り当てられるため、これは機能しません。

上記を達成するためのエレガントなpythonパターンはありますか?

4

3 に答える 3

8

「多数の子クラスと多数のパラメーター」は、パラメーターの命名に関係なく問題のように聞こえます。

少しリファクタリングするだけで、この階層を単純化し、非常に複雑なコンストラクターをなくすいくつかのStrategyオブジェクトを取り除くことができるのではないかと思います。

于 2009-07-29T20:20:00.567 に答える
3

私が見ることができる唯一の解決策は、リストされた変数と *args および **kwargs を組み合わせて使用​​することです。

class Parent(object):
    def __init__(self, a, b, c, ka=None, kb=None, kc=None):
        pass

class Child(Parent):
    def __init__(self, d, e, f, *args, kd=None, ke=None, kf=None, **kwargs):
        Parent.__init__(self, *args, **kwargs)
        pass

このようにして、各クラスに必要なパラメーターを確認できますが、それらを再入力する必要はありません。

注意すべきことの 1 つは、(d、e、f、a、b、c) になると、目的の順序 (a、b、c、d、e、f) が失われることです。*args を他の名前のないパラメーターの前に置く方法があるかどうかはわかりません。

于 2009-07-29T20:18:33.193 に答える
1

パラメータを独自のオブジェクトにグループ化しようとしました。たとえば、sourceDirectory、targetDirectory、temporaryDirectory、serverName、serverPort を渡す代わりに、DirectoryContext および ServerContext オブジェクトを使用します。

コンテキスト オブジェクトがより多くの動作やロジックを持ち始めると、ここで言及されている戦略オブジェクトにつながる可能性があります。

于 2009-07-29T21:01:05.663 に答える