アラフォーおじさんの日常奮闘記

最近は多忙でバドミントンがご無沙汰になってきて、どちらかと言うと英語やプログラミング学習での気付きをシェアすることが多くなってきたブログ。

<python勉強日記>super().__init__()の意味がわからないので色々なパターンで試してみたらわかるようになった☆

こんにちは😊

ずーっと体育館が使えないので、羽根が打ててません。

こういう時は勉強が捗りますね。

 

私は毎日pythonを勉強しています。

今回、classの継承を勉強している中で、super().__init__()ってのが出てきたのですが、その存在、どう動作するのかがイマイチ理解できませんでした。そこで、色々試してみたところわかるようになってきたので、備忘録として残したいと思います。

ちなみに、作業環境はcolabです。

あとすいません、なぜか文章のレイアウトがどうやっても崩れるので

見づらいかもですがご了承ください。

 

 

まずは継承について軽くおさらい

はじめに、こんな感じのclassを作ってみます。

わたくし、車でドライブするのが大好きです🚙🚙

----------------------------------------------------------------

class Car(object):
  def __init__(selfmodel='Yaris'color='black'):
    self.model = model
    self.color = color

  def run(self):
    print(self.model, 'run')
 
class GoodCar(Car):
  pass

----------------------------------------------------------------

CarクラスをGoodCarクラスへ継承しています。

GoodCarクラスをmy_carとしてインスタンス化した後、

クラス変数を以下のように読み込んでみると、

----------------------------------------------------------------

my_car = GoodCar()
 
my_car.model
>>>'Yaris'
my_car.color
>>>'black'
my_car.run()
>>>Yaris run

----------------------------------------------------------------

こうなります。

my_carが走ってくれました!黒いYarisが走ってくれました🚙

ここまでが継承の簡単な流れかなと思います。

 

super().__init__()の登場!

ここでGoodCarをちょっと置いといて、

Carクラスを継承する形でFutureCarクラスを作ってみます。

こんな🚙があるといいなー(^^)/

----------------------------------------------------------------

class FutureCar(Car):
  def __init__(selfmodelcolorauto_run='False'):
    super().__init__(model, color)
    self.auto_run = auto_run

----------------------------------------------------------------

ここでsuper().__init__()の登場。

とりあえず勉強したことを参考に書いてみます。 

そしてFutureCarクラスをインスタンス化。

憧れのマイカー🚙

白いMIRAI、自動運転機能を選べるようにしました。

そして先ほどと同様、クラス変数を出力してみると

----------------------------------------------------------------

my_car = FutureCar(model='MIRAI', color='white', auto_run=True)
 
my_car.model
>>>'MIRAI'
my_car.color
>>>'white'
my_car.auto_run
>>>True
my_car.run()
>>>MIRAI run

----------------------------------------------------------------

黒いYarisではなくて白いMIRAIが!

ついに希望のマイカーが手元に!!

しかし私、ここで疑問が湧いてきました。

----------------------------------------------------------------

class FutureCar(Car):
  def __init__(selfmodelcolorauto_run='False'):
    super().__init__(model, color)
    self.auto_run = auto_run

----------------------------------------------------------------

これは先ほどのFutureCarクラスです。

__init__の引数としてmodel, color, auto_runを記述しています。

さらにsuper().__init__の引数にもmodel, colorを記述しています。

これは何で🤔継承すれば勝手に親クラスの__init__読み込むんだから

別に書かなくてもいいんじゃないの?よくわからん!

ということでわからんことは試してみることにしました。

 

super().__init__()を記述しないとどうなるのか?

FutureCarクラスをまずこうしてやりました!

----------------------------------------------------------------

class FutureCar(Car):
  def __init__(selfmodelcolorauto_run='False'):
    self.auto_run = auto_run

----------------------------------------------------------------

これでmy_carをインスタンス化します。

ちゃんとオーダー(白いMIRAIで自動運転付き)入れました!

----------------------------------------------------------------

my_car = FutureCar(model='MIRAI', color='white', auto_run=True)
 
my_car.model
>>>Attributeエラー
my_car.color
>>>Attributeエラー
my_car.auto_run
>>>True
my_car.run()
>>>Attributeエラー

----------------------------------------------------------------

インスタンス化はするものの、Attributeエラーが。

auto_runだけはうまく行きますが、走りませんorz

子クラスの__init__が親クラスの__init__を上書きしてしまって、

model, colorが無かったことにされるようです。

run()はmodelが引数として必要なのに

無かったことにされているので、エラーが出たってことかな🤔

 

super().__init__()の引数を記述しないとどうなるのか?

次にこんなものを作ってみました。

----------------------------------------------------------------

class FutureCar(Car):
  def __init__(selfmodelcolorauto_run='False'):
    super().__init__()
    self.auto_run = auto_run

----------------------------------------------------------------

super().__init__()の引数を空っぽにしてやりました。

これでmy_carをインスタンス化します。

ちゃんとオーダー(白いMIRAIで自動運転付き)入れました!(2回目)

----------------------------------------------------------------

my_car = FutureCar(model='MIRAI', color='white', auto_run=True)
 
my_car.model
>>>'Yaris'
my_car.color
>>>'black'
my_car.auto_run
>>>True
my_car.run()
>>>Yaris run

----------------------------------------------------------------

届いたのはまさかの黒いYaris。でも自動運転つき。

ちょっとーどういうことー!?

オーダー通ってないよー!?

こういうケースの場合、どうやら親クラスの__init__は

読み込んでくれるものの、

FutureCarクラスで指定した引数は

親クラスの__init__に渡してくれないみたいです。

オーダー伝達不具合が起きました😢😢

 

こんな感じで、

継承後に何か変更したい引数がある時は

super().__init__()にちゃんと引数を渡してあげないと

思わぬもの(黒いYaris)が来るので注意ですね!

実験してみて少しすっきりした気がします。