2013-05-23 10 views
6

Ich habe versucht, etwas darüber zu googeln. Warum arbeiten Nicht-Datendeskriptoren mit alten Klassen?Python Deskriptoren mit alten Klassen

Dokumente sagen, dass sie nicht sollten:
"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 

Danke.

+0

Weil "Descriptor" eine neue Stilklasse ist. – martineau

Antwort

4

Sie haben Recht, die Dokumentation in Frage zu stellen. Ich habe versucht, durch CPython sources zu suchen, um eine Erklärung zu finden, aber seien Sie gewarnt: Ich bin kein Experte.

Von meinem Verständnis, Attributsuche und Beschreiber __get__ Aufruf erfolgt in instance_getattr2 (gewählte Auszüge):

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)); 
    } 
} 

Also entweder ich bin etwas fehlt, oder nichts in der Implementierung erfordert einen neuen Stil Objekt (das widerspricht die Dokumentation).

Ich habe versucht, Python neu zu kompilieren, um den Deskriptoraufruf auf neue Stilklassenobjekte zu beschränken, aber es brachte tatsächlich eine gigantische Unordnung mit sich. Ich habe dabei gelernt, dass Klassenmethoden selbst als Deskriptoren implementiert sind: Dies ist der Mechanismus, der abhängig von der Verwendung gebundene oder ungebundene Methodenobjekte zurückgibt. Zum Beispiel:

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

Als Ergebnis es scheint, dass verhindern würde auch, zumindest mit CPython Umsetzung fordert sie auf, Verfahren für Attribute im alten Stil Objekten oder Klassen Descriptor Aufruf zu verhindern.

Noch einmal, ich bin kein Experte und das ist das erste Mal, dass ich in Python-Implementierung eintauchen, also könnte ich sehr falsch liegen. Ich habe an issue eingereicht, um dies zu klären.

+0

Danke für die Untersuchung, es ist wirklich hilfreich. – alexvassel

+0

Ich bearbeitete meine Antwort nach einer Debugging-Sitzung in CPython: Ich hatte die falschen Funktionen beteiligt, aber das Ergebnis bleibt gleich. – icecrime

+0

Toller Job, nochmals vielen Dank) – alexvassel

Verwandte Themen