2013-05-23 30 views
6

Próbowałem coś o tym napisać. Dlaczego deskryptory niebędące danymi działają z klasami starego typu?Deskryptory w języku Python ze staromodnymi klasami

Dokumenty mówią, że nie powinny:
"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 

Dzięki.

+0

Ponieważ "Deskryptor" jest klasą nowego stylu. – martineau

Odpowiedz

4

Masz prawo kwestionować dokumentację. Próbowałem przeglądać CPython sources, aby znaleźć wyjaśnienie, ale ostrzegam: nie jestem ekspertem.

Z mojego zrozumienia, atrybut wyszukiwania i deskryptor __get__ inwokacja występuje w instance_getattr2 (wybranych ekstraktów):

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

Więc albo ja czegoś brakuje, lub nic w realizacji wymaga obiektu w nowym stylu (co jest sprzeczne dokumentacja).

Dla porównania, próbowałem zrekompilować język Python, aby ograniczyć wywoływanie deskryptorów do nowych obiektów klas stylów, ale spowodowało to gigantyczny bałagan. Nauczyłem się, że metody klasowe są implementowane jako deskryptory: jest to mechanizm używany do zwracania powiązanych lub niezwiązanych obiektów metod w zależności od użycia. Na przykład:

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

W rezultacie wydaje się, że zapobieganie deskryptora inwokację do atrybutów obiektów starego typu lub klasy zapobiegają również metodę wzywa je, przynajmniej z realizacją CPython.

Po raz kolejny nie jestem ekspertem i po raz pierwszy nurkuję w implementacji Pythona, więc mogłem się mylić. Zgłosiłem an issue, aby spróbować to wyjaśnić.

+0

Dzięki za dochodzenie, to jest naprawdę pomocne. – alexvassel

+0

Edytowałem swoją odpowiedź po sesji debugowania w CPython: Miałem złe funkcje, ale wynik pozostaje taki sam. – icecrime

+0

Świetna robota, jeszcze raz dziękuję) – alexvassel