質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

4回答

489閲覧

Python3: インスタンスを他クラスに渡して処理することは避けるべきですか?

hirame19168

総合スコア3

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1グッド

0クリップ

投稿2019/08/11 08:42

編集2019/08/11 09:09

前提・実現したいこと

具体的な内容については書くことができないので少々分かりにくいかもしれませんが,最後まで読んでいただけると幸いです.

・入力ファイルを読み込む.
・読み込んだ結果を変数に格納(ここでは10個の変数があるとします).
・10個の変数をもとに出力ファイルを作成する.
というのがやりたいことです.

当初のプログラム

python

1def load_file(file): 2 """ 3 ファイルを読み込んで,いくつか処理を加えて変数val_1, ..., val_10を返す. 4 """ 5 return val_1, ..., val_10 6 7def make_file(arg_1, arg_2, ..., arg_10): 8 """ 9 受け取った変数をもとにファイルを作成. 10 """ 11 12if __name__ == "__main__": 13 val_1, ..., val_10 = load_file(file_name) 14 make_file(val_1, ..., val_10)

初めはこのようにしていたのですが,
・引数(と戻り値)が多すぎて扱いにくい
val_1, ..., val_10をまとめて利用する場面が他にもあり,そのたびに全てを渡すのは面倒かつミスが起こりやすい
と感じたため,次のようにval_1, ..., val_10をクラスにまとめることにしました.

(実際にはval_1, ..., val_10のように連番の変数ではなく,データ型もサイズも異なる変数なので,これらをvaluesといったリストに格納することは考えておりません.)

修正後のプログラム

python

1class Values: 2 def __init__(self): 3 """ 4 self.val_1, ..., self.val_10の初期化 5 """ 6 7class FileCreator: 8 def __init__(self, values): 9 self.values = values 10 11 def load_file(self, file): 12 """ 13 上と同様にファイルを読み込んでself.values.val_1, ..., self.values.val_10に値を入れる. 14 """ 15 16 def make_file(self): 17 """ 18 やることは上と同じだが,self.valuesの変数をもとにファイルを作成するので引数が必要ない. 19 """ 20 21if __name__ == "__main__": 22 values = Values() # このvaluesは他の場面でも利用する. 23 file_creator = FileCreator(values) 24 file_creator.load_file(file_name) 25 file_creator.make_file()

疑問

FileCreatorクラスが直接Valuesクラスのインスタンスを取り込んでいる以上,Valuesクラスの変更がFileCreatorクラスにもろに影響するという状況があると思います.そのため,このような書き方はコードの修正のしやすさという面でよろしくないのでしょうか.
(例えば,val_1という変数をval_aに変更した場合,FileCreatorクラス内の全てのself.values.val_1self.values.val_aに変える作業が発生します.)

また,このような状況ではどのようにすべきでしょうか.
自分としては,Valuesクラスのインスタンスを渡さず,FileCreatorのメンバ変数としてval_1, ..., val_10を定義してあげて,以下のような関数をFileCreator内で定義すればよいかと考えました.こうすればValuesクラス内の変数名に変更があっても,この部分のみの修正で済むと思います.

python

1def make_values(self): 2 values = Value() 3 values.val_1 = self.val_1 4 ... 5 values.val_10 = self.val_10 6 return values

クラスの扱いに関してよくわからないこと多いので,根本的に使い方が間違っていましたらご指摘いただけると幸いです.

大変長くなってしまい申し訳ありません.
お手数おかけしますが,何卒よろしくお願いします.

shirai👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

Valuesクラスにload(path),save(path)なりの関数を持たせる、つまりファイル操作させるのもひとつの自然な考えかと思います。

投稿2019/08/11 08:53

can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirame19168

2019/08/18 04:22

回答ありがとうございます. クラスを分けない方がいいかもしれませんね...... 検討してみます.
guest

0

Valuesの属性を直接読むのではなく、getter的な関数を用意して、FileCreatorからはその関数を呼ぶようにするのはどうでしょうか。

関数名を何らかの意味に対応した名前にしておけば、変更があってもValuesの中だけで閉じられると思います。

投稿2019/08/19 13:04

bsdfan

総合スコア4571

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirame19168

2019/08/31 10:52

回答ありがとうございます. たしかにそういう方法もありますね.参考にさせていただきます.
guest

0

ベストアンサー

使い方がよく見えないのですが継承させるのがスマートな気がします。
適宜改変してみてください。

python

1class Values(object): 2 def declare_variable(self, values): 3 self.val_1 = values[0] 4 self.val_2 = values[1] 5 self.val_3 = values[2] 6 ... 7 8class FileCreator(Values): 9 def __init__(self, values): 10 super().declare_variable(values) 11 12 def load_file(self, file): 13 # これは他のクラスでは使わない値のようなので 14 # 親クラスではなくここで宣言する 15 16 files = open(file) # すいませんここ適当です 17 18 # 変数(リスト)に何かの値を追加するで正しいですか? 19 self.val_1.append(files[0]) 20 self.val_2.append(files[1]) 21 self.val_3.append(files[2]) 22 ... 23 24 # load_fileで読み込んだ分もprintされる 25 def print_file(self): 26 print(self.val_1) 27 print(self.val_2) 28 print(self.val_3) 29 ... 30 31class Hokanobamen(Values): 32 def __init__(self, values): 33 super().declare_variable(values) 34 35 # load_fileの影響を受けてないのでvaluesの値だけがそのまま反映される 36 def print_val(self): 37 print(self.val_1) 38 print(self.val_2) 39 print(self.val_3) 40 ... 41 42 43if __name__ == "__main__": 44 file_creator = FileCreator(values) 45 file_creator.load_file(file_name) 46 file_creator.print_file() 47 hokanobamen = Hokanobamen(values) 48 hokanobamen.print_val()

