1. ホーム
  2. パイソン

[解決済み】Pythonのクラスはいつ使うべきですか?

2022-04-03 14:08:38

質問

私は2年ほど前からpythonでプログラミングをしています。主にデータ関連(pandas、mpl、numpy)ですが、自動化スクリプトや小さなウェブアプリも作っています。 私はより良いプログラマーになり、私のpythonの知識を増やそうとしています。私を悩ませることの一つは、私が(小さなWebアプリのためのランダムなflaskコードをコピーする以外)クラスを使用したことがないことです。 私はそれが何であるか一般的に理解していますが、私は単純な関数の上にそれらを必要とする理由を理解することができないようです。

私の質問を具体的に補足します。私は、複数のデータソース(mongo、sql、postgres、apis)からデータを取得し、多くのまたは少しのデータ加工と書式設定を行い、データをcsv/excel/htmlに書き込み、電子メールで送信する自動レポートを大量に書いています。 スクリプトは、250行から600行までです。 これを行うためにクラスを使用する理由はあるでしょうか?

どのように解決するのですか?

クラスは オブジェクト指向プログラミング . OOPは、コードの構成、再利用性、カプセル化に大きな関心を寄せています。

まず最初に、免責事項:OOPは、部分的には 関数型プログラミング これはPythonで多く使われている別のパラダイムです。Pythonでプログラミングする人すべてが(あるいはほとんどの言語が)OOPを使っているわけではありません。Java 8では、あまりオブジェクト指向でないこともたくさんできます。もしあなたがオブジェクト指向を使いたくないなら、使わないでください。もしあなたが、二度と使わないデータを処理するために単発のスクリプトを書くだけなら、そのままの書き方を続けてください。

しかし、OOPを使うべき理由はたくさんあります。

いくつかの理由を紹介します。

  • 組織化。 OOPは、コード内のデータと手順の両方を記述し定義する、よく知られた標準的な方法を定義しています。データとプロシージャの両方は、さまざまな定義レベルで(異なるクラスで)格納することができ、これらの定義について話すための標準的な方法があります。つまり、標準的な方法でOOPを使用すれば、後の自分や他の人があなたのコードを理解し、編集し、使用するのに役立つのです。また、複雑で任意のデータ保存メカニズム(ディクショ ンのディック、リスト、ディック、セットのディックのリストなど)を使用する代わりに、データ構造の断片に名前を付けて便利に参照することができるようになります。

  • 状態です。OOPは、状態を定義し、追跡するのに役立ちます。例えば、古典的な例ですが、学生を処理するプログラム(例えば成績プログラム)を作成する場合、学生について必要なすべての情報(名前、年齢、性別、学年、コース、成績、教師、仲間、食事、特別なニーズなど)を一箇所に集め、このデータはオブジェクトが生きている限り持続し、簡単にアクセスできるようにすることができます。

  • カプセル化 : カプセル化によって、プロシージャとデータは一緒に保存されます。メソッド(OOP用語で関数)は、メソッドが操作して生成するデータと一緒に定義されます。Java のような言語では アクセス制御 Pythonでは、パブリックAPIをどのように記述するかによって、メソッドとデータをユーザーから隠すことができることを意味します。このことは、コードを変更する必要がある場合、あるいは変更したい場合、コードの実装には何でもできるが、パブリックAPIは同じままにしておくということです。

  • 継承 : 継承を利用すると、データや手続きを一箇所(一つのクラス)で定義し、後からその機能をオーバーライドしたり拡張したりすることができます。例えば、Pythonの場合、よく dict クラスは、機能を追加するために使用されます。よくある変更は、存在しない辞書からキーが要求されたときに例外を投げるメソッドをオーバーライドして、未知のキーに基づくデフォルト値を与えるというものです。これにより、自分のコードを今すぐまたは後で拡張したり、他の人が自分のコードを拡張したり、他の人のコードを拡張したりすることができるようになります。

  • 再利用性。これらの理由とその他の理由により、コードの再利用性を高めることができます。オブジェクト指向のコードでは、一度しっかりとした(テストされた)コードを書けば、何度でも再利用することができます。もし、特定のユースケースのために何かを微調整する必要があれば、既存のクラスを継承して、既存の動作を上書きすることができます。もし何かを変更する必要があれば、既存のパブリックメソッドのシグネチャを維持したまますべてを変更することができ、誰も賢くなることはありません(希望的観測)。

繰り返しになりますが、OOPを使わない理由はいくつかありますし、使う必要もありません。でも、幸いなことにPythonのような言語では、ほんの少し使うことも、たくさん使うことも、あなた次第なのです。

学生の使用例です(コードの品質を保証するものではありません、単なる例です)。

オブジェクト指向

class Student(object):
    def __init__(self, name, age, gender, level, grades=None):
        self.name = name
        self.age = age
        self.gender = gender
        self.level = level
        self.grades = grades or {}

    def setGrade(self, course, grade):
        self.grades[course] = grade

    def getGrade(self, course):
        return self.grades[course]

    def getGPA(self):
        return sum(self.grades.values())/len(self.grades)

# Define some students
john = Student("John", 12, "male", 6, {"math":3.3})
jane = Student("Jane", 12, "female", 6, {"math":3.5})

# Now we can get to the grades easily
print(john.getGPA())
print(jane.getGPA())

標準ディクショナリ

def calculateGPA(gradeDict):
    return sum(gradeDict.values())/len(gradeDict)

students = {}
# We can set the keys to variables so we might minimize typos
name, age, gender, level, grades = "name", "age", "gender", "level", "grades"
john, jane = "john", "jane"
math = "math"
students[john] = {}
students[john][age] = 12
students[john][gender] = "male"
students[john][level] = 6
students[john][grades] = {math:3.3}

students[jane] = {}
students[jane][age] = 12
students[jane][gender] = "female"
students[jane][level] = 6
students[jane][grades] = {math:3.5}

# At this point, we need to remember who the students are and where the grades are stored. Not a huge deal, but avoided by OOP.
print(calculateGPA(students[john][grades]))
print(calculateGPA(students[jane][grades]))