20. インスタンスメソッド

インスタンスメソッドの基本

クラスメソッドとは

OOPのメソッドは「歩く」「話す」「戦う」といった、オブジェクトの動作や振る舞いのことを指します。クラスメソッドは、クラス内に定義したメソッドのことを指します。

メソッドの例

項目 メソッド 備考
歩く walk スピード、方向などでキャラクターを移動する
話す talk 内容、相手などを指定して会話する
攻撃する attack キャラクターの能力、武器などから、相手に攻撃する

インスタンスメソッドとは

クラスインスタンスで実行できるメソッドをインスタンスメソッドといいます。

インスタンスメソッドの定義

インスタンスメソッドは「修飾子」「メソッド名」「データ型」でクラス内に定義します。

class クラス名:
    # インスタンスメソッド
    メソッド名():
       # 処理

自分のクラスのフィールドにアクセス

インスタンスを生成するとフィールドにアクセスできますが、メソッドの第1引数を利用してアクセスします。

class クラス名:
    フィールド

    メソッド名(self):
       self.フィールド

インスタンスメソッドの定義

Personクラスにインスタンスメソッドを定義します。

項目 メソッド名 引数 戻り値型
歩く walk direction void
話す talk person, message void
攻撃する attack person void

インスタンスメソッドの実装

Personクラスに walk() メソッドを実装します。

models/Person.py
class Person:
    name:str = ""
    job:str = ""
    hp:int = 0

    def walk(self, direction:str):
        message = f"{self.name} move to {direction}"
        print(message)

インスタンスメソッドの実行

インスタンスメソッドはインスタンスで実行します。 staticメソッドではないので、メソッド名で直接実行できません

インスタンス.メソッド名();

メインメソッドで実行

wizardインスタンスでインスタンスメソッドを実行します。

main_app1.py
wizard.walk("town")

メインプログラムを実行して、インスタンスメソッドの結果を確認してみましょう。

結果
アリス move to town

インスタンスと引数

インスタンスそのものを、メソッドの引数に渡すことができます。

talk() メソッドの実装

Personオブジェクトとメッセージを引数にした、talk() メソッドを定義します。

models/Person.py
class Person:
    ...

    def talk(self, person, message):
        message = f"{person.name}!{message}"
        print(message)

talk() メソッドの実行

talk() メソッドを実行します。

models/Person.py
...

warrior:Person = Person()
warrior.name = "ボブ"
warrior.job = "Warrior"
warrior.hp = 50

wizard.walk("town")
wizard.talk(warrior, "こんにちは")
結果
ボブ!こんにちは

インスタンスの参照

インスタンスはメモリーに保持

インスタンスはメモリーに状態を保持され、このインスタンスのメモリの場所を表す値を参照といいます。インスタンスが別のファイルで処理されたとしても、その状態は常に保持されます。

attack() メソッドの実装

attack() メソッドを実装し、引数で渡された Personオブジェクトのhpを計算します。ここでは、変数damageの値だけ引き算しました。

models/Person.py
class Person:
    ...

    def attack(self, person):
        damage = 5
        person.hp -= damage

attack() メソッドの実行

attack() メソッドにwarriorオブジェクトを渡して実行します。これはwizardwarriorに攻撃することを意味します。

main_app1.py
...
wizard.attack(warrior)
print(warrior.hp)

warriorオブジェクトのhpの数値が変化しました。

結果
45

ソース

models/Person.py
class Person:
    name: str = ""
    job: str = ""
    hp: int = 0

    def walk(self, direction: str):
        message = f"{self.name} move to {direction}"
        print(message)

    def talk(self, person, message):
        message = f"{person.name}!{message}"
        print(message)

    def attack(self, person):
        damage = 5
        person.hp -= damage

main_app1.py
from models.Person import Person

wizard:Person = Person()
wizard.name = "アリス"
wizard.job = "Wizard"
wizard.hp = 30

print(wizard.name)
print(wizard.job)
print(wizard.hp)

warrior:Person = Person()
warrior.name = "ボブ"
warrior.job = "Warrior"
warrior.hp = 50

wizard.walk("town")
wizard.talk(warrior, "こんにちは")

wizard.attack(warrior)
print(warrior.hp)

コンストラクタ

コンストラクタのメリット

コンストラクタ(constructor)は、インスタンス生成時に自動実行されるメソッドです。コンストラクタがないと、インスタンス生成の時点で、フィールド値が初期状態のままになってしまいます。そこでコンストラクタを使うと引数にフィールドに値を設定したり、共通処理を実行できます。

  • データ設定を必須にする
  • 必ず処理が実行される
  • コンストラクタの定義

Pythonのコンストラクタ

