Python学習【365日チャレンジ!】80日目のマスターU(@Udemy11)です。
新年度が始まった4月も今日で最後になりましたが、4月の終わりに、切りの良いPython学習80日目を迎えられたのはなかなか気分がいいもんです。
とはいえ、いまの世の中はまさに、自宅にいることが求められている時期ですので、少し気分は沈みがちになりますが、逆に時間を有効に使えるチャンスと考えて、Udemyの講座を受講し、スキルアップを図りましょう。
こんなときだからこそ時間を有効活用して、自分のスキルを磨くか、永遠とYoutubeループを見つづけて無駄な時間を過ごすか、あなたの行動次第であなたの未来が大きく変わります。
この大変な時期をチャンスに変えるために、いますぐUdemyを活用しましょう!
それでは、今日もPython学習をはじめましょう!
昨日の復習
昨日は、クラスの継承について学習しました。
class Car:
def drive(self):
print('manual drive')
class ToyotaCar(Car):
pass
toyota_car = ToyotaCar()
toyota_car.drive()
出力結果
manual drive
Car
をベースクラスとして、5行目でToyotaCar
クラスがCar
を継承することで、Car
に定義されたdrive
メソッドを使うことができました。
ちなみに、pass
は何もしないという意味でしたね。
クラスの継承の詳細については、昨日の記事を参考にしてください。
それでは今日の学習内容にはいりましょう。
メソッドのオーバーライド
メソッドのオーバーライドとは、ベースクラスで定義したメソッドを継承先のクラスで上書き処理をすることです。
class Car:
def drive(self):
print('manual drive')
class ToyotaCar(Car):
def drive(self)
print('semi auto drive')
toyota_car = ToyotaCar()
toyota_car.drive()
出力結果
semi auto drive
ToyotaCar
は、Car
を継承しているので、drive
メソッドは、manual drive
ですが、7行目のオーバーライドによって、drive
メソッドがsemi auto drive
に上書きされます。
これは、引数のデフォルト値を入れているけど実行時に引数の値を入れるのと似ていますね。
ベースクラスで定義しているので、継承先のクラスでは記述の必要はないが、オーバーライドによって上書きが可能ということです。
super()の活用
続いて、コンストラクタで指定してしたベースクラスの引数をsuper()
を使ってオーバーライドしてみます。
class Car:
def __init__(self, name=None):
self.name = name
class ToyotaCar(Car):
def __init__(self, name='Crown', auto_drive=False):
super().__init__(name)
self.auto_drive = auto_drive
toyota_car = ToyotaCar()
print('Name:', toyota_car.name)
print('Auto Drive:', toyota_car.auto_drive)
出力結果
Name: Crown
Auto Drive: False
super()
は、ベースクラスのことを指すので、7行目のsuper().__init__(name)
は、Car
のname
ということです。
つまり、None
だったname
をCrown
に上書きするために、super()
を使っているということです。
super()を使う理由
今紹介した使い方の場合、7行目をself.name = name
と記述しても問題ないんじゃないの?と思った方もいるかもしれません。
わたしもそう思いました。
なぜsuper()
を使ってベースクラスを参照するのか不思議ですよね。
その答えは、オーバーライドにあって、クラスを継承した先で__init__
でコンストラクタを定義すると、すべて上書きされるので、ベースクラスで定義した処理がなくなってしまいます。
たとえば、
class Car:
def __init__(self, name=None):
self.name = name
print(1111)
print(12345)
print(133221)
このように数字を出力する処理をしていた場合(こんな処理はまずありえませんが例として)、クラスを継承したToyotaCar
で、コンストラクタを記述していなければ、ToyotaCar
のインスタンスを作った際に、4行目から6行目の数字が出力されます。
しかし、次のように__init__
をオーバーライドしてname
を変更すると、__init__
がまるごと上書きされるので、ベースクラスの4行目から6行目が削除されてしまい、数字が出力されません。
class ToyotaCar(Car):
def __init__(self, name='Crown')
self.name = name
# ベースクラスの数字の出力がない__init__に上書きされる
super()
を使えば、__init__
の一部分だけを指定して変更することができるわけです。
つまり、次のような記述にすれば、ToyotaCar
のインスタンスを作成したときに、初期化で4行目から6行目の数字が出力されます。
class Car:
def __init__(self, name=None):
self.name = name
print(1111)
print(12345)
print(133221)
class ToyotaCar(Car):
def __init__(self, name='Crown'):
super().__init__(name)
toyota_car = ToyotaCar()
出力結果
1111
12345
133221
ほんとややこしいですが、10行目のsuper().__init__(name)
は、ベースクラスの__init__
の第一引数(name
)に、新しいname
を代入していることを理解しておきましょう。
まるでパズル
引数が絡んできて、一体どの値を変更しているのかわけが分からなくなってしまいます。
今回も記事を書きながら、どのname
を指定しているのか、名前を変えながら、いろいろと試してようやく理解できたのですが、最初はなにがなんやらよくわかりませんでした。
なんとなく聞いていれば、わかった気になってしまうのですが、実際にコードを理解するには一つ一ついじりながら変更してみてはじめて分かることがたくさんあります。
コードをそのまま写経するのも勉強になりますが、ちょっと変えてみたり、追加したりすることで、どのように動いているのかがより理解できるようになります。
ぜひ、いろいろと試してみてください。
それでは、明日もGood Python!