2016-07-25 6 views
0

Gibt es eine Möglichkeit, ein Dictionary von Funktionen zu erstellen, die set- und get-Anweisungen verwenden und sie dann als set verwenden und Funktionen erhalten?Verwenden Sie __get__, __set__ mit Wörterbuchelement?

class thing(object): 
    def __init__(self, thingy) 
     self.thingy = thingy 
    def __get__(self,instance,owner): 
     return thingy 
    def __set__(self,instance,value): 
     thingy += value 

theDict = {"bob":thing(5), "suzy":thing(2)} 

theDict["bob"] = 10 

wollte Ergebnis ist, dass 10 in die Set-Funktion geht und ergänzt die bestehenden 5

print theDict["bob"] 
>>> 15 

tatsächliche Ergebnis ist, dass das Wörterbuch

print theDict["bob"] 
>>> 10 

den Eintrag mit dem numerischen Wert ersetzt Warum kann ich nicht einfach eine Funktion wie .. theDict ["bob"]. Add (10) machen, weil es sich um ein existierendes und bereits wirklich gut funktionierendes handelt g Funktion, die das Set verwendet und bekommt. Der Fall, mit dem ich arbeite, ist ein Randfall, und es wäre nicht sinnvoll, alles neu zu programmieren, um für diesen einen Fall Arbeit zu leisten.

Ich brauche einige Mittel, um Instanzen dieses set/get dingy zu speichern, das zugänglich ist, aber keine Ebene der Tiefe schafft, die vorhandene Referenzen brechen könnte.

Bitte fragen Sie nicht nach dem tatsächlichen Code. Es würde Seiten Code benötigen, um das Problem einzukapseln.

+0

Was zum Teufel? Nein, '__get__' und' __set__' funktionieren nicht so. Ich wäre sehr misstrauisch gegenüber Ihrem bestehenden Design, wenn Ihr vorhandenes Design "dingy" auf dem Deskriptor selbst statt auf Objekten der Klasse speichert, an die der Deskriptor angehängt ist. – user2357112

+0

Ich bin auch ziemlich verwirrt über diese Frage ... Ich verstehe nicht, wie '__get__' und' __set__' sich auf das beziehen, was Sie versuchen zu tun. Ich nehme an, dass Sie eine Wrapper-Klasse erstellen können, die '__getitem__' und' __setitem__' überschreibt, um das delegierte dict auf die von Ihnen gewünschte Art und Weise zu aktualisieren. Aber ohne echten Code zu sehen (oder zumindest ein minimales Beispiel dessen, was Sie wirklich erreichen wollen), wird es schwer sein, mehr Ratschläge zu geben als das ... – mgilson

+0

Das Hauptproblem, das Sie haben, dass Sie müssen Entscheiden Sie, welches Objekt für Ihr benutzerdefiniertes Verhalten verantwortlich ist.Im Moment führen Sie eine Aktion auf Dictionary aus ('theDict [" bob "] = 10') weisen Sie 10 dem Schlüssel' bob' in 'theDict' zu (wie Sie sehen, erwähnt diese Beschreibung nicht einmal den zuvor unter diesem Schlüssel gespeicherten Wert) , aber erwarten Sie, benutzerdefinierte Logik in 'thing' auszunutzen. Wenn benutzerdefinierte Logik in "Sache" ist, fragen Sie "Sache", es zu tun, fragen Sie nicht dict. Und wenn Sie nicht können, überdenken Sie Ihr Design. –

Antwort

1

Sie könnten es tun, wenn Sie können (auch) eine spezielle Version des Wörterbuchs verwenden, die Ihrer Thing Klasse bekannt ist und behandelt sie getrennt:

class Thing(object): 
    def __init__(self, thingy): 
     self._thingy = thingy 
    def _get_thingy(self): 
     return self._thingy 
    def _set_thingy(self, value): 
     self._thingy += value 

    thingy = property(_get_thingy, _set_thingy, None, "I'm a 'thingy' property.") 

class ThingDict(dict): 
    def __getitem__(self, key): 
     if key in self and isinstance(dict.__getitem__(self, key), Thing): 
      return dict.__getitem__(self, key).thingy 
     else: 
      return dict.__getitem__(self, key) 

    def __setitem__(self, key, value): 
     if key in self and isinstance(dict.__getitem__(self, key), Thing): 
      dict.__getitem__(self, key).thingy = value 
     else: 
      dict.__setitem__(self, key, value) 


theDict = ThingDict({"bob": Thing(5), "suzy": Thing(2), "don": 42}) 

print(theDict["bob"]) # --> 5 
theDict["bob"] = 10 
print(theDict["bob"]) # --> 15 

# non-Thing value 
print(theDict["don"]) # --> 42 
theDict["don"] = 10 
print(theDict["don"]) # --> 10 
+0

Das funktioniert fast für mich, aber mit einer Ausnahme. Die Anzahl der übergebenen Argumente. Meine Klasse, die ich in das Wörterbuch einfüge, verwendet die Instanz, die an sie übergeben wurde. Diese dict-Methode scheint diese Instanz nicht zu passieren. Gibt es eine Möglichkeit, dies in dieser Methode zu tun? –

1

Nein, da zum Ausführen theDict["bob"] = 10 die Python-Laufzeit keine Methoden des vorherigen Werts aufrufen. Es ist nicht so, wenn myObject.mydescriptor = 10 den Descriptor Setter aufruft.

Nun, vielleicht ruft es __del__ auf den vorherigen Wert, wenn der Refcount Null erreicht, aber lasst uns dort nicht hingehen!

Wenn Sie so etwas tun möchten, müssen Sie die Funktionsweise des Wörterbuchs ändern, nicht den Inhalt. Zum Beispiel könnten Sie die Unterklasse dict (mit den üblichen Warnungen, dass Sie böse, schlecht und falsch sind, eine nicht-Liskov-substituierende abgeleitete Klasse zu schreiben). Oder Sie könnten eine Instanz von collections.MutableMapping von Grund auf neu implementieren. Aber ich glaube nicht, dass es einen Weg gibt, den normalen Betrieb von dict mit einem speziellen Wert zu hijacken, der darin gespeichert ist.

+0

+1 für den Vorschlag 'collections.MutableMapping'. Siehe: [http://Stackoverflow.com/a/3387975/6084928](http://Stackoverflow.com/a/3387975/6084928) –

+0

@Lex: Ich denke, die Implementierung eines konkreten 'collections.MutableMapping' Containers ist übertrieben- eine relativ einfache Unterklasse von 'dict' funktioniert gut. Siehe [meine Antwort] (http://stackoverflow.com/a/38574478/355230). – martineau

+0

Messepunkt. Ihre Lösung ist prägnanter. –

0

theDict["bob"] = 10 ist nur 10 auf den Schlüssel bob für theDict zuweisen. Ich denke, dass Sie zuerst über die magischen Methoden und __set__ wissen sollten. Gehe zu: https://docs.python.org/2.7/howto/descriptor.html Die Verwendung einer Klasse ist möglicherweise einfacher als dict.

Verwandte Themen