3

コードは次のようになります。

class A(object):
    x = 0
    y = 0
    z = []
    def __init__(self):
        super(A, self).__init__()
        if not self.y:
            self.y = self.x
        if not self.z:
            self.z.append(self.x)

class B(A):
    x = 1

class C(A):
    x = 2

print C().y, C().z
print B().y, B().z

出力は

2 [2]
1 [2]

なぜz上書きされないのyですか?不変型ではないからでしょうか。私はpythonのドキュメントを見ましたが、説明が見つかりませんでした。

4

3 に答える 3

3

はい、それは一方が不変で、もう一方が不変だからです。というか、一方を変異させ、他方を変異させていないということです。(重要なのは、オブジェクトが「変更可能」であるかどうかではなく、実際に変更するかどうかです。) また、インスタンス変数の代わりにクラス変数を使用しているためです (この質問を参照してください)。

クラス定義では、クラスのすべてのインスタンスで共有される 3 つのクラス変数を作成します。クラスのインスタンスを作成した後、そのインスタンスで行うと、インスタンスの属性としてself.xは見つかりませんが、クラスで検索されます。x同様self.zに、クラスを調べて、クラス上のものを見つけます。zクラス変数を作成したため、クラスのすべてのインスタンス間で共有されるリストは1 つだけであることに注意してください(オーバーライドしない限り、すべてのサブクラスのすべてのインスタンスを含みますz)。

を実行すると、インスタンスのみに新しいアトリビュート、インスタンスself.y = self.xアトリビュートが作成されます。

ただし、 を実行してself.z.append(...)も、新しいインスタンス変数は作成されません。むしろ、self.zクラスに保存されているリストを検索し、appendそのリストを変更します。「上書き」はありません。リストは 1 つしかなく、追加を行うとその内容が変更されます。( があるため、1 つの項目のみが追加されますif not self.z。したがって、1 つを追加した後、それは false であり、後続の呼び出しはそれ以上何も追加しません。)

要するに、属性の値を読み取ることは、それに割り当てることと同じではないということです。の値を読み取るときself.x、クラスに格納され、すべてのインスタンス間で共有される値を取得している可能性があります。ただし、値を に割り当てるself.x場合は、常にインスタンス アトリビュートに割り当てられます。同じ名前のクラス属性が既に存在する場合、インスタンス属性はそれを非表示にします。

于 2013-03-18T04:18:31.177 に答える
0

Pythonが本体を評価するとclass A、単一のlistオブジェクトがインスタンス化され、に割り当てられzます。サブクラスはそれをオーバーライドせず、listオブジェクトは参照によってPythonに格納されるため、3つのクラスはすべて同じzリストを共有します。したがって、インスタンス化した最初のクラスにデータが入力さzれ、残りのクラスにはそこに配置されたものがすべて取得されます。リストの内容を変更しましたが、参照するリストzは変更していません。

y以前の値を置き換えて、整数をオブジェクトの内部ディクショナリに直接割り当てているため、これは影響しません。

これを修正するには、コンストラクター内に配列を作成し、次のように割り当てます。

class A(object):
    x = 0
    y = 0
    z = None
    def __init__(self):
        super(A, self).__init__()
        if not self.y:
            self.y = self.x
        if not self.z:
            # create a new list
            z = [self.x]

class B(A):
    x = 1

class C(A):
    x = 2

print C().y, C().z
print B().y, B().z
于 2013-03-18T04:20:57.387 に答える
0

問題は、xyは不変であるのに対し、zは可変であり、それを変更することです。

self.z.append()を置き換えるのではなくz、 にアイテムを追加するだけzです。

(2 つの異なるオブジェクトを作成している)を実行C()した後は、空ではないため、 に評価されなくなります。print C().y, C().zCself.zFalse

2行を逆にするprintと、出力は次のようになります

1 [1]
2 [1]
于 2013-03-18T04:18:35.593 に答える