2009-06-16 12 views
7

In Klasse B unten wollte ich die __set__ Funktion in Klasse A aufgerufen werden, wenn Sie B().a einen Wert zuweisen. Stattdessen wird durch Setzen eines Werts auf B().a der Wert B().a überschrieben. Klasse C, die C().a zuweist, funktioniert ordnungsgemäß, aber ich wollte eine separate Instanz von A für jede Benutzerklasse haben, d. H. Ich möchte nicht 'a' in einer Instanz von C() ändern, um 'a' in allen anderen Instanzen zu ändern. Ich habe ein paar Tests geschrieben, um das Problem zu veranschaulichen. Kannst du mir helfen, eine Klasse zu definieren, die Test1 und Test2 besteht?Warum wird durch die Deklaration einer Deskriptorklasse in der Funktion __init__ die Deskriptorfunktionalität unterbrochen?

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" 

Antwort

4

entsprechend den documentation:

Die folgenden Methoden nur gelten, wenn eine Instanz der Klasse enthält das Verfahren (ein sogenanntes Deskriptor Klasse) in der Klasse erscheint Wörterbuch eines anderen neuen Stils Klasse, bekannt als der Besitzer Klasse. In den folgenden Beispielen bezieht sich "das Attribut" auf das -Attribut, dessen Name der Schlüssel der -Eigenschaft in der Besitzerklasse __dict__ ist. Deskriptoren können nur als New-Style-Klassen implementiert werden.

So können Sie keine Deskriptoren für Instanzen haben.

Da der Deskriptor jedoch einen Verweis auf die Instanz erhält, die für den Zugriff verwendet wird, verwenden Sie diesen Schlüssel als Schlüssel zum Speichern des Status, und Sie können abhängig von der Instanz ein unterschiedliches Verhalten haben.

+0

OK, ich kann damit leben – user83753

+0

Auf den zweiten Gedanken, vielleicht kann ich damit nicht leben. In meiner Anwendung möchte ich Member-Funktionen in A setzen, die auch vom Zustand der Owner-Klasse abhängen. So zum Beispiel: Besitzer (State Info) Owner.a = Daten Owner.a.foo() Wie erhält Foo die Statusinformationen von Besitzer? – user83753

+0

@unknown (google): Oh, dafür speichern Sie die Daten auf der Instanz selbst. So können Sie es von den Methoden holen. – nosklo

0

Hier ist eine Klasse, die die ursprünglichen Tests bestehen kann, aber versuchen Sie es nicht in den meisten Situationen. es schlägt den isinstance-Test auf sich selbst fehl!

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

Das ist eine Klassenfabrik Funktion, als Klasse verkleidet – nosklo

+0

Ja, es ist, und stolz darauf. – user83753

0

Ich wurde von einem ähnlichen Problem gebissen, in dem ich Objekte mit Attributen, die von einem Deskriptor bestimmt wurden, klassifizieren wollte. Als ich das tat, bemerkte ich, dass die Attribute in allen Objekten überschrieben wurden, so dass sie nicht individuell waren.

hob ich eine Frage SO und die resultierende Antwort ist hier: class attribute changing value for no reason

Ein gutes Dokument Link Deskriptoren Diskussion hier ist: http://martyalchin.com/2007/nov/24/python-descriptors-part-2-of-2/

Ein Beispiel Descriptor aus dem oben genannten Link ist unten:

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