2013-05-23 10 views
6

Ho provato a google qualcosa su di esso. Perché i descrittori di dati non funzionano con classi di vecchio stile?Descrittori Python con classi vecchio stile

I documenti dicono che non dovrebbero:
"Note that descriptors are only invoked for new style objects or classes (ones that subclass object() or type()).".

class Descriptor(object): 
    def __init__(self): 
     self.x = 1 

    def __get__(self, obj, cls=None): 
     return self.x 


class A: 
    x = Descriptor() 

a = A() 
a.x 

>>> 1 

Grazie.

+0

Perché 'Descriptor' è una classe di nuovo stile. – martineau

risposta

4

Avete ragione a mettere in discussione la documentazione. Ho provato a cercare attraverso CPython sources per trovare una spiegazione, ma attenzione: non sono esperto.

Dalla mia comprensione, attributo di ricerca e descrittore __get__ invocazione si verifica in instance_getattr2 (estratti scelti):

v = class_lookup(inst->in_class, name, &klass); 
if (v != NULL) { 
    f = TP_DESCR_GET(v->ob_type); 
    if (f != NULL) { 
     PyObject *w = f(v, (PyObject *)inst, (PyObject *)(inst->in_class)); 
    } 
} 

Quindi, o mi manca qualcosa, o niente per l'attuazione richiede un nuovo oggetto-style (che contraddice la documentazione).

Per la cronaca, ho provato a ricompilare Python per limitare il richiamo del descrittore a nuovi oggetti di classi di stile, ma in realtà ha provocato un pasticcio gigantesco. Ho appreso nel processo che i metodi di classe stessi sono implementati come descrittori: questo è il meccanismo utilizzato per restituire oggetti metodo vincolati o non associati a seconda dell'utilizzo. Per esempio:

>>> class A: 
...  def foo(): 
...   pass 
... 
>>> A.foo.__get__(None, A) 
<unbound method A.foo> 
>>> A.foo.__get__(A(), A) 
<bound method A.foo of <__main__.A instance at 0x000000000229CC48>> 

Di conseguenza, sembra che la prevenzione descrittore invocazione per gli attributi degli oggetti in stile antico o classi sarebbe anche impedire le chiamate di metodo su di loro, almeno con l'attuazione CPython.

Ancora una volta, non sono esperto e questa è la prima volta che mi tuffo nell'implementazione di Python, quindi potrei sbagliarmi. Ho archiviato an issue per cercare di chiarire questo.

+0

Grazie per l'indagine, è davvero utile. – alexvassel

+0

Ho modificato la mia risposta dopo una sessione di debug in CPython: avevo le funzioni sbagliate coinvolte, ma il risultato rimane lo stesso. – icecrime

+0

Ottimo lavoro, grazie ancora) – alexvassel

Problemi correlati