クラスの定義
標準形
- クラス定義は、
class [クラス名]:
で始める - コンストラクタ名は
__init__
で決まっている(前後にアンダースコア2つ) - クラス変数(プロパティ)はコンストラクタで定義して明示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Person: def __init__(self, name, age): self.name = name self.age = age def show(self): print("name: " + self.name.ljust(10, ' ') + " age: " + str(self.age)) luice = Person("Luice", 28) john = Person("John", 30) luice.show() john.show() # name: Luice age: 28 # name: John age: 30 |
関数定義と同じく、クラスからオブジェクトを生成するときは、クラスを定義した後でなければならない。
1 2 3 4 |
instance = MyClass() # NameError: name 'MyClass' is not defined class MyClass: pass |
プロパティ
クラス変数(クラス・プロパティ)
クラス定義の直下で定義された変数はクラス変数となり、全てのインスタンスを通じて同じ値が参照される。一般的には[クラス名].[クラス変数名]で用いる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Person: company = 'ABC corp.' john = Person() john.name = 'John' luice = Person() luice.name = 'luice' print(john.name) print(luice.name) print(john.company) print(luice.company) print(Person.company) # John # luice # ABC corp. # ABC corp. # ABC corp. |
インスタンス変数(インスタンス・プロパティ)
インスタンス変数は、コンストラクタで定義して明示する。
1 2 3 4 5 6 7 8 9 10 11 12 |
class Person: def __init__(self, name): self.name = name john = Person("John") luice = Person("Luice") print(john.name) print(luice.name) # John # Luice |
インスタンス生成後にプロパティを定義することもできるが、あるインスタンスで定義したプロパティはそのクラスの他のインスタンスにはいきわたらない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Person: pass john = Person() luice = Person() philip = Person() john.name = "John" luice.name = "Luice" george = Person() print(john.name) # John print(luice.name) # Luice #print(philip.name) # AttributeError #print(george.name) # AttributeError |
なお上記のpass
文は、空のクラスのための構文。クラスの構文上は何か内容が必要なため、プレースホルダとしてpass
文を置いている。passはPythonの予約語で、何も行わない。
インスタンス変数はpublic
Pythonのインスタンス変数は全てpublicアクセス可能。これを隠蔽するのに、以下の方法がある。
- クラス変数の先頭にアンダースコアを1つ付ける(_)
- この方法は「作法」であり、普通に変数名を指定してアクセスが可能
- クラス変数の先頭にアンダースコアを2つ付ける(__)
- この方法はPythonでアクセスが拒否される
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Person: def __init__(self, name, age, nation): self.name = name self._age = age self.__nation = nation john = Person("John", 30, "US") print(john.name) print(john._age) print(john.__nation) # John # 30 # AttributeError: 'Person' object has no attribute '__nation' |
ただし(2)の方法でも実はアクセスが可能。アンダースコア2つを前置した変数は、_クラス名__変数名
に変換されるため、この変数名を使ってアクセスできる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Person: def __init__(self, name, age, nation): self.name = name self._age = age self.__nation = nation john = Person("John", 30, "US") print(john.name) print(john._age) print(john._Person__nation) # John # 30 # US |
メソッド
コンストラクタ
- コンストラクタの名前は
__init__
で決まっている - 少なくとも先頭に1つの、自己参照用の引数が必要
- この引数の変数名は任意だが、Pythonの慣習で
self
を用いることになっている
- この引数の変数名は任意だが、Pythonの慣習で
1 2 3 4 5 6 |
class MyClass: def __init__(self, p1, p2): self.property1 = p1 self.property2 = p2 instance = MyClass(10, 20) |
インスタンスメソッド
コンストラクタと同じく、インスタンスメソッドは最低1つの引数を持ち、第1引数はインスタンス自身への参照が渡される。
この引数の変数名は任意だが、Pythonの慣習でself
を用いることになっている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Person: def __init__(self, name): self.name = name def introduce(self): print('My name is ' + self.name) def cheer(me, greeting): print(greeting + ", I'm " + me.name) person = Person('Luice') person.introduce() person.cheer("Hi") # My name is Luice # Hi, I'm Luice |
クラスの継承
継承
基本的なクラスの継承方法は以下の手順による。
- 子クラスのclass宣言で親クラスを指定
- 子クラスのコンストラクタで親クラスのコンストラクタを呼ぶ
- 必要に応じて追加のプロパティを定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class ParentClass: def __init__(self, name): self.name = name class ChildClass(ParentClass): def __init__(self, name, age): ParentClass.__init__(self, name) self.age = age person = ParentClass('John') print(person.name) person = ChildClass('Luice', 35) print(person.name + ', ' + str(person.age) + 'years old') # 実行結果 # John # Luice, 35years old |
オーバーライド
子クラスで親クラスのメソッドをオーバーライドできる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
class ParentClass: def __init__(self, name): self.name = name def print_me(self): print('My name is ' + self.name) class ChildClass(ParentClass): def __init__(self, name, age): ParentClass.__init__(self, name) self.age = age def print_me(self): print('I am ' + self.name + ', ' + str(self.age) + 'years old') person = ParentClass('John') person.print_me() person = ChildClass('Luice', 35) person.print_me() # 実行結果 # My name is John # I am Luice, 35years old |
親クラスのメソッドの呼び出し
子クラスでオーバーライドしたメソッドでも、親クラスの名前を指定して、親のメソッドを呼び出せる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class ParentClass: def __init__(self, name): self.name = name def print_me(self): print('My name is ' + self.name) class ChildClass(ParentClass): def __init__(self, name, age): ParentClass.__init__(self, name) self.age = age def print_me(self): ParentClass.print_me(self) print(str(self.age) + 'years old') person = ChildClass('Luice', 35) person.print_me() # 実行結果 # My name is Luice # 35years old |
※super()メソッドを用いるべきか。