「mro()」は何をしますか?


回答:


211

従う...:

>>> class A(object): pass
... 
>>> A.__mro__
(<class '__main__.A'>, <type 'object'>)
>>> class B(A): pass
... 
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
>>> class C(A): pass
... 
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
>>> 

単一の継承がある限り__mro__、クラス、そのベース、そのベースのベースなどのタプルobjectのみになります(もちろん、新しいスタイルのクラスでのみ機能します)。

今、多重継承で...:

>>> class D(B, C): pass
... 
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)

...また__mro__、クラスが重複せず、祖先の後にクラスがないという保証も得られます。最初に同じレベルの多重継承(この例ではBとCなど)に入るクラスは、__mro__左から右へ。

メソッドだけでなく、クラスのインスタンスで取得するすべての属性は、概念的にに沿って検索される__mro__ため、祖先の中で複数のクラスがその名前を定義している場合、これにより、属性がどこにあるかがわかります。__mro__その名前を定義しています。


9
こんにちは、alex、D .__ mro__とD.mro()の間に違いはありますか?
zjm1126 2010年

26
mroメタクラスでカスタマイズでき、クラスの初期化時に一度呼び出され、結果は次の場所に保存され__mro__ます。docs.python.org/library/…を参照してください。
Alex Martelli、2010年

23
属性解決順序ではなくメソッド解決順序と呼ばれるのはなぜですか?
Bentley4 2013年

1
@Alexマルテッリは前記の内容と同じように python-history.blogspot.com/2010/06/...MRO新しいクラスが場合にのみ、Pythonの2.2 MROとPython 2.3 MRO(C3)として、使用されたときに属性が追加されなければなりません使用されています。
アンディ2014

82

mro()メソッド解決順序の略です。これは、クラスが派生した型のリストを、メソッドが検索された順序で返します。

mro()または__mro__は、新しいスタイルクラスでのみ機能します。Python 3では、問題なく動作します。しかしpython 2では、これらのクラスはから継承する必要がありobjectます。


10

これはおそらく解決の順序を示します。

class A(object):
    def dothis(self):
        print('I am from A class')

class B(A):
    pass

class C(object):
    def dothis(self):
        print('I am from C class')

class D(B, C):
    pass

d_instance= D()
d_instance.dothis()
print(D.mro())

そして応答は

I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]

ルールは深さ優先であり、この場合、D、B、A、Cを意味します。

Pythonは通常、継承クラスを検索するときに深さ優先順を使用しますが、2つのクラスが同じクラスから継承する場合、Pythonはそのクラスの最初の言及をmroから削除します。


1
ご覧のとおり、順序はD、B、A、Cです
ストライカー

1
「Pythonはmroからそのクラスの最初の言及を削除する」とはどういう意味ですか?
Ruthvik Vaila 2017

2
@RuthvikVaila:その部分はあまりよく言われていないと思います。Pythonの歴史に関するこのブログの投稿で、Guido van Rossumは(Python 2.2で導入されたMROスキームについて)「この検索で​​クラスが重複した場合、最後の出現を除くすべてがMROリストから削除される」(強調鉱山) )。これは、クラスの最初の「メンション」だけを削除できることを意味します。
martineau 2017

1

解決の順序は、ダイヤモンドの継承では異なります。

class A(object):
    def dothis(self):
        print('I am from A class')


class B1(A):
    def dothis(self):
        print('I am from B1 class')
    # pass


class B2(object):
    def dothis(self):
        print('I am from B2 class')
    # pass


class B3(A):
    def dothis(self):
        print('I am from B3 class')


# Diamond inheritance
class D1(B1, B3):
    pass


class D2(B1, B2):
    pass


d1_instance = D1()
d1_instance.dothis()
# I am from B1 class
print(D1.__mro__)
# (<class '__main__.D1'>, <class '__main__.B1'>, <class '__main__.B3'>, <class '__main__.A'>, <class 'object'>)


d2_instance = D2()
d2_instance.dothis()
# I am from B1 class
print(D2.__mro__)
# (<class '__main__.D2'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)

しかし、なぜ解像度が異なるのですか?
ヴァディム

多重継承のシナリオでは、指定された属性が現在のクラスで最初に検索されます。見つからない場合、検索は同じクラスを2回検索することなく、深さ優先、左右の方法で親クラスに続きます。
ギリッシュグプタ

申し訳ありませんが、なぜ最初の場合に行くのかclass B3、2番目の場合はclass A後で行くのか理解できませんclass B1
Vadim
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.