[解決済み] クラスメソッドでsuperを使用する
質問
Pythonのsuper()関数を勉強しています。
この例(2.6)を見るまで、私はそれを把握していると思っていましたが、私自身が行き詰っていることに気づきました。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 9, in do_something
do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>
例の直前のこの行を読んで、予想と違っていました。
クラスメソッドを使用している場合、superを呼び出すためのインスタンスを持っていないのです。幸いなことに、superは第2引数に型を与えても動作します。---以下のように、型は直接superに渡すことができます。
これはまさにPythonがdo_something()はBのインスタンスで呼び出されるべきであると言って、不可能だと教えてくれているものです。
どのように解決するのですか?
テキストは、詳細よりもむしろアイデアの味を楽しむために読まなければならないことがあります。これはそのような場合の一つです。
では
リンク先ページ
で、例2.5、2.6、2.7はすべて1つのメソッドを使用する必要があります。
do_your_stuff
. (つまり
do_something
は次のように変更されます。
do_your_stuff
.)
さらに
Ned Deily が指摘したように
,
A.do_your_stuff
はクラスメソッドでなければなりません。
class A(object):
@classmethod
def do_your_stuff(cls):
print 'This is A'
class B(A):
@classmethod
def do_your_stuff(cls):
super(B, cls).do_your_stuff()
B.do_your_stuff()
super(B, cls).do_your_stuff
は
バウンド
メソッド(
脚注2
). このため
cls
の第二引数として渡された
super()
であれば、それは
cls
であり、返されたメソッドに束縛されます。言い換えれば
cls
はメソッドの最初の引数として渡されます。
do_your_stuff()
の第一引数として渡されます。
再掲すると
super(B, cls).do_your_stuff()
原因
A
's
do_your_stuff
メソッドを
で呼び出される
cls
が第一引数として渡されます。それが動作するためには
A
's
do_your_stuff
はクラスメソッドでなければなりません。リンク先のページではそのことに触れていない。
が、これは決定的にそうです。
PS.
do_something = classmethod(do_something)
は、classmethod を作る古い方法です。
新しい(er)方法は、@classmethodデコレータを使うことです。
注意点として
super(B, cls)
で置き換えることはできません。
super(cls, cls)
. そうすると、無限ループになる可能性があります。例えば
class A(object):
@classmethod
def do_your_stuff(cls):
print('This is A')
class B(A):
@classmethod
def do_your_stuff(cls):
print('This is B')
# super(B, cls).do_your_stuff() # CORRECT
super(cls, cls).do_your_stuff() # WRONG
class C(B):
@classmethod
def do_your_stuff(cls):
print('This is C')
# super(C, cls).do_your_stuff() # CORRECT
super(cls, cls).do_your_stuff() # WRONG
C.do_your_stuff()
は
RuntimeError: maximum recursion depth exceeded while calling a Python object
.
もし
cls
は
C
であれば
super(cls, cls)
は検索する
C.mro()
の後にあるクラスを検索します。
C
.
In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]
そのクラスは
B
であるとき
cls
は
C
,
super(cls, cls).do_your_stuff()
常に
コール
B.do_your_stuff
. 以来
super(cls, cls).do_your_stuff()
の内部で呼び出されます。
B.do_your_stuff
の中で呼び出されると、最終的に
B.do_your_stuff
を無限ループで呼び出すことになります。
Python3では
の0-引数形式を
super
が追加されたので
super(B, cls)
で置き換えることができます。
super()
と置き換えることができ、Python3は文脈から
super()
の定義にある
class B
と等価であるべきです。
super(B, cls)
.
しかし、どのような状況でも
super(cls, cls)
(または同様の理由で
super(type(self), self)
) は決して正しくありません。
関連
-
[解決済み] 関数内でグローバル変数を使用する
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで静的なクラス変数は可能ですか?
-
[解決済み] モジュールの関数名(文字列)を使って、モジュールの関数を呼び出す。
-
[解決済み] Could not find or load main class "とはどういう意味ですか?
-
[解決済み] Pythonのsuper()は多重継承でどう動くのか?
-
[解決済み] print()を使用してクラスのインスタンスを表示するには?
-
[解決済み】forループを使った辞書の反復処理
-
[解決済み】PECS(Producer Extends Consumer Super)って何?)
-
[解決済み] Python 3でバイナリデータを標準出力に書き込むには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 2つの線分が交差しているかどうかを確認するにはどうすればよいですか?
-
[解決済み] PILからopenCVフォーマットへの変換
-
[解決済み] Django のテストデータベースをメモリ上だけで動作させるには?
-
[解決済み] Pythonの要素別タプル演算(sumなど
-
[解決済み] 文字列から先頭と末尾のスペースを削除するには?
-
[解決済み] ファブリック経由でデプロイユーザとしてvirtualenvを有効化する
-
[解決済み] 値で列挙名を取得する [重複]。
-
[解決済み] PyMongoで.sortを使用する
-
[解決済み] Jupyter (IPython)ノートブックのセッションをpickleして保存する方法
-
[解決済み] Pythonで基底クラスのクラスメソッドを呼び出す