2009-06-16 13 views
7

W klasie B poniżej chciałem wywołać funkcję __set__ w klasie A za każdym razem, gdy przypisano wartość do B().a. Zamiast tego ustawienie wartości na B().a powoduje zastąpienie wartości B().a. Przypisanie klasy C do C().a działa poprawnie, ale chciałem mieć oddzielną instancję klasy A dla każdej klasy użytkownika, tj. Nie chcę zmieniać "a" w jednym wystąpieniu C(), aby zmienić "a" we wszystkich innych instancjach. Napisałem kilka testów, aby pomóc zilustrować problem. Czy możesz mi pomóc zdefiniować klasę, która przejdzie zarówno test1, jak i test2?Dlaczego deklarowanie klasy deskryptorów w funkcji __init__ powoduje przerwanie działania deskryptora?

class A(object): 
    def __set__(self, instance, value): 
     print "__set__ called: ", value 

class B(object): 
    def __init__(self): 
     self.a = A() 

class C(object): 
    a = A() 

def test1(class_in): 
    o = class_in() 
    o.a = "test" 
    if isinstance(o.a, A): 
     print "pass" 
    else: 
     print "fail" 

def test2(class_in): 
    o1, o2 = class_in(), class_in() 
    if o1.a is o2.a: 
     print "fail" 
    else: 
     print "pass" 

Odpowiedz

4

odpowiednio do documentation:

następujące metody zastosowanie tylko gdy przykład z klasy zawierającej metody (tak zwane deskryptor klasę) pojawia się w klasie słownik innej klasy w nowym stylu, znanej jako klasa właściciela. W poniższych przykładach "atrybut" odnosi się do atrybutu , którego nazwa jest kluczem do właściwości w klasie właściciela "__dict__. Deskryptory mogą być implementowane jako same klasy w nowym stylu.

Dzięki temu nie można mieć deskryptorów w instancjach.

Jednakże, ponieważ deskryptor otrzymuje odwołanie do instancji używanej do uzyskania dostępu do niego, po prostu użyj go jako klucza do przechowywania stanu i możesz mieć inne zachowanie w zależności od instancji.

+0

OK, mogę z tym żyć – user83753

+0

Po krótkiej myśli, może nie mogę z tym żyć. W mojej aplikacji chcę umieścić funkcje składowe w A, które również zależą od stanu klasy właściciela. Na przykład: Właściciel (informacja o stanie) Owner.a = dane Owner.a.foo() W jaki sposób foo otrzymuje informacje o stanie od właściciela? – user83753

+0

@unknown (google): oh, ponieważ przechowujesz dane na samej instancji. Możesz więc pobrać go z metod. – nosklo

0

Oto klasa, która może przejść oryginalne testy, ale nie należy jej używać w większości sytuacji. nie powiedzie się sam test isinstance!

class E(object): 
    def __new__(cls, state): 
     class E(object): 
      a = A(state) 
      def __init__(self, state): 
       self.state = state 
     return E(state) 

#>>> isinstance(E(1), E) 
#False 
+0

to funkcja fabryczna klasy, przebrana za klasę – nosklo

+0

Tak, jest i jest z tego dumna. – user83753

0

Zostałem ukąszony przez podobny problem, ponieważ chciałem klasy obiektów o atrybutach regulowanych przez deskryptor. Kiedy to zrobiłem, zauważyłem, że atrybuty zostały nadpisane we wszystkich obiektach, tak że nie były indywidualne.

podniosłem pytanie SO i odpowiedź wypadkowa jest tutaj: class attribute changing value for no reason

Dobrym Link dokument omawiania deskryptorów jest tutaj: http://martyalchin.com/2007/nov/24/python-descriptors-part-2-of-2/

Przykładem deskryptor od wspomnianego linku poniżej:

class Numberise(object): 
    def __init__(self, name): 
     self.name = name 

    def __get__(self, instance, owner): 
     if self.name not in instance.__dict__: 
      raise (AttributeError, self.name) 
     return '%o'%(instance.__dict__[self.name]) 

    def __set__(self, instance, value): 
     print ('setting value to: %d'%value) 
     instance.__dict__[self.name] = value 
Powiązane problemy