「初期データとしてユーザーを10人生成したい」というときの
実装方法と注意点について説明する。
任意の数のデータを生成する
まずはクラスから生成したインスタンスではなく、
通常の数値や文字データの場合。
# 「1」というデータを5つ生成する
number_list: list[int] = [1] * 5
print(number_list)
# 実行結果
[1, 1, 1, 1, 1]
リストに対して* 5
を記載することで、そのデータを5個複製できる。
クラスからインスタンスを生成する場合(注意)
例えば以下のようなユーザークラスから生成したインスタンスを、3人分作りたいとする。
from dataclasses import dataclass
@dataclass
class User:
name: str
先程と同じように、以下のコードで生成してしまうとNG。
# "hoge"という名前のユーザーを3人分生成する
user_list: list[User] = [User("hoge")] * 3
print(user_list)
# 全員分のデータを出力する
for user in user_list:
print(f"id={id(user)} user_name={user.name}")
# 実行結果
[User(name='hoge'), User(name='hoge'), User(name='hoge')]
id=4472590608 user_name=hoge
id=4472590608 user_name=hoge
id=4472590608 user_name=hoge
どこがNGポイントかと言うと、インスタンスのIDが全て同一のものになってしまっている点だ。
この場合、仮にuser_list[0]
のデータを変更した場合、同時にuser_list[1]
とuser_list[2]
のデータも同じように変更されてしまう。
user_list: list[User] = [User("hoge")] * 3
print(user_list)
for user in user_list:
print(f"id={id(user)} user_name={user.name}")
user_list[0].name = "fuga"
print("user_list[0]の名前を「fuga」に変更しました")
for user in user_list:
print(f"id={id(user)} user_name={user.name}")
# 実行結果
[User(name='hoge'), User(name='hoge'), User(name='hoge')]
id=4439085520 user_name=hoge
id=4439085520 user_name=hoge
id=4439085520 user_name=hoge
user_list[0]の名前を「fuga」に変更しました
id=4439085520 user_name=fuga
id=4439085520 user_name=fuga
id=4439085520 user_name=fuga
どうしたらよいか?
これを解決するためには、以下のように書けばOK。
# リスト内包表記で、for文を使って「User("hoge")」を3回実行する
user_list: list[User] = [User("hoge") for _ in range(0, 3)]
print(user_list)
for user in user_list:
print(f"id={id(user)} user_name={user.name}")
# 実行結果
# 全てインスタンスIDが異なる状態で生成されていることが分かる
[User(name='hoge'), User(name='hoge'), User(name='hoge')]
id=4441985296 user_name=hoge
id=4441983312 user_name=hoge
id=4441983248 user_name=hoge
まとめ
- 数値や文字列をたくさん生成する場合は気にせず簡単な表記でOK
- クラスからインスタンスを生成する場合は、しっかりと都度インスタンスを生成するような実装が必要