Python 応用編 2日目

Pythonのクラスとは、オブジェクト指向プログラミングの基本的な概念の一つです
この章では、Pythonにおけるクラスの基本的な機能について説明していきます

Pythonでのクラスについて

オブジェクト指向とは、プログラムの要素をモノ(オブジェクト)として扱う考え方のことです
オブジェクトはデータ(属性)と機能を持ち、それらを組み合わせてシステムを構築します

Pythonのクラスはオブジェクトの構造を定義するための型で、属性とメソッドを一つにまとめて定義した設計図のようなものです。この設計図であるクラスから新しいインスタンスを生成します
それぞれのインスタンスは自身の状態を保持する「データ属性」と状態を変更するための「メソッド」(機能)を持つことができます

クラスからインスタンスを生成する操作のことを「インスタンス化(実体化)」と言います

クラスの定義とインスタンス化

クラスを生成するには、以下のように記述します

class クラス名:

class クラス名と記述したあとコロン(:)の後ろで改行し、次の行からはインデントして記述していきます
クラス名は、自由につけることができますが、1文字目は英大文字、2文字目以降は英小文字または数字を使うことが推奨されています。また、クラス名が複数の単語から生成されている場合は、各単語の先頭を英大文字にすることで単語の境目を表します

空のクラスの作成

データ属性やメソッドを持たない空のクラスは以下のように記述します

class クラス名:
    pass

インスタンスを作成し変数に保存するには、以下のように記述します

変数 = クラス名(変数,変数,,,)

以下は、空のクラスを定義しインスタンスを作成するサンプルプログラムです

class MyClass:
  pass

m = MyClass()
print(type(m))
実行結果
<class '__main__.MyClass'>

m = MyClass()

クラスの新しいインスタンスを生成し、そのオブジェクトをローカル変数mへ代入します
ローカル変数mの型はMyClassとなっています

インスタンス変数

データ属性を使い、インスタンスで値を保持することができます
インスタンスが保持している変数を「インスタンス変数」と言い、各インスタンスで固有のデータです
インスタンス変数はクラスの中で共通して使用できる変数です

インスタンス変数は、クラス定義内で明示的に定義されていなくても、値を代入することでインスタンス内に自動的に生成されます
これにより、インスタンス変数を動的に後から追加できます

インスタンス変数へは以下のようにアクセスします

インスタンス.インスタンス変数名 =# 代入
インスタンス.インスタンス変数名 # 参照

以下はMyClassというクラスを定義し、インスタンスm1,m2を作成しインスタンス変数を設定したサンプルプログラムです

class MyClass:
  pass

m1 = MyClass()

m1.name="Taro"
m1.age=21
print(m1.name)
print(m1.age)

m2 = MyClass()
m2.name="Jiro"
m2.age=22
print(m2.name)
print(m2.age)
実行結果
Taro
21
Jiro
22

インスタンスの初期化

クラスには「__init()__」という名前の特殊メソッドを定義することで、インスタンス化の際に自動的にこのメソッドが呼び出されます
「__init()__」メソッドはインスタンス変数の初期化をするために使うことができます

class クラス名:
    def __init__(self,引数1,引数2,,)
        self.属性名1 = 引数1

__init__メソッドの最初の引数はselfと記述することが暗黙のルールとなっています
selfはインスタンス自身のオブジェクトが格納されています
このselfを使い、インスタンス変数の更新や参照をすることができます

以下に__init__メソッドを使ったサンプルプログラムを示します

class MyClass:
  def __init__(self):
    print("コンストラクタが呼ばれました。")

m1 = MyClass()

m1.name="Taro"
m1.age=21
print(m1.name)
print(m1.age)
実行結果
コンストラクタが呼ばれました。
Taro
21

また、属性を__init__メソッドで初期化するサンプルプログラムを示します

class MyClass:
  def __init__(self,name,age):
    self.name = name
    self.age = age

m1 = MyClass("Taro",21)
print(m1.name)
print(m1.age)

m2 = MyClass("Jiro",22)
print(m2.name)
print(m2.age)
実行結果
Taro
21
Jiro
22

メソッドを定義

クラス内で独自のメソッドを以下のように定義します

class クラス名:
    def メソッド名(self,引数,,,):

上記のメソッドは処理の対象となるインスタンスを指定して呼び出すメソッドなので「インスタンスメソッド」と呼びます
定義したメソッドは以下のように呼び出します

インスタンス.メソッド名(引数,,,)

先に作成したMyClassにintroduce()というメソッドを追加してみます

class MyClass:
  def __init__(self,name,age):
    self.name = name
    self.age = age

  def introduce(self):
    print("私の名前は" + self.name + "です。")
    print("年齢は" + str(self.age) + "です。")

m1 = MyClass("Taro",21)
m1.introduce()

m2 = MyClass("Jiro",22)
m2.introduce()
実行結果
私の名前はTaroです。
年齢は21です。
私の名前はJiroです。
年齢は22です。

