LoginSignup
1
1

More than 1 year has passed since last update.

Pythonのクラス変数はコンストラクタで初期化しなさいなって話

Last updated at Posted at 2023-03-15

コメントにてご指摘いただきました。
筆者の勘違いから理解までの流れをお楽しみください。

事象

listをクラス変数として初期化していると、
インスタンスのsample_1sample_2listが共有されちゃいます。

Sampleクラス
class Sample:
    int_x:int = 0
    list_y:list = []
        
    def set_int(self, val):
        self.int_x = val
    
    def list_add(self, val):
        self.list_y.append(val)

インスタンス生成後、当然両方とも初期値です。

インスタンス生成後
sample_1 = Sample()
sample_2 = Sample()
# 1_int:0
# 1_list:[]
# 2_int:0
# 2_list:[]

sample_1intを変更してもsample_2intには影響ないですね。

intを変更
sample_1.set_int(3)
# 1_int:3
# 1_list:[]
# 2_int:0
# 2_list:[]

ただしsample_1listを変更するとsample_2listも変更されています!
クラス変数でもlistはシャロ―コピーされるっぽいですね、、、
全然違いました。
こちらの素晴らしくわかりやすいコメントをご参照ください。

listを変更
sample_1.list_add('TEST')
# 1_int:3
# 1_list:['TEST']
# 2_int:0
# 2_list:['TEST']

解決方法

タイトル通りsampleクラスをこんな感じで変更して、
コンストラクタ内でlistを初期化すると想定通りの動きになります。

修正後Sampleクラス
class Sample:
    int_x:int = 0
    list_y:list
    
    def __init__(self):
        self.list_y = []
        
    def set_int(self, val):
        self.int_x = val
    
    def list_add(self, val):
        self.list_y.append(val)

インスタンス生成後、intは前回と同じ動きになります。

インスタンス生成後
sample_1 = Sample()
sample_2 = Sample()
# 1_int:0
# 1_list:[]
# 2_int:0
# 2_list:[]

sample_1.set_int(3)
# 1_int:3
# 1_list:[]
# 2_int:0
# 2_list:[]

Sampleクラスを修正したことで、想定通りsample_2listは影響なく済みました!

listを変更
sample_1.list_add('TEST')
# 1_int:3
# 1_list:['TEST']
# 2_int:0
# 2_list:[]

Python結構長いこと使っていましたが全然知りませんでした、、、
みんな気を付けてくれよな!

1
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1