質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

【Kivy】super(親クラス, self).__init__(**kwargs)の役割

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,174

score 8

ご質問内容

kivy初心者です。
画面にnormalという文字を表示させるコードなのですが、以下2通りの方法で試しました。

ここで「該当のソースコード①」のMyRootクラスにて、親クラスの呼び出し

super(MyRoot, self).__init__(**kwargs)


は、何故必要なのでしょうか。

※上記コードの役目を理解したかったため、「該当のソースコード②」で試しました。
エラー(ウィンドウが立ち上がりすぐに消える)が発生しますが、根本的なkivyの仕組みが理解できておらず、いまいち上記コードの役目が理解できません。
エラーコード:

Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "C:xxxxxxxx\kivy\app.py", line 800, in run
     root = self.build()
   File "<stdin>", line 3, in build
 TypeError: __init__() should return None, not 'BoxLayout'

お手数ですが、分かる方がいらっしゃいましたら、教えて下さい。

該当のソースコード①(成功)

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label

class MyRoot(BoxLayout):
    def __init__(self, **kwargs):
        super(MyRoot, self).__init__(**kwargs)
        lbl = Label(text='normal')
        self.add_widget(lbl)

class Renshu(App):
    def build(self):
        return MyRoot()

Renshu().run()

該当のソースコード②(失敗)

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label

class MyRoot(BoxLayout):
    def __init__(self, **kwargs):
     layout = BoxLayout() #変更箇所
        lbl = Label(text='normal')
        layout.add_widget(lbl)
        return layout #追加箇所

class Renshu(App):
    def build(self):
        return MyRoot()

Renshu().run()

補足(新たに試したコード)

super(MyRoot, self).__init__(**kwargs)

を使わなかった場合

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label

class MyRoot(BoxLayout):
    def __init__(self, **kwargs):
        self.layout = BoxLayout()
        self.lbl = Label(text='LLL')
        self.layout.add_widget(self.lbl)

class Renshu(App):
    def build(self):
        L = MyRoot()
        return L.layout

Renshu().run()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

 TypeError: __init__() should return None, not 'BoxLayout'は「__init__Noneを返すべきであって、BoxLayout型を返しちゃ駄目ですよ」という意味です。

__init__はよくコンストラクタと解説されますが、MyRoot()とか書くと直接__init__が呼ばれてその返り値が返る……という単純なものではありません。オブジェクトの実際の生成は__new__が担いますし、全体を統率して最終的なMyRoot()の値を返しているのはまた別の仕組みです(Pythonの中では低レイヤな話なので、私も全貌は知らないしここで書きません)。

なので、直接のエラー原因はreturn layoutを書いたことなのですが、これを消しても当然期待通りには動きません。

super(MyRoot, self).__init__(**kwargs)というのは、機能的にはBoxLayout.__init__(self, **kwargs)と書いているのと同じ、と捉えると多少わかりやすいと思います。意味合いとしては「selfを自身の親クラスのオブジェクトとみなして、そのコンストラクタで初期化する」ということになります。

参考:組み込み関数 — Python 3.7.3 ドキュメント | super

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/27 20:28

    丁寧に分かりやすく教えていただきありがとうございます。かなり理解が進みました。

    すごくもやもやしていたのですが、一気に解消されました。

    ありがとうございました。

    キャンセル

  • 2019/05/27 21:37

    今回だとMyRootクラスは親クラスのBoxLayoutとほとんど同じものにしたい訳ですね。
    lbl = Label(text='normal')
    self.add_widget(lbl)
    の2行だけが変更点で、これは__init__に書く必要があります。
    なので、「まずsuper()を使ってBoxLayoutとして初期化してから、更にMyRoot独自の機能を付け足すための処理を行って、MyRootの__init__を終える」という流れになります。

    キャンセル

  • 2019/05/28 12:56

    コード組立ての流れまで教えていただきありがとうございます。
    構造がイメージしやすく、すごくわかりやすかったです。

    教えて頂いた内容、試してみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る