Index
クラス
クラスは変数とメソッドを定義することができるオブジェクトの設計図のようなものです。
クラスを定義するときは、オブジェクト指向の概念を理解することが重要になります。下の記事にオブジェクト指向についての考え方を書いております。オブジェクト指向がよくわからない場合は、まずそちらをご覧ください。
(例:従業員を表すクラス)
class Employee: # クラス変数 company_name = "株式会社ニシキヘビ" def __init__(self, name, department): # インスタンス変数 self.name = name self.department = department def introduce(self): # クラス変数とインスタンス変数を使用するメソッド print(f"私の名前は{self.name}です。{Employee.company_name}の{self.department}で働いています。")
上の例からクラスでは次の3つを定義することができることが分かります。
- クラス変数
- インスタンス変数
- メソッド
クラス変数・インスタンス変数
クラス変数・インスタンス変数の違い
クラス変数とインスタンス変数の違いは次の通りです。
項目 | クラス変数 | インスタンス変数 |
---|---|---|
共通性 | すべてのオブジェクトで共有 | オブジェクトごとに独立 |
定義場所 | クラス定義内 | オブジェクト生成時 |
アクセス方法 | クラス名.変数名 | オブジェクト名.変数名 |
クラス全体で共通のものはクラス変数で定義し、インスタンスごとに変更したい共通の属性はインスタンス変数で定義します。
(再掲)
class Employee: # クラス変数 company_name = "株式会社ニシキヘビ" def __init__(self, name, department): # インスタンス変数 self.name = name self.department = department
先ほどの例では、従業員にとって会社名は共通のため、クラス変数でcompany_name
を定義します。従業員の名前や所属部署は全従業員に共通の属性ではありますが、その中身は従業員ごとに異なります。そのため、name
やdepartment
はインスタンス変数で定義します。
コンストラクタ(__init__)
__init__()
メソッドはコンストラクタと呼ばれ、このクラスのインスタンスが生成されたときに呼び出されます。__init__()
の第1引数self
はインスタンス自身を表します。
class Employee: # 省略 # コンストラクタ def __init__(self, name, department): # インスタンス変数 self.name = name self.department = department def main(): # オブジェクトの作成 employee1 = Employee("田中", "営業") employee2 = Employee("佐藤", "開発") if __name__ == '__main__': main()
上の例では、main()
内でインスタンスを作成しています。引数はインスタンス自身であるself
を除いたdepartment
が必要になります。
メソッド
クラスが持つ関数をメソッドと呼びます。メソッドの第1引数もコンストラクタ同様self
でインスタンス自身を指定し、第2引数以降でメソッドの引数を受け取ります。
class Employee: # 省略 # メソッドの定義 def introduce(self): # クラス変数とインスタンス変数を使用するメソッド print(f"私の名前は{self.name}です。{Employee.company_name}の{self.department}で働いています。") def main(): # オブジェクトの作成 employee1 = Employee("田中", "営業") employee2 = Employee("佐藤", "開発") # メソッドの呼び出し employee1.introduce() employee2.introduce() if __name__ == '__main__': main()
アクセス制限
アクセス制限の仕方
Pythonにはpublic
やprivate
などのアクセス修飾子はサポートされていません。アンダーバーを用い、アクセス制限を表現します。
先頭に付けるアンダーバーの個数 | 意味 |
---|---|
なし | 参照できる |
1個 | 参照できるが慣習的に外部から参照しない |
2個 | 参照できない(AttributeError) |
(例)
class MyClass: def __init__(self): self._name = "田中" @property def name(self): return self._name @name.setter def name(self, new_name): self._name = new_name def main(): human1 = MyClass() human1.name = "山下" print(f"名前:{human1.name}") if __name__ == '__main__': main()
上記の例のようにアクセス制限をするときはゲッター、セッターを使い、アクセスを制御します。
_name
のようにアンダーバーをつけることで外部から直接参照しないことを示しています。しかし、_name
の値を取得したい場合や値を変更したい場合があります。そのときはゲッター、セッターを介して値の取得、代入を行います。
ゲッターやセッターはプロパティと呼ばれるクラスのメンバで変数のように参照できる関数のことです。プロパティはデコレータと呼ばれる@
ではじまるキーワードを使い定義されます。デコレータは関数やクラスに特殊な振る舞いを注入することができる機能です。
(再掲:定義部分)
# ゲッター @property def name(self): return self._name # セッター @name.setter def name(self, new_name): self._name = new_name
プロパティ | 説明 | デコレータ |
---|---|---|
ゲッター | 外部から値を取得するためのプロパティ | @property |
セッター | 外部から値を代入するためのプロパティ | @変数名.setter |
前述の通り、プロパティは関数でありながら変数のように参照することができます。
def main(): human1 = MyClass() # セッターの呼び出し human1.name = "山下" # print内でゲッターを呼び出している print(f"名前:{human1.name}")
継承
継承とは
Pythonでも他のオブジェクト指向言語と同様、クラスを継承することができます。クラスを継承することでサブクラスは親クラスがもつ属性やメソッドを利用することができます。
class Animal: def __init__(self, name, age): self.name = name self.age = age def speak(self): raise NotImplementedError def eat(self): print(f"{self.name} は食事中") class Dog(Animal): def __init__(self, name, age, breed): super().__init__(name, age) self.breed = breed def speak(self): print(f"{self.name} はワンワン吠えます") def walk(self): print(f"{self.name} は散歩中です") def main(): # オブジェクト作成 pochi = Dog("ポチ", 3, "柴犬") # 継承した属性とメソッドの利用 print(pochi.name) # 出力:ポチ print(pochi.age) # 出力:3 pochi.speak() # 出力:ポチはワンワン吠えます pochi.eat() # 出力:ポチは食事中 pochi.walk() # 出力:ポチは散歩中です if __name__ == '__main__': main()
メソッドのオーバーライド
サブクラスでは親クラスのメソッドをオーバーライド(上書き)できます。
class Animal: # 省略 def speak(self): raise NotImplementedError # 省略 class Dog(Animal): # 省略 def speak(self): print(f"{self.name} はワンワン吠えます") # 省略
Animalクラスでspeck()
メソッドを定義し、サブクラスであるDogクラスでオーバーライドしています。今回は、詳細をサブクラスで定義したいため、親クラスではraise NotImplementedError
としています。
raise
は例外を発生させるためのキーワードです。raise NotImplementedError
は未実装のメソッドを呼び出した際に発生する例外となっています。
super()
super()
は親クラスを参照します。
class Dog(Animal): def __init__(self, name, age, breed): # サブクラスのコンストラクタ super().__init__(name, age) # 親クラスを参照し初期化 self.breed = breed
多重継承
Pythonは多重継承がサポートされています。
class Animal: def __init__(self, name): self.name = name class Voice: def __init__(self, sound): self.sound = sound class Dog(Animal, Voice): def __init__(self, name): super().__init__(name) self.sound = "bow wow" dog = Dog("Pochi") print(dog.name, dog.sound) # 出力: Pochi bow wow
複数のクラスに共通する性質をもつサブクラスを作りたい場合に多重継承をします。上の例では Animal クラスと Voice クラスを継承した Dog クラスを定義しています。