クラス

投稿者: | 2022-12-06
  • 参考
    • https://gammasoft.jp/blog/difference-method-vs-function/
    • https://tdak.hateblo.jp/entry/20140406/1396773476

目次

メソッドと関数

  • メソッドと関数の違いとは?
  • 使い方(呼び出し方)の違いに着目するとわかりやすい

  • 関数
    • 単独で呼び出しができる
    • 例)組み込み関数の print()len()など

  • メソッド
    • データに付けて呼び出す
    • 例)a_list.append(data)など
    • データに紐付いて、処理や操作を行う関数のこと
    • メソッドを使うと、データに対していろんな操作を行える(命令型プログラミング
    • メソッドはデータの型に紐付いているため、呼び出せる種類もデータ型で異なる

オブジェクト

  • 簡単にいえば、データと命令(メソッド、処理ともいう)が一緒になっているもの
  • オブジェクトは、単なるデータではない。メソッドも持っている
  • そのため「振る舞い」を持っている。振る舞いとは「行動や動作のしかた。挙動」
  • ちなみに、プロパティとは上記でいうデータを指す(データ、状態、変数)
  • メソッドは、そのデータ(プロパティ)に紐付く関数のこと(再掲)

クラス

  • オブジェクトを設計するコードのこと、オブジェクトの設計図とも呼ばれる

インスタンス

  • クラスによって設計されたオブジェクトのことを、区別してそう呼ぶ
  • コンピューター的には、メモリーを確保した状態のことを「実体(インスタンス)」と呼ぶためかな

クラスとインスタンスの関係

つまり、クラスには実体はないが、インスタンス(オブジェクト)にはある、ってことか。

以下の例は、わかりやすい(たい焼きには振る舞いの概念が含まれていないが)

  • 家を建てる設計図:クラス、設計図をもとに建てた家:インスタンス
    • 家を建てるための設計図があるとします。
    • 設計図を元に、同じ形の家をたくさん建てることができます。
    • 設計図がただそこにあるだけでは家はできあがりません。
    • 設計図を元に大工さんがトンカンすると家が建ちます。
    • 設計図に書いてあるドアを開けることはできませんが、実際に建てた家のドアを開けることはできます。
  • たい焼きの型:クラス、型をつかって焼いたたい焼き:インスタンス
    • たい焼きの型を元に、同じ形のたい焼きをたくさん作ることができます。
    • たい焼きの型だけではお腹は膨れません。
    • 型に生地を流し込んで焼くことで食べることができます。
    • 型にはあんこが含まれませんが、実際に焼いたたい焼きにはあんこが含まれるかもしれません。

 プログラミングにおける実体化

  • クラス(設計図、型、定義)を元に、実体化させる必要がある
  • また実体化させることでインスタンスがもつプロパティやメソッドにアクセスができる

なぜオブジェクト指向なのか

  • 負担を減らすため
    • 生徒がたくさんいる学校を想像してみる
    • たくさんの部活動がある
    • 生徒はどこかの部活に所属している
    • 部活動の時間になった
    • 教師が生徒一人一人の部活動を調べて、「あなたは野球部だからこのユニフォームに着替えて校庭に行きなさい」「あなたは吹奏楽部だから音楽室へ行きなさい」と指示をするのは大変
    • 生徒に「部活動の時間ですよ」と伝えたら、それぞれが自身の部活動に合った自律した行動をとってくれれば教師の負担は軽くなる

  • 処理を複雑にさせない
    • プログラムでも同じことが言える
    • メインの処理がそれぞれのデータに対して細かく指示を出していると、処理が複雑になってしまう
    • 上の例をオブジェクト指向に当てはめると
    • 生徒はオブジェクト、教師はそれらのオブジェクトを扱う処理に近い
    • 複雑なプログラムはバグを生み出しやすく、また変更も難しくなる

クラスを定義する

  • 何も定義されていないMyClassという名前のクラス(設計図)を作成(白紙の設計図)
  • MyClassの後ろには()は付かない、
class MyClass:
  pass

インスタンスのアトリビュート

  • MyClassというクラス(設計図)から、インスタンス(オブジェクト)を作成する
  • クラスからインスタンスを作るためには、クラスを関数のように呼び出して、iという変数にMyClassから作ったインスタンスを代入する
  • MyClassは白紙の設計図のようなももので、それから作られたインスタンスは何のデータも持ってないし、メソッドも持たない
  • iに代入してはじめインスタンスができるってことか。
 i = MyClass()
  • インスタンスにデータを持たせたい場合アトリビュート(属性)を使う
  • valueという名前のアトリビュート(どんな名前でもよい)に数値を代入し、値を表示させる
  • つまり、インスタンスのアトリビュートに代入を行うとアトリビュートを定義できる
  • アトリビュートはインスタンスが持つことができる変数のようなもの

メソッドの定義と初期化メソッド

  • クラスにメソッドを追加するには、def文を使う
  • self とはインスタンス自身をさす。selfを使って、インスタンス自体を操作できる
  • 初期化メソッド __init__(self) はインスタンス生成時に自動的に実行される

メソッドと第1引数「self」

  • クラスを定義したら、__init__() と同様に、第1引数に必ず self を渡すこと
    • def __init__( self, 〜
  • そうすることで、引数 self にインスタンスが代入される
class Prism:
    def __init__(self, width, height, depth): # 初期化メソッドを定義
        self.width = width # アトリビュートを追加
        self.height = height
        self.depth = depth
        
    # 体積を求める
    def content(self):
        return self.width * self.height * self.depth
  • p1.height という式は、関数内 self.height と同じ。self がインスタンス自身を表している
  • つまり、self を使ってインスタンスにデータを登録し、メソッドを使ってメソッドの振る舞いを定義していく。これがPythonのクラス設計の流儀

dataclass

from dataclasses import dataclass

# 従来
class Person_bf():
    def __init__(self, first_name, last_name, age):
        self.firstname = first_name
        self.last_name = last_name
        self.age = age

# dataclassを利用
@dataclass
class Person():
    first_name: str
    last_name: str
    class_num: str
    math: int
    english: int
    science: int
    
    def average(self):
        return round((self.math + self.english + self.science) / 3, 0)
    
yamada = Person('taro', 'yamada', 'class 1', 80, 78, 90)
tanaka = Person('goro', 'tanaka', 'class 2', 90, 93, 87)
suzuki = Person('yoko', 'suzuki', 'class 3', 74, 90, 98)

print(f'{yamada.average()=}')
print(f'{tanaka.average()=}')
print(f'{suzuki.average()=}')