目的
- クラスメソッドの効果的な使い方を考える
- 中の人が初めてクラスメソッドを学んだので、使い方の備忘録として記述する
ポイント
- classmethodはインスタンス化しないでクラス内の要素にアクセスできる
- @classmethodでクラスメソッドを修飾する
- classmethodは引数に自分自身のクラスを持ち、自分自身をclsと記述する
中の人が考えたclassmethodの使いどころ
- 以下の状況が重なったとき
- クラスが何かのソースを参照したデータを持っている
- ソースが変わったときに別のクラスを生成したい
- ソースごとにサブクラスを定義するのは冗長である
- (インスタンス生成前にクラスにデータを持たせたい)
## 結論
今回の例はインスタンス生成時にソースを指定するコンストラクタを書いておけばいいんジャマイカ・・・
中の人の技量が足りなかったため、効果的な使い方を提示するに至らなかった。
また、下記コードは意図しない動作になっていることが判明しました。
中の人のレベルが上がったら修正します。
誤解誤認されませんよう、お気をつけください。
コード
データソースの準備
sample_data_for_clasmethod1.csv
0,10
1,20
2,30
3,40
sample_data_for_clasmethod2.csv
0,1
1,2
2,3
3,4
クラスの定義
- pandasで読み込んだdfを保持するcls.dataを有するクラス
- クラスメソッドで指定したデータソースをdfにしてcls.dataに保持する機能を持たせる
- インスタンスメソッドで各列の合計を計算する機能を持たせる
classmethod_for_learning.py
import pandas as pd
class SampleData:
data_kind = 'CSV'
def __init__(self, data_name):
""" 初期化 """
self.data_name = data_name
def show_sum_1st_column(self):
return self.data.iloc[:,0].sum()
def show_sum_2nd_column(self):
return self.data.iloc[:,1].sum()
@classmethod
def load_data_source(cls, data_path):
cls.data = pd.read_csv(data_path)
return cls
実行コード
- プリント関数内の文書のように動作確認を行うコード
- データのソースはsample_data_for_clasmethod1.csv
- データソース指定後は、クラスオブジェクトをsample1と定義する
main1.py
print('sample1を与えたクラスメソッドの動作を確認する')
sample1 = SampleData.load_data_source('sample_data_for_clasmethod1.csv')
print(sample1.data_kind)
print(sample1.data)
print()
sample1_ins = sample1('sample1_dataを与えたクラスで生成したインスタンスであるsample1_ins')
print(sample1_ins.data_name)
print('sample1_insのデータを確認する(クラスメソッドから呼び出す)')
print(sample1_ins.data)
print('sample1_insのメソッドを確認する')
print('0列目合計', sample1_ins.show_sum_1st_column())
print('1列目合計', sample1_ins.show_sum_2nd_column())
- 同様にデータのソースをsample_data_for_clasmethod2.csvに変更して実行
- データソース指定後は、クラスオブジェクトをsample2と定義する
main2.py
print('sample2を与えたクラスメソッドの動作を確認する')
sample2 = SampleData.load_data_source('sample_data_for_clasmethod2.csv')
print(sample2.data_kind)
print(sample2.data)
print()
sample2_ins = sample2('sample2_dataを与えたクラスで生成したインスタンスであるsample2_ins')
print(sample2_ins.data_name)
print('sample2_insのデータを確認する(クラスメソッドから呼び出す)')
print(sample2_ins.data)
print('sample2_insのメソッドを確認する')
print('0列目合計',sample2_ins.show_sum_1st_column())
print('1列目合計',sample2_ins.show_sum_2nd_column())
実行結果
- クラス内にデータを保持していることが確認できた
- クラス内のデータをクラスメソッドで変更できた。
- データのソースが異なるクラスを、それぞれ別名のクラスオブジェクト(sample1とsample2)に定義できた
- インスタンス化してもクラス内のデータは保持された
- それぞれのインスタンスのメソッドにより異なるソースの処理を行えた
sample1を与えたクラスメソッドの動作を確認する
CSV
0 10
0 1 20
1 2 30
2 3 40
sample1_dataを与えたクラスで生成したインスタンスであるsample1_ins
sample1_insのデータを確認する(クラスメソッドから呼び出す)
0 10
0 1 20
1 2 30
2 3 40
sample1_insのメソッドを確認する
0列目合計 6
1列目合計 90
sample2を与えたクラスメソッドの動作を確認する
CSV
0 1
0 1 2
1 2 3
2 3 4
sample2_dataを与えたクラスで生成したインスタンスであるsample2_ins
sample2_insのデータを確認する(クラスメソッドから呼び出す)
0 1
0 1 2
1 2 3
2 3 4
sample2_insのメソッドを確認する
0列目合計 6
1列目合計 9