Python superの理解
3048 ワード
原文住所:https://laike9m.com/blog/li-jie-python-super,70/
Python superの理解
今日知乎で1つの问题に答えて、意外にも1つの賛都がなくて、不思议で、结局これは私のとてもまじめに答えた问题の1つです.それなら貼っておいたほうがいいです.一部の内容は後で補充します.
もとの問題
Pythonで直接親クラス名で親メソッドを呼び出すことができる以上、super関数はなぜ存在しますか?例えばclass Child(Parent):def_init(self): Parent.__Init(self)この方式はsuper(Child,self)と同じである.Init()の違いはありますか?
あなたの質問に答えると、答えはいいですが、違いはありません.しかし、この問題の答えは私にはよくないと思います.
スーパーといえば親を思い浮かべるな!superはMROの次のクラスを指します!スーパーといえば親を思い浮かべるな!superはMROの次のクラスを指します!スーパーといえば親を思い浮かべるな!superはMROの次のクラスを指します!
スーパーといえば、父は初心者が犯しやすい間違いであり、私が犯した間違いでもあると思います.このことを忘れてから、この文章を見に行きます:Python’s super()considered super!これはRaymond Hettingerが書いた文章であり、世界で公認されている
長い議論を見たくないなら、この答えを見に行きます.
2つのパラメータclsとinstはそれぞれ2つのことをした:1.instはMROを生成するlist 2を担当する.現在のMROのindexをclsで位置決めし、mro[index+1]を返すことがsuperの本質であることを覚えておいてください.MROはクラス継承の順序を表すMethod Resolution Orderのフルネームです.あとで詳しく話します.
例を挙げる
しゅつりょく
まず,
次に、MRO内のindexをBにより位置決めし、次を見つける.明らかにBの次はCです.そこで、Cの
ちなみに、なぜBの
実はこのすべての論理はまだはっきりしていて、肝心なのは
では、MROのクラスの順番はいったいどのように並んでいるのでしょうか.Python’s super() considered super!MROでは、ベースクラスは派生クラスの後ろに永遠に現れ、複数のベースクラスがあれば、ベースクラスの相対的な順序は変わらない.MROの公式文書については、The Python 2.3 Method Resolution Orderを参照してください.MROの順序に関する理論的な解釈があります.
最後の最後に、皆さんに注意してください.何のsuperだ、MROだ、new-style classを狙っているんだ.new-style classでなければ、親クラスのクラス名を正直に使って関数を呼び出しましょう.
Python superの理解
今日知乎で1つの问题に答えて、意外にも1つの賛都がなくて、不思议で、结局これは私のとてもまじめに答えた问题の1つです.それなら貼っておいたほうがいいです.一部の内容は後で補充します.
もとの問題
Pythonで直接親クラス名で親メソッドを呼び出すことができる以上、super関数はなぜ存在しますか?例えばclass Child(Parent):def_init(self): Parent.__Init(self)この方式はsuper(Child,self)と同じである.Init()の違いはありますか?
あなたの質問に答えると、答えはいいですが、違いはありません.しかし、この問題の答えは私にはよくないと思います.
super
について話すには、まず「super」という名前が私たちに与えた干渉を無視しなければならない.スーパーといえば親を思い浮かべるな!superはMROの次のクラスを指します!スーパーといえば親を思い浮かべるな!superはMROの次のクラスを指します!スーパーといえば親を思い浮かべるな!superはMROの次のクラスを指します!
スーパーといえば、父は初心者が犯しやすい間違いであり、私が犯した間違いでもあると思います.このことを忘れてから、この文章を見に行きます:Python’s super()considered super!これはRaymond Hettingerが書いた文章であり、世界で公認されている
super
に対する説明が最も透徹している文章でもあり、superを議論すると必ずそれに言及します(もちろんPython's Super Considered Harmfulもあります).長い議論を見たくないなら、この答えを見に行きます.
super
はこのことをしています.def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]
2つのパラメータclsとinstはそれぞれ2つのことをした:1.instはMROを生成するlist 2を担当する.現在のMROのindexをclsで位置決めし、mro[index+1]を返すことがsuperの本質であることを覚えておいてください.MROはクラス継承の順序を表すMethod Resolution Orderのフルネームです.あとで詳しく話します.
例を挙げる
class Root(object):
def __init__(self):
print("this is Root")
class B(Root):
def __init__(self):
print("enter B")
# print(self) # this will print <__main__.d object="" at="">
super(B, self).__init__()
print("leave B")
class C(Root):
def __init__(self):
print("enter C")
super(C, self).__init__()
print("leave C")
class D(B, C):
pass
d = D()
print(d.__class__.__mro__)
しゅつりょく
enter B
enter C
this is Root
leave C
leave B
(, , , , )
super
が親と実質的に関連していないことを知った後、enter Bの次の文がthis is Rootではなくenter Cである理由を理解するのは難しくありません(superが「親を呼び出す方法」を表すと考えると、当然次の文がthis Rootであるべきだと思います).フローは、Bの__init__
関数で次のようになります.super(B, self).__init__()
まず,
self.__class__.__mro__
を取得し,ここでselfはBではなくDのinstanceであることに注意した.(, , , , )
次に、MRO内のindexをBにより位置決めし、次を見つける.明らかにBの次はCです.そこで、Cの
__init__
を呼び出し、enter Cを打ち出します.ちなみに、なぜBの
__init__
が呼び出されるのかというと、Dは__init__
を定義していないので、MROで次のクラスを探して、__init__
を定義しているかどうか、つまりBの__init__
を呼び出すのかを確認します.実はこのすべての論理はまだはっきりしていて、肝心なのは
super
がいったい何をしたのかを理解することです.では、MROのクラスの順番はいったいどのように並んでいるのでしょうか.Python’s super() considered super!MROでは、ベースクラスは派生クラスの後ろに永遠に現れ、複数のベースクラスがあれば、ベースクラスの相対的な順序は変わらない.MROの公式文書については、The Python 2.3 Method Resolution Orderを参照してください.MROの順序に関する理論的な解釈があります.
最後の最後に、皆さんに注意してください.何のsuperだ、MROだ、new-style classを狙っているんだ.new-style classでなければ、親クラスのクラス名を正直に使って関数を呼び出しましょう.