【演習問題】

  1. Circleクラスを作成し円周、面積を計算するメソッドを実装する
    Circleクラス:
     半径
     面積を計算するメソッド
     円周を計算するメソッド
     ※円周率は3.14とする
    (1) Circleクラスからインスタンスを作成する
    (2) 半径から円の面積、円周を計算し表示する
    実行結果
    半径を入力してください:4.5
    円の面積:63.585
    円周の長さ:28.26

クラスの派生と継承

「派生」とはあるクラスをベースにして別のクラスを定義することで、ベースになるクラスを「基底クラス」、基底クラスから派生したクラスを「派生クラス」と呼びます
派生クラスは基底クラスがもつ属性やメソッドを受け継ぎます
これを「継承」と呼びます

派生と継承が効果的に利用できるのは、似た機能を持った複数のクラスが存在する場合です
共通の機能を基底クラスに抜き出し、各クラスを派生クラスにすることにより重複する処理を基底クラスにまとめることができます

派生クラスの定義

派生クラスは以下のように定義します

class クラス名(基底クラス名,,,)
    

派生クラスを定義する際、複数の基底クラスを指定することができます
この章では1つの基底クラスを指定した場合の説明を行います

以下に商品の名前と価格を表示するサンプルプログラムを示します

class Goods():
  def __init__(self,name,price):
    self.name = name
    self.price = price

  def show_info(self):
    print("商品名:" + self.name)
    print("価格:" + str(self.price) + "")

class Book(Goods):
  def __init__(self,name,price,code):
    super().__init__(name,price)
    self.code = code

  def show_info(self):
    super().show_info()
    print("コード:" + self.code)

class Music(Goods):
  def __init__(self,name,price,artist):
    super().__init__(name,price)
    self.artist = artist

  def show_info(self):
    super().show_info()
    print("アーティスト:" + self.artist)

b1 = Book("吾輩は猫である","660","4041001013")
b1.show_info()
print()
m1 = Music("ニュー・ベスト・バッハ100","2167","Bach")
m1.show_info()
実行結果
商品名:吾輩は猫である
価格:660円
コード:4041001013

商品名:ニュー・ベスト・バッハ100
価格:2167円
アーティスト:Bach

class Goods():

まず、基底クラスのGoodsを作成します。基底クラスではデータ属性として商品名を価格を保持し、show_info()というメソッドで商品名と価格を表示する処理を用意しています

class Book(Goods):

基底クラスのGoodsから派生したBookクラスを作成します。基底クラスのデータ属性以外に、ISBNコードを保持しています

 def show_info(self):
    super().show_info()
    print("コード:" + self.code)

Bookクラスのshow_info()メソッドは、基底クラスのshow_info()メソッドをオーバーライドしています
オーバーライドとは、基底クラスから継承したメソッドを派生クラスで再定義することです
オーバーライドを行うには、派生クラス側で、基底クラスから継承したメソッドと同じ名前のメソッドを定義します
派生クラスのインスタンスからオーバーライドしたメソッドを呼び出すと派生クラスで定義したメソッドが呼び出されます
派生クラスで再定義したメソッドの中で、基底クラスから継承したメソッドを呼び出すとき、super()関数を使って呼び出しています

class Music(Goods):

基底クラスのGoodsから派生したMusicクラスを作成します。基底クラスのデータ属性以外に、アーティスト名を保持します

def show_info(self):
    super().show_info()
    print("アーティスト:" + self.artist)

Musicクラスのshow_info()メソッドも、基底クラスのshow_info()メソッドをオーバーライドしています

b1 = Book("吾輩は猫である","660","4041001013")
b1.show_info()

Bookクラスからインスタンスを生成し変数b1に代入しBookクラスのshow_info()メソッドを呼び出します

m1 = Music("ニュー・ベスト・バッハ100","2167","Bach")
m1.show_info()

Musicクラスからインスタンスを生成し変数m1に代入しMusicクラスのshow_info()メソッドを呼び出します

【演習問題】

  1. 次の要件を満たすプログラムを作成する
    Personクラス:
     名前(文字列)
     性別(文字):’m’→男性、’f’→女性を表す
     年齢(整数)
     表示するためのメソッド(Introduction)を用意:名前、性別、年齢を表示
    Patientクラス:(Personクラスからの派生クラスとして作成する)
     身長(cm)
     体重(kg)
     表示するためのメソッド(Introduction)を用意:名前、性別、年齢、身長、体重を表示
     適正体重(BMI)より大きいか小さいかを表示するメソッドを作成する
     ※ 適正体重(BMI)=体重(kg) ÷ (身長(m)× 身長(m))
    • (1)Patientクラスからインスタンスを作成し指定した名前、性別、年齢、身長、体重を表示する
      (2)適正体重(BMI)が25より大きければ「肥満です」、小さければ「肥満ではありません」と表示する
   実行結果
   私の名前はTaroです。
   年齢は21です。
   性別は男性です。
   身長は175.5cmです。
   体重は65.7kgです。
   肥満ではありません。

コメント

この記事へのコメントはありません。

関連記事

Java 応用編 1日目

Python 基本編 3日目

Python 基本編 2日目

PAGE TOP