71758


下のコードを実行すると  
結果は、

[code]

    出力結果: データ1 データ2
    
[/code]

となります。  
私は、

[code]

    出力結果: データ1
    
[/code]

となると予想しておりました。  
sample1とsample2は別メモリだと思ったからです。  
理解できないでいます。  
ご指導よろしくお願いいたします。

[code]

       class Sample:
        
          c_list = []
        
          def add_c_list(self,data):
            self.c_list.append(data)
        
        print("出力結果:", end=" ")
        sample1 = Sample()
        sample1.add_c_list("データ1")
        
        sample2 = Sample()
        sample2.add_c_list("データ2")
        
        for item_data in sample1.c_list:
          print(item_data, end=" ")
    
[/code]


CC BY-SA 4.0
2020-11-05T14:06:55.257
71754
2020-11-06T10:09:15.200
34450
question
python
インスタンスの考え方


ご質問のコメントにある重複候補のリンクとは[別の回答](https://ja.stackoverflow.com/a/56191)が端的で分かりやすく感じました。  
類似質問の回答で頻出するPythonチュートリアルの[クラスとインスタンス変数](https://docs.python.org/ja/3.7/tutorial/classes.html#class-
and-instance-variables)も良くまとまっていますので、ご一読をお勧めします。

class直下で宣言された変数は **クラス変数** と呼ばれ、全てのインスタンスで値が共有されます。  
class直下で宣言 **されてない** self変数は **インスタンス変数** と呼ばれ、個別のインスタンスごとに別々の値を持ちます。

下記のサンプルコードで、クラス変数とインスタンス変数のリストの値を可視化してみました。

**サンプルコード:**

[code]

    class Sample:
        c_list = []  #クラス変数
    
        def __init__(self):
            self.i_list = []  #インスタンス変数
    
        def add_list(self,data):
            self.c_list.append(data)
            self.i_list.append(data)
    
    sample1 = Sample()
    sample1.add_list("データ1")
    
    sample2 = Sample()
    sample2.add_list("データ2")
    
    print("sample1.c_list:", ",".join(sample1.c_list))
    print("sample2.c_list:", ",".join(sample2.c_list))
    print("sample1.i_list:", ",".join(sample1.i_list))
    print("sample2.i_list:", ",".join(sample2.i_list))
    
[/code]

**出力結果:**

[code]

    sample1.c_list: データ1,データ2
    sample2.c_list: データ1,データ2
    sample1.i_list: データ1
    sample2.i_list: データ2
    
[/code]


CC BY-SA 4.0
2020-11-06T01:08:17.530
71758
2020-11-06T01:08:17.530
9820
71754
answer


payaneco さんの説明に補足します。

c_list がいつもクラス変数と考えていると混乱する場合があります。

具体的には  
self.c_list.append(data)  
に以下のコードを追加した  
self.c_list = self.c_list + [data]  
self.c_list += [data]  
次のクラスでの動作は

[code]

    class Sample:
        c_list = []  #クラス変数
    
        def __init__(self):
            self.i_list = []  #インスタンス変数
    
        def add_list(self,data):
            self.c_list.append(data)
            self.c_list = self.c_list + [data]
            self.c_list += [data]
            self.i_list.append(data)
    
    sample1 = Sample()
    sample1.add_list("データ1")
    
    sample2 = Sample()
    sample2.add_list("データ2")
    
    print("Sample.c_list:", ",".join(Sample.c_list))
    print("sample1.c_list:", ",".join(sample1.c_list))
    print("sample2.c_list:", ",".join(sample2.c_list))
    print("sample1.i_list:", ",".join(sample1.i_list))
    print("sample2.i_list:", ",".join(sample2.i_list))
    
[/code]

**出力結果**

[code]

    Sample.c_list: データ1,データ2
    sample1.c_list: データ1,データ1,データ1
    sample2.c_list: データ1,データ2,データ2,データ2
    sample1.i_list: データ1
    sample2.i_list: データ2
    
[/code]

となります。  
これは

[code]

    def add_list(self,data):
        self.c_list.append(data)             # 1回目の呼び出しだけ c_list はクラス変数
        self.c_list = self.c_list + [data]   # 左辺の c_list はインスタンス変数、右辺はクラス変数
        self.c_list += [data]                # c_list はインスタンス変数
    
[/code]

と書いてしまうと  
self.c_list.append(data) については、1回目の呼び出しにおける self.c_list はクラス変数です。

self.c_list = self.c_list + [data] については、1回目の呼び出しでは右辺の self.c_list はクラス変数ですが、
**左辺の self.c_list はインスタンス変数** になってしまいます。  
しかもエラーになりません。

self.c_list += [data] では、インスタンス変数の c_list が生成されてしまっているため self.c_list
はインスタンス変数になります。

なお、add_list メソッドの2回目の呼び出し以降はすべて self.c_list はインスタンス変数になります。

クラス変数 c_list に対してノットインプレースな処理（束縛関係更新処理）を行うと c_list は途端にインスタンス変数として生成されてしまいます。  
これを防ぐには `type(self).c_list` でアクセスすることで常時クラス変数にアクセス可能です。  
（`self.__class__.c_list` によるアクセスでもクラス変数アクセスです）  
個人的には同じ名前のインスタンス変数を生成してしまわないよう `type(self).c_list` をお勧めします。


CC BY-SA 4.0
2020-11-06T10:09:15.200
71771
2020-11-06T10:09:15.200
41756
71754
answer