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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Kivy

Kivyは、Pythonを用いたNUI開発のためのオープンソースフレームワーク。マルチタッチなど多くの入力に対応したNUIアプリなどを開発することができます。多くの環境で動作するクロスプラットフォームです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

2475閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

Kivy

Kivyは、Pythonを用いたNUI開発のためのオープンソースフレームワーク。マルチタッチなど多くの入力に対応したNUIアプリなどを開発することができます。多くの環境で動作するクロスプラットフォームです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/05/27 07:27

編集2019/05/27 09:55

ご質問内容

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'

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

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

python

1from kivy.app import App 2from kivy.uix.boxlayout import BoxLayout 3from kivy.uix.button import Button 4from kivy.uix.label import Label 5 6class MyRoot(BoxLayout): 7 def __init__(self, **kwargs): 8 super(MyRoot, self).__init__(**kwargs) 9 lbl = Label(text='normal') 10 self.add_widget(lbl) 11 12class Renshu(App): 13 def build(self): 14 return MyRoot() 15 16Renshu().run()

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

python

1from kivy.app import App 2from kivy.uix.boxlayout import BoxLayout 3from kivy.uix.button import Button 4from kivy.uix.label import Label 5 6class MyRoot(BoxLayout): 7 def __init__(self, **kwargs): 8     layout = BoxLayout() #変更箇所 9 lbl = Label(text='normal') 10 layout.add_widget(lbl) 11 return layout #追加箇所 12 13class Renshu(App): 14 def build(self): 15 return MyRoot() 16 17Renshu().run()

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

super(MyRoot, self).__init__(**kwargs) ```を使わなかった場合 ```python 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()

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

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 07:38

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/05/27 09:51

教えていただきありがとうございます。 ・親クラスの __init__ は、クラス継承しただけでは自動で呼び出されない →そのため、__init__ メソッドを呼び出す必要あり →つまり、子クラス内にsuper~ のコード文が必要 ということでしょうか? また、補足に記載したコードを試してみると上手くいきました。 「__init__はNoneを返すべきであって、BoxLayout型を返してはいけない」というのは、MyRootクラス(BoxLayout継承クラス)のコードに関するエラーだったということでしょうか? 基礎的な質問、勉強不足ですいません。 教えて下さい。
hayataka2049

2019/05/27 11:34 編集

>・親クラスの __init__ は、クラス継承しただけでは自動で呼び出されない >→そのため、__init__ メソッドを呼び出す必要あり >→つまり、子クラス内にsuper~ のコード文が必要 >ということでしょうか? 子クラスに__init__を定義しなければ、親の__init__がそのまま動きます。 また、子に__init__を定義するけど、親の__init__の処理を流用してうまくやりたいという意思はまったくないという場合、super().__init__せずに書くことも可能です。 子で__init__を上書きして、だけど親の__init__で行われている処理は活用したいというときにこの書き方を使います。
hayataka2049

2019/05/27 11:17

>また、補足に記載したコードを試してみると上手くいきました。 これだと実質的にBoxLayout()クラスをインスタンス化して返しているだけです。クラス継承を使わないで書いてもいっこうにかまいません。 >「__init__はNoneを返すべきであって、BoxLayout型を返してはいけない」というのは、MyRootクラス(BoxLayout継承クラス)のコードに関するエラーだったということでしょうか? そうです。
退会済みユーザー

退会済みユーザー

2019/05/27 11:28

丁寧に分かりやすく教えていただきありがとうございます。かなり理解が進みました。 すごくもやもやしていたのですが、一気に解消されました。 ありがとうございました。
hayataka2049

2019/05/27 12:37

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

退会済みユーザー

2019/05/28 03:56

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問