記載日:2023/02/05
pythonのclassやmoduleについて、自分なりに考えてみました。
そんなに知見があるわけではないのですが、実際のコードを書いてみて感じたことを記載します。同じ疑問を感じた方にとって、少しでも疑問解消の助けになればと思います。
流れ
以降では、以下のように進めていきます。
・まず、classとmoduleのそれぞれで同じ機能を書いてみる。
・次に、それぞれを比較して分かることを考えてみる。
結論を書くと、それぞれに良いところがありました。使う状況によって使い分けていくことになりそうです。
・moduleのメリット
module(__init__.py)のコード量が少なく、Main.pyでの呼び出しもシンプル(インスタンスを作ってない)
・classのメリット
classではインスタンスを作ることで、複雑な機能をMain->classへ委任(委譲)できる。
(コンストラクタによる共通引数の一括渡しや、メソッド間で共用できるprivate変数の使用ができる。)
classとmoduleの具体例
以下プロジェクト構成を考えてみます。
このプロジェクトでは、ユーザの指定する数字と"count"とを足し算することを5回します。
"count"は、1からスタートし、足し算が行われる毎に1増えることとします。
プロジェクト
|
|-Classes
| |
| |-Calc.py
|
|-Modules
| |
| |-Calc
| |
| |-__init__.py
|
|-Main.py
classを使った場合
Classes/Calc.pyのコード
class Calc:
def __init__(self, count):
self.count=count
def SumCount(self, num):
return num+self.CountUp()
def CountUp(self):
self.count+=1
return self.count
Main.pyのコード
import sys
from Classes.Calc import Calc as CalcC
def Main():
calc=CalcC(0)
for arg in sys.argv:
ans=0
if IsInt(arg):
ans=calc.SumCount(int(arg))
else:
print(arg)
print(ans)
# 出力は以下となる。1週目(sys.argv[0])では、"Main.py"と"0"が出力。
#
# > python Main.py 4 6 7 3 9
# > Main.py
# > 0
# > 5
# > 8
# > 10
# > 7
# > 14
def IsInt(arg):
try:
int(arg)
except ValueError:
return False
else:
return True
if __name__=="__main__":
Main()
moduleを使った場合
Modules/Calc/__init__.pyのコード
def SumCount(num, count):
return num+count
Main.pyのコード
import sys
import Modules.Calc as CalcM
def Main():
i=0
for arg in sys.argv:
ans=0
if IsInt(arg):
ans=CalcM.SumCount(int(arg), i)
else:
print(arg)
print(ans)
i+=1
# 出力は以下となる。1週目(sys.argv[0])では、"Main.py"と"0"が出力。
#
# > python Main.py 4 6 7 3 9
# > Main.py
# > 0
# > 5
# > 8
# > 10
# > 7
# > 14
def IsInt(arg):
try:
int(arg)
except ValueError:
return False
else:
return True
if __name__=="__main__":
Main()
それぞれのコードを比べてみると
moduleとclassを比べると、以下のようなことが言えるかと思います。
・moduleのメリット
__init__.pyのコード量が少なく、Main.pyでの呼び出しもシンプル(インスタンスを作ってない)
・moduleのデメリット(classのメリット)
今回は簡単な例なので大した違いはないが、引数の数が多い場合や引数を使った処理が複雑な場合、メソッドを使う度に多くの引数を書かなくてはいけなかったり、Main.pyのコード量が多くなってしまう。
(classでは、コンストラクタやprivate変数を使うことでカウント処理を委任(委譲)できる。)
参考にさせて頂いたサイト
__init__.pyについて
https://qiita.com/msi/items/d91ea3900373ff8b09d7
ディレクトリ構成について
https://rinatz.github.io/python-book/ch04-07-project-structures/