2010-01-26 15 views
7

Qualsiasi idea se c'è un modo per rendere il seguente codice per lavorareModifica istanza di classe all'interno di un metodo di istanza

class Test(object): 

    def __init__(self, var): 
     self.var = var 

    def changeme(self): 
     self = Test(3) 

t = Test(1) 
assert t.var == 1 
t.changeme() 
assert t.var == 3 

è qualcosa di simile al seguente sicuro da usare per gli oggetti più complessi (come i modelli Django, a caldo scambiare la voce db a cui l'istanza fa riferimento)

class Test(object): 

    def __init__(self, var): 
     self.var = var 

    def changeme(self): 
     new_instance = Test(3) 
     self.__dict__ = new_instance.__dict__ 

t = Test(1) 
assert t.var == 1 
t.changeme() 
assert t.var == 3 
+2

Perché? Vuoi chiaramente una nuova istanza, perché non creare una nuova istanza e buttarla via? Spiega l'usecase, per favore. –

risposta

7

self = Test(3) re-binding del nome locale self, senza effetti esternamente osservabili.

Assegnazione self.__dict__ (a meno che non si sta parlando di istanze con __slots__ o da classi con metaclassi non banali) di solito è OK, e così è self.__init__(3) per reinizializzare l'istanza. Tuttavia preferirei avere un metodo specifico self.restart(3) che conosce viene chiamato su un'istanza già inizializzata e fa tutto ciò che è necessario per soddisfare quel caso specifico e insolito.

+0

Le metaclasses modello di Django sono ... disordinate. Non sarei sorpreso se tentassi di riassegnare "self .__ dict__' esplose in modo spettacolare. –

+0

@Ignacio, con "metaclassi non banali" in riproduzione (o '__slots__', ecc.), Potresti invece usare un ciclo di' getattr'/'setattr'. Il vantaggio di scrivere il metodo 'restart' che sostengo è che si isolano i tweaking (se ce ne sono) necessari per supportare vari casi, da oggetti normali a quelli con metaclomi disordinati e così via. –

3

No e no.

Detto questo, è possibile cambiare la classe di , ma non fare nemmeno questo.

2

Il codice precedente funziona, tranne che non farà molto, visto che sostituisce semplicemente l'oggetto denominato 'self' nell'ambito di changeme(). I nomi Python non sono vincolati ai valori, sono sempre relativi al loro ambito o spazio dei nomi.

di fare ciò che si vuole che ci si bisogno di avere accesso a un nome al di fuori della classe, che è possibile assegnare ad esso dal di dentro:

class Test: 
    def changeme(self): 
    global myclass 
    myclass = Test(3) 

myclass = Test(2) 
myclass.changeme() 
print myclass # 3 

Questo fondamentalmente solo sovrascrive il nome di 'MyClass' per puntare alla nuova istanza. Non "sovrascrive" la prima istanza come si potrebbe pensare. La vecchia istanza vive ancora, e sarà raccolta dei rifiuti a meno che non venga fatto riferimento altrove.

Problemi correlati