はい、それは一方が不変で、もう一方が不変だからです。というか、一方を変異させ、他方を変異させていないということです。(重要なのは、オブジェクトが「変更可能」であるかどうかではなく、実際に変更するかどうかです。) また、インスタンス変数の代わりにクラス変数を使用しているためです (この質問を参照してください)。
クラス定義では、クラスのすべてのインスタンスで共有される 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
場合は、常にインスタンス アトリビュートに割り当てられます。同じ名前のクラス属性が既に存在する場合、インスタンス属性はそれを非表示にします。