Problem mit dict.item()

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
Frank aka Ch3ck3r
User
Beiträge: 49
Registriert: Dienstag 13. November 2007, 21:56
Wohnort: Berlin
Kontaktdaten:

Dienstag 15. Januar 2008, 21:47

Hi ich habe ein Problem bei folgendem dict und der Methode item()

Code: Alles auswählen

        addmenus = {
            "Programm":
                {
                    "&Informationen": [u"Informationen \xfcber das Programm",self.onAbout],
                    "&Beenden": ["Verbindung trennen und das Programm beenden",self.onExit]
                },
            "Verbindung":
                {
                    "&Herstellen": ["Die Verbindung mit dem Server herstellen",self.onConnect],
                    "&Trennen": ["Die Verbindung mit dem Server trennen",self.onDisconnect],
                    "separator": None,
                    u"&Pr\xfcfen": [u"Die Verbindung mit dem Server pr\xfcfen",self.onCheck]
                }
        }
Wenn ich nun

Code: Alles auswählen

for heading,content = addmenus.items():
    print heading
laufen lasse bekomme ich als erstes "Verbindung" ausgegeben, anstatt "Programm". Auch wenn ich das Dict umdrehe bleibt die Ausgabe so.
Ich möchte jedoch erst Programm ausgeben.
kostenlose TS2-Server für jeweils 31 Tage:
http://www.ts-onlyfree.de
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Dienstag 15. Januar 2008, 22:15

http://docs.python.org/lib/typesmapping.html hat geschrieben:Keys and values are listed in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary's history of insertions and deletions.
Die Reihenfolge der Schlüssel und Werte ist mehr oder weniger willkürlich, sie ändert sich lediglich nicht, wenn du das dict nicht veränderst.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Dienstag 15. Januar 2008, 22:22

Das die Syntax überhaupt geht :?: ...

Richtig sollte es so sein:

Code: Alles auswählen

for heading,content in addmenus.items():
    print heading
Wie Trundle schon sagte, kannst du bei einem dict nicht davon ausgehen das die Werte in der Reihenfolge rausfallen wie du sie einträgst.
Frank aka Ch3ck3r
User
Beiträge: 49
Registriert: Dienstag 13. November 2007, 21:56
Wohnort: Berlin
Kontaktdaten:

Dienstag 15. Januar 2008, 22:44

das war nur ein kleines beispiel... ich wollte euch nicht diesen kompletten Code schreiben:

Code: Alles auswählen

        addmenus = {
            "Verbindung":
                {
                    "&Herstellen": ["Die Verbindung mit dem Server herstellen",self.onConnect],
                    "&Trennen": ["Die Verbindung mit dem Server trennen",self.onDisconnect],
                    "separator": None,
                    u"&Pr\xfcfen": [u"Die Verbindung mit dem Server pr\xfcfen",self.onCheck]
                },
            "Programm":
                {
                    "&Informationen": [u"Informationen \xfcber das Programm",self.onAbout],
                    "&Beenden": ["Verbindung trennen und das Programm beenden",self.onExit]
                }
        }
        self.menus(addmenus)
        self.Show(1)
        
    def menus(self,menus={}):
        self.menubar = wx.MenuBar()
        for menuname,menuentries in menus.items():
            newmenu = wx.Menu()
            for title,details  in menuentries.items():
                print title
                if title != "separator" and details != None:
                    status = details[0]
                    function = details[1]
                    tobind = newmenu.Append(-1,title,status)
                    self.Bind(wx.EVT_MENU,function,tobind)
                else:
                    newmenu.AppendSeparator()
            self.menubar.Append(newmenu,menuname)
        self.SetMenuBar(self.menubar)
Wie zum Teufel kann ich denn dann bitte die Reihenfolge bestimmen?
Ich kann ja nicht sagen ich lese zuerst "Programm" aus also addmenu["programm"] denn ich weiß ja nicht was dort steht (also hier in dem Beispiel schon, aber das soll ja dynamisch laufen am ende, und der erste eintrag soll zu erst ausgegeben werden.)
kostenlose TS2-Server für jeweils 31 Tage:
http://www.ts-onlyfree.de
Nicht_zu_definieren
User
Beiträge: 21
Registriert: Freitag 21. April 2006, 17:01
Kontaktdaten:

Dienstag 15. Januar 2008, 22:52

Ich würde es ganz einfach mit Tupeln machen:

Code: Alles auswählen

