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

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

新規登録して質問してみよう
ただいま回答率
85.30%
Python 3.x

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

Q&A

解決済

2回答

1050閲覧

pythonで、親クラスのコンストラクタの引数にselfがあるとエラーになる原因

biotoap2

総合スコア3

Python 3.x

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

1グッド

0クリップ

投稿2022/10/17 02:50

pythonのクラス継承について。

class child(parent):
def init(self):
super().init(●●●)

●●●の部分の最初に「self」が必要だと思っていたのですが、selfを書くと以下のエラーになります。

原文
UFuncTypeError: Cannot cast ufunc 'add' output from dtype('O') to dtype('float64') with casting rule 'same_kind'

deepLでの翻訳
UFuncTypeError: ufunc 'add' の出力を dtype('O') から dtype('float64') にキャストできません キャストルール 'same_kind' が適用されます

一方で、selfを書かなければ、思った通りの挙動になりました。
また、
parent.init(self, ~)
という表記にしても、思った通りの挙動になりました。つまり、super()と書くのではなく、親クラス名を直接書くわけです。

これはどういう現象なのでしょうか?

ちなみに、他でも同じようなことをしているのですが、そっちでは
super().init(self, ~)
という書き方でいけてます。この謎を教えてください。

melianを押しています

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

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

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

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

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

int32_t

2022/10/17 02:53

親クラスの init() はどのように定義されていますか。
biotoap2

2022/10/17 02:56

返信ありがとうございます! このようになっています! 親の上に、さらに親が5代ほど続いているようなのですが・・・ def __init__( self, point: list | np.ndarray = ORIGIN, radius: float = DEFAULT_DOT_RADIUS, stroke_width: float = 0, fill_opacity: float = 1.0, color: Color | str = WHITE, **kwargs, ): super().__init__( arc_center=point, radius=radius, stroke_width=stroke_width, fill_opacity=fill_opacity, color=color, **kwargs, )
guest

回答2

0

https://docs.python.org/ja/3/library/functions.html#super

メソッドの呼び出しを type の親または兄弟クラスに委譲するプロキシオブジェクトを返します。これはクラスの中でオーバーライドされた継承メソッドにアクセスするのに便利です。

両方の用途において、典型的なスーパークラスの呼び出しは次のようになります:

python

1class C(B): 2 def method(self, arg): 3 super().method(arg) # This does the same thing as: 4 # super(C, self).method(arg)

とある通りです。
super().__init__(self, ~)はおかしいです。


ちなみに、他でも同じようなことをしているのですが、そっちでは
super().__init__(self, ~)
という書き方でいけてます。この謎を教えてください。

がおかしくて、実際はうまくいってない可能性の方が高そうです。

python

1class A: 2 def __init__(self, must_be_set, optional=0): 3 self.must_be_set = must_be_set 4 self.optional = optional 5 6 7class B(A): 8 def __init__(self, must_be_set): 9 super().__init__(self, must_be_set) 10 11b = B(1) 12print(b.must_be_set) # => <__main__.B object at 0x102ea40a0> 13print(b.optional) # => 1 14# B(1)の1はmust_be_setのつもりなのにそうなってない

こんな感じで意図通りの動きになってないんじゃないかと想像します。


parent.__init__(self, ~)
という表記にしても、思った通りの挙動になりました。

parent.method(self, ~)の代わりにsuper().method(〜)と使えば親や兄弟のmethodに処理を委譲できるようなオブジェクト」を得ることがsuperの役割なので、それは当然そうです。

superがよしなにやってくれていることを自分で書きました、という話になっています。


superのポイントは

親または兄弟クラスに委譲するプロキシオブジェクトを返します

"または兄弟クラス" の部分で、菱形継承などの(まれな)ケースで親クラスではなく兄弟クラスが移譲先になる時があることです。
移譲先が親クラスであるべきか兄弟クラスであるべきかを判断するコードを自前でやるのは苦痛なので、super()を呼んでおけばよろしくやってくれるというメリットがあります。

補足
高度でレアなケースなので初級者がこのメリットを理解する必要はあまり感じません。「そうなんだ」程度でいいと思います。

第一に、単継承のクラス階層構造で super は名前を明示することなく親クラスを参照するのに使え、それゆえコードをメンテナンスしやすくなります。

の方がメリットは大きいかと思います。(すでに回答が付いている通り)

投稿2022/10/17 04:03

編集2022/10/17 04:20
quickquip

総合スコア11310

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

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

biotoap2

2022/10/17 04:17

詳しくありがとうございます! 正直、100%の理解はできないのですが、少なくともこの件に関して正誤の判別はできるようになったと思います!
guest

0

ベストアンサー

super().__init__(〜) の場合、self を引数として渡す必要はありません。一般のメソッドで foo.method(foo, 〜) と書かずに foo.method(〜) となるのと同じです。

親クラスが Parent であれば、super().__init__(〜) と書いても Parent.__init__(self, 〜) と書いても同じです。親クラスの名前を正確に書かなくていいぶん、super()のほうがバグが混入しにくいでしょう。

ちなみに、他でも同じようなことをしているのですが、そっちでは
super().init(self, ~)
という書き方でいけてます。この謎を教えてください。

そっちのほうが特殊な気がします。動いているように見えて実は正しく動いてないだけかもしれません。

投稿2022/10/17 03:21

編集2022/10/17 03:23
int32_t

総合スコア21929

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

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

biotoap2

2022/10/17 03:28

返信ありがとうございます! 確認なのですが、 >super().__init__(〜) の場合、self を引数として渡す必要はありません。 「渡す必要がない」のか、「渡してはいけない」のか、どっちでしょうか? 文字通りであれば前者ですが、以下の部分からは後者のようにも解釈できそうで・・・。どちらにしても、自分でもちょっと挙動をテストしてみます。 >そっちのほうが特殊な気がします。動いているように見えて実は正しく動いてないだけかもしれません。
int32_t

2022/10/17 03:34

特殊な場合を除き、渡すと動かないので渡してはダメです。 特殊な場合: __init__() の self 以外の最初の引数が、そのクラスのインスタンスを指定することになっている場合
biotoap2

2022/10/17 03:41

そうなんですね!わかりました! ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問