Modificare un'istanza di classe all'interno di un metodo di istanza
Domanda
Qualche idea se c'è un modo per rendere il seguente codice di lavorare
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 modelli di Django, a hot swap voce db l'istanza si riferisce a)
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
Soluzione
self = Test(3)
è ri-vincolante il nome self
locale, senza effetti esternamente osservabili.
L'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)
di ri-inizializzare l'istanza. Comunque preferirei avere un metodo specifico self.restart(3)
che sa è in fase di chiamata su un'istanza già inizializzata e fa tutto ciò che è necessario per far fronte a quel caso specifico e insolito.
Altri suggerimenti
No, e no.
Detto questo, è possono cambiare il class , ma non fare nemmeno questo.
Il primo codice funziona, tranne che non farà molto, visto che solo sostituisce l'oggetto denominato 'sé' nell'ambito della changeme (). nomi Python non sono bloccati ai valori, sono sempre rispetto al loro campo di applicazione o dello spazio dei nomi.
Per 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 "sovrascrivere" il primo esempio, come si potrebbe pensare. Il vecchio esempio vive ancora, e sarà garbage collection a meno che non si fa riferimento altrove.