Pythonの基本~クラスと継承~
Pythonをやっていてクラス、メソッド、属性といった言葉をなんとなく理解していますが、きちんと理解しておきたいのでその周辺の学習をします。脇道?のような気もしますが、Pythonの基本なので避けては後々困るでしょうから早めにちゃんと学習しておきます。
とても分かりやすい記事として下記リンクがありました。
memopy.hatenadiary.jp
クラスは属性とメソッドの塊です。オブジェクトとしてこの一式を吐き出すときに呼び出されるのが__init__(self)でselfはクラス自身がselfですよと置くための絶対必要な引数で特別なので、第一引数に置くと言うことですね。
他のところではクラス名は頭文字を大文字にする習慣があると見たのでそうすることにします。
試しに、写経…だと完全な転載なので名前をオリジナルにしてソースコードを書きます。
class Class: def __init__(self): self.attribute = 10 object1 = Class() print(object1.attribute) object2 = Class() print(object2.attribute)
こうすると結果はこうなります。
10 10
二つのオブジェクトを作ることが出来ました。_init__オブジェクト生成の際に呼び出される特別な処理でコンストラクタと呼ばれるようです。さて、クラスを宣言した後でオブジェクト生成時に属性の値が簡単に変更出来るようにするには以下のようにコンストラクタに変更用の引数を定義してあげます。
class Class: def __init__(self, argument): self.attribute = argument object1 = Class(10) print(object1.attribute) object2 = Class(20) print(object2.attribute)
先のソースコードからargumentが増えただけです。オブジェクト生成時にClass(argumentの値)としてあげるとattributeにargumentの値が格納されて以下の結果となります。
10 20
ちゃんとClassが引数をattributeに格納していることが確認出来ました。Classは__init__以外にメソッドを持つことが出来ます。試しにメソッドを追加してみましょう。
class Class: def __init__(self, argument): self.attribute = argument def method1(self): print( "half of argument is " + str(self.attribute/2) ) object1 = Class(10) print(object1.attribute) print(object1.method1()) object2 = Class(20) print(object2.attribute) print(object2.method1())
method1を追加し、生成したオブジェクトのメソッドとして呼び出します。実行結果は以下の通り。
10 half of argument is 5.0 None 20 half of argument is 10.0 None
コンストラクタとメソッドで定義した出力以外でNoneという出力があります。これはメソッドが明示的にreturnと表記していなくてもとにかくreturnを返すという仕組みになっているためです。詳しくは以下のリンクに記載されています。
stackoverflow.com
続いてはクラスの継承についてやっていきます。
先ずは本当に継承するだけ。
class Class: def __init__(self, argument): self.attribute = argument def method1(self): print( "half of argument is " + str(self.attribute/2) ) class Class_mod(Class): pass object1 = Class_mod(10) print(object1.attribute) print(object1.method1()) object2 = Class_mod(20) print(object2.attribute) print(object2.method1())
これを実行すると…
10 half of argument is 5.0 None 20 half of argument is 10.0 None
となり、ClassとClass_modは同じクラスとして動作しています。これだと意味が無いのでクラスの中身をいじってみます。
class Class: def __init__(self, argument): self.attribute = argument def method1(self): print( "half of argument is " + str(self.attribute/2) ) class Class_mod(Class): def __init__(self, argument1, argument2): self.attribute2 = argument2 object1 = Class(10) print(object1.attribute) print(object1.method1()) object2 = Class_mod(10,100) print(object2.attribute2) print(object2.attribute) print(object2.method1())
生成されたobjectはClassとClass_mod用に2つがあります。object1はClassをそのまま実行するので、先の実行例と同じになる一方で、object2がClass_modにより生成されたオブジェクトとなります。
object2はattributeの属性に関してそのような属性はありませんとエラーになります。これはClass_modがClassを継承してその内容が変更される際に__ini__を行い、Classの__init_がオーバーライド(上書き)されてしまったためにClassのattributeが失われています。
そうならないように、Class_mod内でスーパークラスのClassにおける__init__を呼び出す一文を付け加えます。
class Class: def __init__(self, argument): self.attribute = argument def method1(self): print( "half of argument is " + str(self.attribute/2) ) class Class_mod(Class): def __init__(self, argument, argument2): Class.__init__(self, argument) self.attribute2 = argument2 object1 = Class(10) print("***** object1 *****") print(object1.attribute) print(object1.method1()) object2 = Class_mod(10,100) print("***** object2 *****") print(object2.attribute2) print(object2.attribute) print(object2.method1()) || 出力が見やすくなるように少し弄りました。これで実行してみると… >|| ***** object1 ***** 10 half of argument is 5.0 None ***** object2 ***** 100 10 half of argument is 5.0 None
以上のようにattributeエラーにならずにobject2が実行できました。上記の方法でもスーパークラスの継承は出来るのですが、Python3系ではsuper()を使う方法があります。実際に使ってみましょう。
class Class: def __init__(self, argument): self.attribute = argument def method1(self): print( "half of argument is " + str(self.attribute/2) ) class Class_mod(Class): def __init__(self, argument, argument2): super().__init__(argument) self.attribute2 = argument2 object1 = Class(10) print("***** object1 *****") print(object1.attribute) print(object1.method1()) object2 = Class_mod(10,100) print("***** object2 *****") print(object2.attribute2) print(object2.attribute) print(object2.method1())
ここで注意なのはsuper().__init__()の引数はselfを除くという点です。
また、Class_modの中でも新たにメソッドを定義可能で、Classのときと同じようにdefで定義してあげれば大丈夫です。
以上、クラスと継承についてでした。言葉をちゃんと覚えるって大切ですね。ということで、以下の記事を読んでおきたいと思います。
www.shido.info
まだ、理解しきれないですけど…そのうち分かるでしょう!笑