2013-10-24 13 views
5

sagen, dass ich eine Klasse, die __slots__ definiert:Kann __setattr __() in einer Klasse mit __slots__ definiert werden?

class Foo(object): 
    __slots__ = ['x'] 

    def __init__(self, x=1): 
     self.x = x 

    # will the following work? 
    def __setattr__(self, key, value): 
     if key == 'x': 
      object.__setattr__(self, name, -value) # Haha - let's set to minus x 

Kann ich __setattr__() für ihn definieren?

Seit Foo hat keine __dict__, was wird es aktualisieren?

Antwort

9

All Ihr Code tut, abgesehen von den Wert zu negieren, rufen Sie die Elternklasse __setattr__, die genau das ist, was ohne Ihre __setattr__ Methode passieren würde. Die kurze Antwort lautet also: Sicher kannst du eine __setattr__ definieren.

Was Sie nicht tun können, ist __setattr__ neu definieren self.__dict__ zu verwenden, da Instanzen einer Klasse mit Schlitzen nicht haben ein __dict__ Attribut. Aber solche Instanzen tun haben ein self.x Attribut, es ist Inhalt nicht nur in einem Wörterbuch auf der Instanz gespeichert.

Stattdessen werden die Slot-Werte an der gleichen Stelle gespeichert, andernfalls würde ein Instanz-Wörterbuch gespeichert werden. auf dem Objektheap. Platz ist reserviert für len(__slots__) Referenzen, und descriptors auf den Klassenzugriff diese Referenzen in Ihrem Namen.

Also, in einem __setattr__ Haken, können Sie einfach direkt stattdessen jene Deskriptoren nennen:

def __setattr__(self, key, value): 
    if key == 'x': 
     Foo.__dict__[key].__set__(self, -value) 

Interessante Umweg: ja, Klassen ohne __slots__ Attribut gibt ist ein Schlagwort, dass Sie Zugriff geben würde, zum __dict__ Objekt der Instanzen:

>>> class Bar(object): pass 
... 
>>> Bar.__dict__['__dict__'] 
<attribute '__dict__' of 'Bar' objects> 
>>> Bar.__dict__['__dict__'].__get__(Bar(), Bar) 
{} 

die ist, wie normale Instanzen aussehen kann bis self.__dict__. Was Sie fragt, wo das Bar.__dict__ Objekt gefunden wird. In Python ist es turtles all the way down, Sie aussehen würde, die auf dem type Objekt natürlich Objekt bis:

>>> 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}) 
+0

tut hier __dict__ zu arbeiten? ist das, weil die effektive Adresse von __dict__ und die Heap-Elemente die gleiche ist, und das ist eine Art Osterei? oder meinst du __slots__? –

+0

@CorleyBrigman: Verwechseln Sie nicht das "__dict__" der ** Klasse ** mit dem der ** Instanz **. Instanzen der Klasse "Foo" haben kein Attribut "__dict__". –

+0

@CorleyBrigman: Und 'Foo'-Instanzen haben kein '__dict__'-Attribut, weil' Foo .__ dict __ ['__ dict __']' einen 'KeyError' auslöst. –