Tutto il codice fa, oltre a negare il valore, è chiamare la classe genitore __setattr__
, che è esattamente ciò che accadrebbe senza il tuo metodo __setattr__
. Quindi la risposta breve è: Certo, puoi definire un __setattr__
.
Quello che non si può fare è ridefinire __setattr__
usare self.__dict__
, perché le istanze di una classe con slot Non hanno un attributo __dict__
. Ma tali istanze do hanno un attributo self.x
, il suo contenuto non è memorizzato in un dizionario nell'istanza.
Invece, i valori di slot sono memorizzati nella stessa posizione in cui un dizionario di istanza __dict__
sarebbe altrimenti memorizzato; sull'heap dell'oggetto. Lo spazio è riservato ai riferimenti len(__slots__)
e descriptors alla classe accede a questi riferimenti per tuo conto.
Così, in un gancio __setattr__
, si può chiamare tali descrittori direttamente invece:
def __setattr__(self, key, value):
if key == 'x':
Foo.__dict__[key].__set__(self, -value)
deviazione Interessante: sì, sulle classi, senza un attributo __slots__
, c'è è un descrittore, che vi darà l'accesso alla __dict__
oggetto di istanze:
>>> class Bar(object): pass
...
>>> Bar.__dict__['__dict__']
<attribute '__dict__' of 'Bar' objects>
>>> Bar.__dict__['__dict__'].__get__(Bar(), Bar)
{}
che è come normali casi possono guardare su self.__dict__
. Che ti fa chiedere dove si trova l'oggetto Bar.__dict__
. In Python, è turtles all the way down, ci si guarda che oggetto sul type
oggetto, naturalmente:
>>> type.__dict__['__dict__']
<attribute '__dict__' of 'type' objects>
>>> type.__dict__['__dict__'].__get__(Bar, type)
dict_proxy({'__dict__': <attribute '__dict__' of 'Bar' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Bar' objects>, '__doc__': None})
fa __dict__ lavorare qui? è perché l'indirizzo effettivo di __dict__ e degli elementi dell'heap è lo stesso, e questa è una specie di uovo di Pasqua? o intendevi __slots__? –
@CorleyBrigman: non confondere il '__dict__' della ** classe ** con quella dell'istanza ** **. Le istanze della classe 'Foo' non hanno un attributo' __dict__'. –
@CorleyBrigman: E le istanze di 'Foo' non hanno attributo' __dict__', perché 'Foo .__ dict __ ['__ dict __'] 'genera un' KeyError'. –