2015-08-13 15 views
9

In Python 3, object è un'istanza di type e type è anche un'istanza di object!Python 3: come può l'oggetto essere istanza di tipo?

Com'è possibile che ogni classe sia derivata dall'altra?

Eventuali dettagli di implementazione?

ho controllato questo using isinstance(sub, base), che, secondo la documentazione Python, controlla se sottoclasse è derivata dalla classe base:

isinstance(object, type) 
Out[1]: True 

isinstance(type, object) 
Out[2]: True 

risposta

16

Questo è uno dei casi limite in Python:

  • Tutto in Python è un oggetto, quindi dal momento che object è il tipo di base di tutto, type (essendo qualcosa in Python) è un'istanza di object.
  • Poiché object è la base tipo di tutto, object è anche un tipo, che rende object un'istanza di type.

Si noti che questo rapporto è nulla è possibile replicare con i propri cose in Python. È una singola eccezione incorporata nella lingua.


Sul lato attuazione, i due nomi sono rappresentati da PyBaseObject_Type (per object) e PyType_Type (per type).

Quando si utilizza isinstance, il tipo di check-in l'ultimo passo, dopo tutto il resto ha fallito-è fatto da type_is_subtype_base_chain:

type_is_subtype_base_chain(PyTypeObject *a, PyTypeObject *b) 
{ 
    do { 
     if (a == b) 
      return 1; 
     a = a->tp_base; 
    } while (a != NULL); 

    return (b == &PyBaseObject_Type); 
} 

Ciò mantiene sostanzialmente risalendo il tipo gerarchia dei a e controlla la tipo risultante contro b. Se non riesce a trovarne uno, l'ultima risorsa è verificare se b è in realtà object nel qual caso la funzione restituisce true: poiché tutto è un oggetto. Quindi la parte "tutto è un'istanza di object" è effettivamente codificata nel controllo dell'istanza.

E per quanto riguarda il motivo per cui object è un type, questo è in realtà ancora più semplice perché è semplicemente definito in quel modo nel declaration of PyBaseObject_Type:

PyTypeObject PyBaseObject_Type = { 
    PyVarObject_HEAD_INIT(&PyType_Type, 0) 
    "object",         /* tp_name */ 
    sizeof(PyObject),       /* tp_basicsize */ 
    … 

Il PyVarObject_HEAD_INIT imposta essenzialmente la roba informazioni sul tipo di base, tra cui il tipo di base, che è PyType_Type.

realtà ci sono altri due conseguenze di questa relazione:

  • Poiché tutto è un oggetto, object è anche un'istanza di object: isinstance(object, object)
  • Da PyType_Type è implementata anche con la stessa PyVarObject_HEAD_INIT, type è anche un tipo: isinstance(type, type).
+0

Sono sicuro che è possibile emulare questo comportamento con sottoclassi virtuali. – Dunes

Problemi correlati