addmenus = (
    ('Programm', (
        ('Herstellen', 'Die Verbindung herstellen', self.onConnect),
        ('Trennen', 'Die Verbindung trennen', self.onDisconnect),
        :
        :
    :
    :
)
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Dienstag 15. Januar 2008, 23:01

Frank aka Ch3ck3r hat geschrieben:Wie zum Teufel kann ich denn dann bitte die Reihenfolge bestimmen?
Mit einer Liste oder einem Tupel beispielsweise.

Code: Alles auswählen

addmenus = (
    ('Programm', (
        ('Informationen',
            ('Informationen über das Programm', self.onAbout)),
        ('Beenden',
            ('Verbindung trennen und das Programm beenden', self.onExit))
    )),
    ('Verbindung', (
        ('Herstellen',
            ('....', self.onConnect)),
        ('Trennen',
            ('....', self.onDisconnect))
    ))
)

for menuname, menuentries in addmenus:
    for title, details  in menuentries:
        ...
Edit: zu lahm.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dienstag 15. Januar 2008, 23:28

Trundle hat geschrieben:Mit einer Liste oder einem Tupel beispielsweise.
Oder mit einem Ordered Dict. Gibts auch schon mehrfach implementiert.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Frank aka Ch3ck3r
User
Beiträge: 49
Registriert: Dienstag 13. November 2007, 21:56
Wohnort: Berlin
Kontaktdaten:

Mittwoch 16. Januar 2008, 15:02

gefällt mir nicht so wirklich xD aber wenn es nun einmal nicht anders geht, werde ich das mit Tupeln machen.

Danke für eure Hilfe (ich werd mir erstmal die Ordered Dicts anschauen)
kostenlose TS2-Server für jeweils 31 Tage:
http://www.ts-onlyfree.de
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Mittwoch 16. Januar 2008, 16:13

Vielleicht ist dieses Beispiel interessant für Dich:
http://www.python-forum.de/topic-6891.html ?
(Soll keine Eigenwerbung sein ...)

Gruß,
Christian
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Mittwoch 16. Januar 2008, 17:43

Trundle hat geschrieben:
Frank aka Ch3ck3r hat geschrieben:Wie zum Teufel kann ich denn dann bitte die Reihenfolge bestimmen?
Mit einer Liste oder einem Tupel beispielsweise.
Wo wir schon im anderen Thread bei den Grundkonzepten von Listen und Tupeln sind, wäre das hier "korrekter":

Code: Alles auswählen

addmenus = [
    ('Programm', [
        ('Informationen',
            ('Informationen über das Programm', self.onAbout)),
        ('Beenden',
            ('Verbindung trennen und das Programm beenden', self.onExit))
    ]),
    ('Verbindung', [
        ('Herstellen',
            ('....', self.onConnect)),
        ('Trennen',
            ('....', self.onDisconnect))
    ])
]
Zuletzt geändert von birkenfeld am Mittwoch 16. Januar 2008, 19:35, insgesamt 1-mal geändert.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Mittwoch 16. Januar 2008, 19:31

Ich persönlich würde eine DSL erfinden und benutzen, um derartige Menüs zu definieren. Zum Beispiel so:

Code: Alles auswählen

menu_bar(
  menu("Programm",
     item("&Informationen", help_text="Informationen über das Programm", action=self.onAbout),
     item("&Beenden", help_text="...", action=self.onExit),
  ),
  ...
)
Letztlich wird das die selbe Struktur mit Tupel und Listen erzeugen, doch das ist um eine Größenordnung leichter zu lesen und zu verstehen, finde ich.

Es könnte auch interessant sein, folgenden Ansatz mal auszuprobieren:

Code: Alles auswählen

@menu_item("About", in_menu="Programm", help_text="...")
def onAbout():
   ...

@menu_item("Beenden", in_menu="Programm", help_text="...")
def onExit():
   ....
Vorteil wäre, dass man sich so sein Menü relativ dynamisch zusammenbauen kann. Nachteil wäre, dass das Menu relativ dynamisch zusammengebaut ist und z.B. die Reihenfolge der Menüeintrage schwer zu definieren ist.

Da es mir allgemein besser erscheint, ein Command-Pattern zu benutzen und nicht einfach nur Funktionen, wäre eine Kombination beider Ansätze denkbar:

Code: Alles auswählen

class AboutCmd(Command):
  label = "About"
  help_text = "..."
  
  def execute(): ...

class ExitCmd(Command):
  label = "Beenden"

  def execute(): ...

menu_bar(
  menu("Programm", AboutCmd, ExitCmd, ...),
)
Das würde (mit weniger Aufwand) dem Weg entsprechen, wie man das z.B. in der Eclipse-Plattform sieht. Es gibt dann verschiedene Arten von Kommandos: Welche, die man rückgängig machen (UndoableCommand) kann und welche, die die Undo-Liste löschen usw. Kommandos kann man dann sowohl in der zentralen Menüleiste, also auch in Form von Schaltflächen in der Funktionsleiste als auch als einzelne Schaltflächen vorfinden. Kommando-Exemplare könnten zudem wissen, ob sie gerade erlaubt sind (enablement state), dann können diese aber wiederum keinen Zustand für das Undo speichern, weil jetzt Kommando-Exemplare und nicht mehr Kommando-Klassen über die Menüleiste referenziert werden.

Egal, was ich sagen wollte ist: Nimm nicht einfach nur Listen, mach es lesbar und abstrahiere dabei. Nutze die Möglichkeiten der Metaprogrammierung.

Stefan
lunar

Mittwoch 16. Januar 2008, 19:41

sma hat geschrieben:Das würde (mit weniger Aufwand) dem Weg entsprechen, wie man das z.B. in der Eclipse-Plattform sieht. Es gibt dann verschiedene Arten von Kommandos: Welche, die man rückgängig machen (UndoableCommand) kann und welche, die die Undo-Liste löschen usw. Kommandos kann man dann sowohl in der zentralen Menüleiste, also auch in Form von Schaltflächen in der Funktionsleiste als auch als einzelne Schaltflächen vorfinden. Kommando-Exemplare könnten zudem wissen, ob sie gerade erlaubt sind (enablement state), dann können diese aber wiederum keinen Zustand für das Undo speichern, weil jetzt Kommando-Exemplare und nicht mehr Kommando-Klassen über die Menüleiste referenziert werden.
Ein halbwegs modernes GUI-Toolkit sollte solche Klassen eigentlich mitbringen. Qt4 hat QAction, Swing hat Action, aber wx offenbar nicht, oder?
Antworten