Pythonでは、コンストラクタは init という特殊なメソッド名で定義します。引数は定義できますが、戻り値は定義できません。

def __init__(self, 引数):
    # インスタンス生成時の処理

コンストラクタの実行

インスタンス生成でコンストラクタが実行

コンストラクタはインスタンス生成、つまりクラスを呼び出した時点で自動実行されます。

# クラスを呼び出すと実行
インスタンス = クラス名()

引数指定もできる

コンストラクタに引数がある場合は、引数指定もできます。

# 引数を使ってインスタンスを生成
インスタンス = クラス名(引数, ...)

コンストラクタの実装

コンストラクタの自動生成

「Person」クラスに init メソッドを使用して、引数を受け取りフィールドを初期化します。

models/Person.py
class Person:
    def __init__(self, name, job):
        print("キャラクタ新規作成")
        self.name = name
        self.job = job
        self.hp = 50
  • コンストラクタ内でコンソール出力し、hp=50としておきます。

引数のコンパイルエラー

Personインスタンス生成ではコンストラクタの引数がマッチしていないため、エラーになります。

引数の修正

Personのコンストラクタに「name」「job」を代入することで、プロパティが設定されます。

main_app1.py
# コンストラクタに name、jobを指定してインスタンスを生成
wizard = Person("アリス", "wizard")

# wizard = Person()
# wizard.name = "アリス"
# wizard.job = "Wizard"
# wizard.hp = 30

print(wizard.name)
print(wizard.job)
print(wizard.hp)

# コンストラクタに name、jobを指定してインスタンスを生成
warrior = Person("ボブ", "warrior")

# warrior = Person()
# warrior.name = "ボブ"
# warrior.job = "Warrior"
# warrior.hp = 50

wizard.walk("town")
wizard.talk(warrior, "こんにちは")

wizard.attack(warrior)
print(warrior.hp)
結果
キャラクタ新規作成
アリス
wizard
50
キャラクタ新規作成
アリス move to town
ボブ!こんにちは
45

演習

つぎのプログラムをみて回答してください。

models/Animal.py
from models.Animal import Animal

def main():
    dog = Animal()
    dog.type = "dog"
    dog.name = "ポチ"
    dog.crying = "わん!"

    cat = Animal()
    cat.type = "cat"
    cat.name = "ミケ"
    cat.crying = "にゃー!"

    dog.walk()
    dog.cry()
    cat.cry()
    cat.escape()

main()
animal_main.py
def main():
    dog = Animal()
    dog.type = "dog"
    dog.name = "ポチ"
    dog.crying = "わん!"

    cat = Animal()
    cat.type = "cat"
    cat.name = "ミケ"
    cat.crying = "にゃー!"

    dog.walk()
    dog.cry()
    cat.cry()
    cat.escape()

main()

問題1

Animalクラスの walk() のことを何といいますか?

  1. staticメソッド
  2. フィールド
  3. インスタンス
  4. インスタンスメソッド

問題2

animal_main.py を実行した結果はどれですか?

  1. わん! ポチが歩いた にゃー!
  2. わん! ポチが歩いた にゃー!ミケが逃げた
  3. ポチが歩いた わん! にゃー!ミケが逃げた
  4. ポチが歩いた わん! ミケが逃げた

問題3

つぎのプログラムがあります。

Animal.java
class Animal:
    def __init__(self, type, name, crying):
        self.type = type
        self.name = name
        self.crying = crying

    def walk(self):
        message = self.name + "が歩いた"
        print(message)

    def cry(self):
        print(self.crying)

    def escape(self):
        message = self.name + "が逃げた"
        print(message)
animal_main.py
from models.Animal import Animal

def main():
    dog = Animal("dog", "ポチ", "わん!")
    cat = Animal("cat", "ミケ", "にゃー!")
    elephant = Animal("elephant", "ジャンボ", "ぱおーん!")

    dog.cry()
    cat.escape()
    elephant.cry()
    dog.escape()

main()

Animalクラスの init 部分のことを何といいますか?

  1. クラス
  2. インスタンス
  3. インスタンスメソッド
  4. コンストラクタ

問題4

「animal_main.py」を実行した結果はどれですか?

  1. にゃー! ミケが逃げた ぱおーん! ポチが逃げた

  2. にゃー! ミケが逃げた わん! ポチが逃げた

  3. わん! ミケが逃げた ぱおーん! ジャンボが逃げた

  4. わん! ミケが逃げた ぱおーん! ポチが逃げた

  5. わん! ポチが歩いた にゃー!ミケが逃げた

  6. ポチが歩いた わん! にゃー!ミケが逃げた

  7. ポチが歩いた わん! ミケが逃げた

Python超入門