75

親から継承するクラス変数を子クラスに変更してもらいたいのですが。

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

class Parent(object):
    foobar = ["hello"]

class Child(Parent):
    # This does not work
    foobar = foobar.extend(["world"])

そして理想的には:

Child.foobar = ["hello", "world"]

私はそれをできた:

class Child(Parent):
    def __init__(self):
      type(self).foobar.extend(["world"])

しかし、Childのインスタンスをインスタンス化するたびに、「world」がリストに追加されますが、これは望ましくありません。さらに次のように変更できます。

class Child(Parent):
    def __init__(self):
      if type(self).foobar.count("world") < 1:
          type(self).foobar.extend(["world"])

ただし、動作する前にChildのインスタンスをインスタンス化する必要があるため、これはまだハックです。

もっと良い方法はありますか?

4

3 に答える 3

76

サブクラスに別のリストを作成したい場合、親クラスのリストを変更しないでください (その場で変更するか、最初から期待値をそこに置くだけなので、これは無意味に思えます)。

class Child(Parent):
    foobar = Parent.foobar + ['world']

これは継承とは無関係に機能することに注意してください。これはおそらく良いことです。

于 2012-11-15T19:16:55.170 に答える
39

クラス変数で変更可能な値を使用しないでください。インスタンス初期化子を使用して、代わりにインスタンスにそのような値を設定します。__init__()

class Parent(object):
    def __init__(self):
        self.foobar = ['Hello']

class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()
        self.foobar.append('world')

foobarそうしないと、リストがインスタンス間だけでなくサブクラス間でも共有されるため、どうなりますか。

いずれにせよ、変更可能なクラス変数を介してインスタンス間で状態を共有したい場合でも、親クラスの変更可能なものを変更しないようにする必要があります。名前への割り当てのみが新しい変数を作成します。

class Parent(object):
    foobar = ['Hello']

class Child(Parent):
    foobar = Parent.foobar + ['world']

クラスの新しい foobar変数が作成されChildます。割り当てを使用することで、新しいリスト インスタンスが作成され、Parent.foobarミュータブルは影響を受けません。

そのような場合、ネストされたミュータブルに注意してください。必要に応じて、copyモジュールを使用してディープ コピーを作成します。

于 2012-11-15T19:15:14.563 に答える