2009-06-16 5 views
7

Nella classe B di seguito volevo che la funzione __set__ in classe A venisse chiamata ogni volta che si assegna un valore a B().a. Invece, impostando un valore su B().a si sovrascrive con il valore B().a. La classe C che assegna a C().a funziona correttamente, ma volevo avere un'istanza separata di A per ogni classe utente, cioè non voglio cambiare 'a' in un'istanza di C() per cambiare 'a' in tutte le altre istanze. Ho scritto un paio di test per aiutare a illustrare il problema. Puoi aiutarmi a definire una classe che supererà sia test1 che test2?Perché dichiarare una classe descrittore nella funzione __init__ interrompe la funzionalità del descrittore?

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" 

risposta

4

conseguenza alla documentation:

I seguenti metodi applicano solo quando un'istanza della classe contenente il metodo (un descrittore cosiddetto classe) appare nella classe dizionario di un'altra classe di nuovo stile, nota come della classe del proprietario. Negli esempi di seguito, "l'attributo" si riferisce all'attributo il cui nome è la chiave della proprietà nella classe proprietario '__dict__. I descrittori possono essere implementati solo come classi di nuovo stile.

Quindi non è possibile avere descrittori su istanze.

Tuttavia, poiché il descrittore ottiene un riferimento all'istanza utilizzata per accedervi, basta usarlo come chiave per memorizzare lo stato e si può avere un comportamento diverso a seconda dell'istanza.

+0

OK, posso conviverci con quello – user83753

+0

Ripensandoci, forse non posso vivere con quello. Nella mia applicazione voglio inserire funzioni membro in A che dipendono anche dallo stato della classe del proprietario. Ad esempio: Proprietario (informazioni di stato) Proprietario.a = dati Owner.a.foo() Come si può ottenere le informazioni di stato dal proprietario? – user83753

+0

@unknown (google): oh, per questo si memorizzano i dati sull'istanza stessa. Quindi puoi recuperarlo dai metodi. – nosklo

0

Ecco una classe che può superare i test originali, ma non provare a utilizzarla nella maggior parte delle situazioni. fallisce il test dell'istanza su se stesso!

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

è una funzione di classe factory, camuffata come classe – nosklo

+0

Sì, lo è e ne è orgoglioso. – user83753

0

mi è stato morso da un problema simile in che volevo oggetti di classe con gli attributi governati da un descrittore. Quando l'ho fatto, ho notato che gli attributi venivano sovrascritti in tutti gli oggetti in modo che non fossero individuali.

ho sollevato una domanda SO e la risposta risultante è qui: class attribute changing value for no reason

Un buon collegamento del documento discutere descrittori è qui: http://martyalchin.com/2007/nov/24/python-descriptors-part-2-of-2/

Un esempio descrittore dal link di cui sopra è di seguito:

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