コメントを受けて追記

だとしたらクラスは1つあれば大丈夫そうですね。
ファイル読み書き関連は全部適当に書いてます。
ModelViewControlを心がけると読みやすと思います。

python

1class RetouchFile(object): 2 def __init__(self, values): 3 self.val_1 = values[0] 4 self.val_2 = values[1] 5 self.val_3 = values[2] 6 def load_file(self, file): 7 self.load_data = open(file, 'r') 8 def edit_data(self): 9 self.val_1.append(self.load_data[0]) 10 self.val_2.append(self.load_data[1]) 11 self.val_3.append(self.load_data[2]) 12 def write_data(self): 13 data = [] 14 data.append(self.val_1) 15 data.append(self.val_2) 16 data.append(self.val_3) 17 write_data = open(file, 'w') 18 write_data.write(data) 19 20if __name__ == '__main__': 21 values = ... # どこか別のところからvaluesは持ってくる予定でしょうか 22 retouch_file = RetouchFile(values) 23 retouch_file.load_file(file) 24 retouch_file.edit_data() 25 retouch_file.write_data()

投稿2019/08/19 07:11

編集2019/08/19 12:45
shirai

総合スコア1290

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirame19168

2019/08/19 10:18

回答ありがとうございます. 質問が抽象的で大変申し訳ありませんでした. このプログラムの場合,Valuesクラスのインスタンス(というかメンバ変数val_1~val_10)をFileCreatorやHokanobamenが,それぞれで固有に保持しているという考えで合っていますでしょうか. 質問には書いていなかったのですが,一つのvalues = Values()というインスタンスを各処理に回したいと思っています(FileCreatorに渡すのもHokanobamenに渡すのもvaluesという一つのインスタンス). そういった場合の対処法をご教授いただければ幸いです.
shirai

2019/08/19 10:38

それぞれ固有に保持しているというところは正しいです。 if __name__ == '__main__'内の最終行に print(file_creator.val_1) print(hokanobamen.val_1) を追加してみてください。 fileで追加した分だけ差分が出るはずです。 インスタンスとはFileCreaterやHokanobamenではなく、file_createrやhokanobamenをさします。 各処理に回すというのはFileConectorのインスタンスメソッドで変化した valuesの値をHokanobamenでも使いたいということですか?
hirame19168

2019/08/19 11:45

> 各処理に回すというのはFileConectorのインスタンスメソッドで変化した valuesの値をHokanobamenでも使いたいということですか? そうです!個別にvaluesを保持している必要はなくて, file_creatorでload_file()してvaluesに値を入れる→このvalues内の値ををhokanobamenで処理→file_creatorに戻してmake_file() といったことができたらよいと考えています.
shirai

2019/08/19 12:45

回答追記しました。
hirame19168

2019/08/31 10:51

ありがとうございます. この方法で進めていこうと思います. 何度も回答していただき本当にありがとうございました.
guest

0

リストにできない、ではなく、それをリストにするにはどうすればいいかを考えればいいのでは

それさえできればあとは簡単でしょ。

投稿2019/08/11 11:28

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirame19168

2019/08/18 04:20

回答ありがとうございます. val_1~val_10は配列がほとんどなのですが,それらのサイズが異なります.それらをvaluesというリストに格納したときに values[0][0], values[1][0][0] といった具合にインデックスの書き方が変わってしまうのを避けたいというのがリストにしたくない理由でした.もう一度リストで上手く扱えないか考えてみたいと思います.
y_waiwai

2019/08/19 07:23

クラスなり配列なりサイズの違うものをリストに入れて処理するってのはふつーに行われてることですし、何がダメなのかよくわからないですね
hirame19168

2019/08/19 10:06

ダメというわけではないのですが,リストに入れたときにvalues[0]~values[10]それぞれ何なのかが分かりにくくなるのを避けたいんです(こっちの理由の方がメインです.というか上で述べた理由は大した問題ではないですね,すみません). val_1~val_10はリストで回して使うようなものではなくて場面ごとに使いたい変数で,よくあるゲームの例で言えばname, hp, weaponといった感じです.それをリストに入れてしまうと0番目がnameで...といった具合に知っておかなければならないですよね.ただ変数自体はまとめておきたいので,クラスに入れたいという話です. 「クラスやら配列やらをリストに入れて処理する」ことについては理解しているつもりですが,このような考えでクラスを利用するのは間違っていますでしょうか.
y_waiwai

2019/08/19 13:11

どうやら、今回の案件はそれぞれクラスを作ってそれで駆動するのがいいきがしますが。 #そんでそのインスタンスでリストを作ると
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問