Wert eines Dictionaries hängt von anderem Dictionary-Wert ab

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
BastiL
User
Beiträge: 135
Registriert: Montag 7. Juli 2008, 20:22

Hallo zusammen,

ich bräuchte etwa so etwas:

Code: Alles auswählen

testdict={"wert1" : 5, "wert2" : 2*testdict["wert1"],}
Der Wert zum Schlüssel "wert2" hängt also dynamisch vom Wert zu Schlüssel "wert1" ab. Wie lässt sich so etwas realisieren?

Danke.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

indem du die settattr Methoden überschreibst und dir solche Hooks einbaust.

€dit sagt, da gibts nen Modul für, aber im Prinzip ist da ne Speziallösung vermutlich besser.
Wenn du die Dinge tatsächlich als "3*foo" eingeben willst, muss eben "x*foo" nen Proxy erstellen.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

from functools import partial 
import operator as op

class ProxyFactory(object):

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

    def create_proxy(self, func):
        return Proxy(self, func)

    def _operation_proxy(self, func, val):
        return self.create_proxy(partial(func, val))

    def __mul__(self, other):
        return self._operation_proxy(op.mul, other)

    def __add__(self, other):
        return self._operation_proxy(op.add, other)

class Proxy(object):

    def __init__(self, parent, mod):
        self._parent = parent
        self._mod = mod

    def __getattr__(self, name):
        if not name in ("_parent", "_mod"):
            return self._mod(getattr(self._parent, name))
        else:
            return object.__getattr__(self, name)



master = ProxyFactory(5)
mul = master * 2
add = master + 1
assert mul.val == 10
assert add.val == 6
ich war mal so frei.
BastiL
User
Beiträge: 135
Registriert: Montag 7. Juli 2008, 20:22

Danke audax,

allerdings bin ich noch nicht so lange dabei als das dich das genau verstehe. Das ganze klingt ziemlich kompliziert..... Was muss ich den jetzt mit der von dir geposteten Lösung tun?

Ich bin gerade am grübeln ob das sich das nicht auch einfacher verwalten lässt, d.h ob ich eine andere Datenstruktur verwenden könnte....

Grüße
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Wo genau im Code hast du denn Probleme?
Probier einfach mal mit Teilstücken des Codes im Interpreter rum und schau in die Doku des operator und des functools Moduls. Sind alles keine schweren Dinge.
Die die object.__getattr__ Sache muss ich da machen, da ein self.foo schon wieder die eigene __getattr__ Methode aufruft und ich so eine Endlosschleife baue.

Aber na andere Datenstruktur wäre auch gut :D
BastiL
User
Beiträge: 135
Registriert: Montag 7. Juli 2008, 20:22

audax hat geschrieben:Aber na andere Datenstruktur wäre auch gut :D
Ok was ich machen möchte ist ein Interface für ein Programm schreiben, das dem Code Variablen übergibt. Die Variablen sichere ich in dictionaries, dabei ist der Variablenname der Schlüssel und der Wert der Variable der Wert. Was mich da schon stört, ist dass ich dictionaries nicht anordnen kann, außerdem würde ich gerne eine Erklärung noch irgendwie für jede Variable mitspeichern. Der User soll alle Variablen ändern können. Manche Variablen hängen von anderen Variablen ab - daher der Kunstgriff... Am Ende wird der Inhalt aller dictionaries in ein File geschrieben, dass dann die Schnittstelle darstellt.
Wie könnte denn die Datenstruktur sonst aussehen? Eventuell könnte man das über geschachtelte Listen realisieren?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Bau einfach eine Klasse dafür. So in der Art:

Code: Alles auswählen

class Variable(object):
    def __ini__(self, name, wert, beschreibung):
        self.name = name
        self.wert = wert
        self.beschreibung = beschreibung
Hört sich aber so an, als wenn du ein dickes Fass aufmachen willst ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BastiL
User
Beiträge: 135
Registriert: Montag 7. Juli 2008, 20:22

Hmm, ich muss dann aber für jede neue Variable eine neue Instanz der Klasse erzeugen. Jetzt brauche ich Methoden, um zu prüfen, ob eine Varible definiert ist und ggf. den Wert zu ändern. Deshalb bin ich ja auf dictionaries gekommen - die bringen diese Methoden von Haus aus mit.
jens hat geschrieben:Bau einfach eine Klasse dafür. So in der Art:

Code: Alles auswählen

class Variable(object):
    def __ini__(self, name, wert, beschreibung):
        self.name = name
        self.wert = wert
        self.beschreibung = beschreibung
Hört sich aber so an, als wenn du ein dickes Fass aufmachen willst ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

audax hat geschrieben:€dit sagt, da gibts nen Modul für, aber im Prinzip ist da ne Speziallösung vermutlich besser.
Ja, Trellis bzw. die ganzen CLOS Cells-Ports für Python.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Spricht irgendwas hiergegen?

Code: Alles auswählen

In [4]: a = {"wert1": 5, "wert2": lambda: a["wert1"] * 2}

In [5]: print a["wert2"]()
10
Du musst deine dynamischen Werte dann nur markieren, so dass du die Funktion aufrufen kannst.
BastiL
User
Beiträge: 135
Registriert: Montag 7. Juli 2008, 20:22

str1442 hat geschrieben: Du musst deine dynamischen Werte dann nur markieren, so dass du die Funktion aufrufen kannst.
Sieht eigentlich gut aus. wie meinst du das mit dem markieren?
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Naja, du hast dann eben Funktionen statt direkter Werte, die du erst aufrufen musst. Also musst du, wenn du einen Wert abrufst, entweder ausserhalb explizit überprüfen ob du ein Funktionsobjekt zurückbekommst oder einen Wert, oder du definierst einen Boolean Status, der dir anzeigt, ob das jetzt ein "statischer" oder ein dynamischer Wert ist. Zum Beispiel könnte jeder Wert des Dict ein Tupel sein, dessen erstes Argument wie gehabt der jeweilige Wert ist und als zweiten Wert True oder False. Dokumentieren tust du das dann als "is_dynamic" oder sowas. Dann reicht ein

Code: Alles auswählen

current_dict = dict((key, (normal_dict[0][key]() if normal_dict[key][1] else normal_dict[key][0])) for key in normal_dict)
Wobei normal_dict die Funktion beinhaltet und current_dict eben alle statischen Werte + die evaluierten dynamischen Werte.
BastiL
User
Beiträge: 135
Registriert: Montag 7. Juli 2008, 20:22

Ok so langsam verstehe ich deine Idee, str1442.
Ich habe mir alternativ noch überlegt, das mit skalaren Hilfsvariablen zu lösen.

Code: Alles auswählen

testdict={"wert1" : 5,}
tmp=2*testdict["wert1"]
testdict.update({"wert2" : tmp,})
print testdict
{'wert2': 10, 'wert1': 5}
testdict["wert1"]=7
print testdict
{'wert2': 10, 'wert1': 7}
Der Initialzustand ist so stimmig. Allerdings wird die Variable "tmp" nach einer Änderung von "wert1" natürlich nicht dynamisch aktualisiert - gibt es dafür Möglichkeiten?
kryz
User
Beiträge: 12
Registriert: Sonntag 3. Februar 2008, 16:55

vielleicht habe das problem nicht verstanden, aber würde folgendes nicht auch gehen?

Code: Alles auswählen

class MyDict(dict):
    def __setitem__(self, key, value):
        if key == 'wert1':
            dict.__setitem__(self, 'wert2', 2*value)
            dict.__setitem__(self, key, value)
        else:
            dict.__setitem__(self, key, value)

d = MyDict()
d['wert1'] = 2
print d
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Dann müsste man allerdings die Funktionen, die man braucht, gesondert abspeichern und sich eine Datenstruktur ausdenken, die alle Statischen Namen, von denen der neue Wert abhängt, in einer One to Many Relation abbilden, etwa einem Neuen dict mit <neuer_wert> => <tupel von alten werten>>. Das müsste dann in einer bestimmten Reihenfolge als Parameter an die Funktionen gegeben werden. Zumindest, wenn man das ganze generisch implementieren will. Schließlich soll das ja ein Dictionary sein, und nicht eine DoWhatEverIWantionary. Erledingt man das gleiche gleich mit lambda zuweisungen, braucht man nur sich das jeweils aktuelle Dict generieren lassen, indem man die Funktionen auswertet, die auf das Dict selbst mittels Closure Zugriff haben.
Antworten