Che cosa significa “(mro)” che fare?

In django.utils.functional.py:

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

Non capisco mro(). Che cosa fa e che cosa “mro” significa?

InformationsquelleAutor zjm1126 | 2010-01-06



4 Replies
  1. 195

    Seguire…:

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

    Finchè abbiamo l’ereditarietà singola, __mro__ è solo la tupla: la classe, la sua base di base di base, e così via fino a object (funziona solo per le nuove classi di stile, naturalmente).

    Ora, con più eredità…:

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

    …hai anche la certezza che, in __mro__, nessuna classe è duplicato, e non di classe, che arriva dopo i suoi antenati, salvare classi che prima di entrare allo stesso livello di ereditarietà multipla (come B e C in questo esempio) sono in __mro__ sinistra a destra.

    Ogni attributo di una istanza della classe, non solo i metodi, è concettualmente guardò in alto, lungo il __mro__, quindi, se più di una classe tra gli antenati definisce che il nome, questo ti dice dove l’attributo sarà trovato, nella prima classe in __mro__ che definisce che il nome.

    • ciao,alex,c’è qualche differenza tra la D.__mro__ e D. (mro).
    • mro può essere personalizzata con una metaclass, è convocata una volta all’inizializzazione della classe, e il risultato viene memorizzato in __mro__ — vedi docs.python.org/library/… .
    • Perché si chiama metodo di risoluzione ordine invece di attributo ordine di risoluzione?
    • Proprio come @Alex Martelli ha detto che il contenuto di python-history.blogspot.com/2010/06/…, il manutenzione l’attributo dovrebbe essere aggiungere quando la nuova classe vengono utilizzate solo quando Python 2.2 MRO e Python 2.3 MRO(C3) sono utilizzati.
  2. 80

    mro() si distingue per il Metodo di Risoluzione Ordine. Restituisce un elenco di tipi di classe è derivata da, nell’ordine in cui vengono cercati i metodi.

    (mro) o __mro__ funziona solo sulle nuove classi di stile. In python 3, funzionano senza problemi. Ma in python 2 classi bisogno di ereditare da oggetti.

  3. 9

    Questo potrebbe forse mostrare l’ordine di risoluzione.

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

    e la risposta sarebbe

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

    La regola è prima di profondità, che in questo caso significherebbe D, B, A, C.

    Python utilizza normalmente un prima di profondità ordine durante la ricerca di ereditare le classi, ma quando due classi ereditano dalla stessa classe, Python rimuove la prima menzione di quella classe da mro.

    • Così come si può vedere l’ordine è D, B, A, C
    • Che cosa si intende per “Python rimuove la prima menzione di quella classe da mro.”?
    • Penso che è poco indicato. In questo post sul blog la storia di Python, Guido van Rossum osservazioni (circa il MRO regime introdotto in Python 2.2) “Se ogni classe è stato duplicato in questa ricerca, ma tutte le last avvenimento sarebbe eliminato dal MRO list” (enfasi mia). Questo implica che si può rimuovere più di un solo “parlare” della classe.
  4. 1

    Ordine di risoluzione sarà diverso in diamante eredità.

    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'>)
    • ma perché la risoluzione è diversa ?
    • L’ereditarietà multipla scenario, qualsiasi attributo specificato è cercato prima classe corrente. Se non viene trovato, la ricerca continua in classi padre in profondità, sinistra-destra di moda senza ricerca stessa classe due volte.
    • scusa ma non capisco perché nel primo caso si tratta di andare a class B3 ma nel secondo caso si tratta di andare a class A dopo class B1

Lascia un commento