[解決済み] Python 3.xのsuper()はなぜ魔法なのか?
質問
Python 3.xでは。
super()
は引数なしで呼び出すことができます。
class A(object):
def x(self):
print("Hey now")
class B(A):
def x(self):
super().x()
>>> B().x()
Hey now
これを実現するために、コンパイル時にいくつかのマジックが行われますが、その結果のひとつが、次のコード(これは
super
を
super_
) は失敗します。
super_ = super
class A(object):
def x(self):
print("No flipping")
class B(A):
def x(self):
super_().x()
>>> B().x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in x
RuntimeError: super(): __class__ cell not found
なぜ
super()
は、コンパイラの支援なしに実行時にスーパークラスを解決できないのでしょうか?この動作やその根本的な理由が、不用心なプログラマに噛み付くような実用的な状況はありますか?
...それから、余談ですが、Pythonで関数やメソッドなどを別の名前にバインドし直すと壊れるという例は他にもあるのでしょうか?
どのように解決するのですか?
新しい魔法
super()
の挙動は、D.R.Y. (Don't Repeat Yourself) の原則に違反しないように追加されたものです。
PEP 3135
. グローバルに参照することで明示的にクラス名を付けなければならないことも、以下のような再バインドの問題を引き起こしがちです。
super()
そのものです。
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
クラス・デコレーターを使う場合も同様で、デコレーターは新しいオブジェクトを返し、そのオブジェクトはクラス名を再束縛します。
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
マジック
super()
__class__
セルは、元のクラスオブジェクトにアクセスできるようにすることで、これらの問題をうまく回避しています。
このPEPはGuidoによってキックオフされました。
当初は
super
キーワードになる
また、セルを使って現在のクラスを検索するというアイデアもあります。
も彼の
. 確かに、キーワードにするアイデアは、その一部である
PEPの最初のドラフト
.
しかし、実際には、その後、グイド自身が
キーワードのアイデアは、「魔法のようすぎる」として、このアイデアから離れました。
その代わりに、現在の実装を提案したのです。彼は
を別の名前にすることが予想されました。
super()
が問題になる可能性があります。
:
私のパッチは中間的な解決策を使用しています。
__class__
という名前の変数を使用する場合は、常に'super'
. したがって、もしあなたが (グローバルに) リネームsuper
をsupper
を使用しsupper
でなくsuper
は動作しません。 を引数として渡すと動作します。__class__
または実際のクラスオブジェクト); もし、無関係の という名前の変数があります。super
の場合、動作はしますが、このメソッドは セル変数に使用されるやや遅い呼び出し経路です。
ということで、結局、グイド自身が
super
キーワードはしっくりこないので、魔法のような
__class__
のセルは、許容できる妥協点でした。
実装のマジック、暗黙の動作がやや意外であることには同意しますが
super()
は、この言語で最も誤用される関数の1つです。誤って適用されたすべての
super(type(self), self)
または
super(self.__class__, self)
そのコードが派生クラスの
無限再帰例外が発生します。
. 少なくとも、簡素化された
super()
の呼び出しは、引数なしで
その
という問題が発生します。
リネームされた
super_
を参照するだけです。
__class__
メソッド内で
も
と入力すれば、再び動作するようになります。のどちらかを参照すると、セルが作成されます。
super
または
__class__
という名前をメソッドに追加します。
>>> super_ = super
>>> class A(object):
... def x(self):
... print("No flipping")
...
>>> class B(A):
... def x(self):
... __class__ # just referencing it is enough
... super_().x()
...
>>> B().x()
No flipping
関連
-
PythonはWordの読み書きの変更操作を実装している
-
[解決済み] [Solved] sklearn error ValueError: 入力に NaN、infinity または dtype('float64') に対して大きすぎる値が含まれている。
-
[解決済み】TypeErrorの修正方法。Unicodeオブジェクトは、ハッシュ化する前にエンコードする必要がある?
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] Pythonで例外を手動で発生(スロー)させる
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
Pythonコンテナのための組み込み汎用関数操作
-
PicgoのイメージベッドツールをPythonで実装する
-
Evidentlyを用いたPythonデータマイニングによる機械学習モデルダッシュボードの作成
-
Python LeNetネットワークの説明とpytorchでの実装
-
[解決済み] _tkinter.TclError: 表示名がなく、$DISPLAY環境変数もない。
-
[解決済み】TypeErrorの修正方法。Unicodeオブジェクトは、ハッシュ化する前にエンコードする必要がある?
-
[解決済み】Python regex AttributeError: 'NoneType' オブジェクトに 'group' 属性がない。
-
[解決済み】ilocが「IndexError: single positional indexer is out-of-bounds」を出す。
-
[解決済み] super().method() と super(self.__class__,self).method() の違いについて [重複]。
-
[解決済み】クラスメソッドの目的は何ですか?