【问题标题】:What does "mro()" do?“mro()”是做什么的?
【发布时间】:2023-04-10 19:19:01
【问题描述】:

django.utils.functional.py:

for t in type(res).mro():  # <----- this
    if t in self.__dispatch:
        return self.__dispatch[t][funcname](res, *args, **kw)

我不明白mro()。它有什么作用,“mro”是什么意思?

【问题讨论】:

标签: python method-resolution-order


【解决方案1】:

跟随...:

>>> 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__ 的第一个类中。

【讨论】:

  • 嗨,alex,D.__mro__ 和 D.mro() 之间有什么区别吗?
  • mro 可以通过元类自定义,在类初始化时调用一次,结果存储在__mro__ -- 见docs.python.org/library/…
  • 为什么叫方法解析顺序而不是属性解析顺序
  • 就像@Alex Martelli 说的和python-history.blogspot.com/2010/06/… 的内容一样,mro 属性应该在使用新类时添加,仅当 Python 2.2 MRO 和 Python 2.3 使用 MRO(C3)。
【解决方案2】:

mro() 代表方法解析顺序。它返回类派生的类型列表,按照搜索方法的顺序排列。

mro()__mro__ 仅适用于新样式类。在 Python 3 中,它们可以正常工作。然而,在 Python 2 中,这些类需要继承自 object

【讨论】:

    【解决方案3】:

    这可能会显示解决的顺序。

    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 在搜索继承类时通常使用深度优先顺序,但当两个类继承自同一个类时,Python 会从 mro 中删除该类的第一次提及。

    【讨论】:

    • 所以你可以看到顺序是D,B,A,C
    • “Python 从 mro 中删除了该类的第一次提及”是什么意思?
    • @RuthvikVaila:我认为这部分表述得不好。在这个关于 Python 历史的blog post 中,Guido van Rossum 评论(关于 Python 2.2 中引入的 MRO 方案)“如果在此搜索中重复了任何类,则除了 last 之外的所有类都将被删除来自 MRO 列表”(强调我的)。这意味着它可以删除的不仅仅是类的第一个“提及”。
    【解决方案4】:

    菱形继承中的解析顺序会有所不同。

    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'>)
    

    【讨论】:

    • 但是为什么分辨率不同?
    • 在多重继承的场景中,任何指定的属性都会先在当前类中搜索。如果未找到,则以深度优先、左右方式继续搜索父类,而不搜索同一类两次。
    • 对不起,但我不明白为什么在第一种情况下它会转到class B3,但在第二种情况下它会在class B1 之后转到class A
    猜你喜欢
    • 2018-05-28
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 2011-11-01
    相关资源
    最近更新 更多