werte aus dict lesen

Fragen zu Tkinter.
Antworten
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

Mittwoch 30. August 2006, 21:00

Hallo,

wie würdet ihr das folgende Problem lösen.

Code: Alles auswählen

from Tkinter import *

class Demo:
	def __init__(self, fenster):
		self.root=fenster
		
		self.wdict= {'aname':10,
					'cname':30,
					'bname':20,
					'dname':40,
				}
					
		for xv in range(len(self.wdict)):
			setattr(self, 'of%s' %xv, Frame(self.root) )
			
		for name in self.wdict.keys():
			button=Button(getattr(self, 'of%s' %xv),
				text=name,width=14, height=4,
				command=lambda s=self,
					wert=name :s.ausgabe(wert ))
						
			button.pack(side=LEFT, padx=2, pady=2, expand=YES, fill=BOTH)
			getattr(self, 'of%s' %xv).pack(expand=YES, fill=BOTH)
			
	def ausgabe(self, x):
		a=self.wdict.get(x)
		print a
if __name__=='__main__':
	root=Tk()
	Demo(root)
	root.mainloop()
es muss doch irgendwie auch einfacher gehen ? :roll:

schonmal danke.

Gruss
pyStyler
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Mittwoch 30. August 2006, 22:00

Hi PyStyler,

wow, ich bin mir nicht sicher, ob ich mit meiner jetzigen Erfahrung einen solch anspruchsvollen Code zusammenbekommen hätte (so dass er auch noch funktioniert)! Wie kommst Du auf diese (sorry) "Hintertürfunktionen" getattr und setattr? Die kann man gebrauchen, wenn man Namen deklarieren will, die als Strings vorliegen und später direkt als Name aufgerufen werden sollen, etwa so:

Code: Alles auswählen

>>> class dummy:pass
>>> test = dummy()
>>> setattr(test,"a", "Hallo welt")
>>> test.a
'Hallo welt'
Meistens kann man das aber schöner über Dictionaries oder sogar Listen lösen. In diesem Fall brauchst nichts außer dem eingangs definierten Dictionary.

Diese Klasse macht zumindest äußerlich das gleiche:

Code: Alles auswählen

class Demo:
    def __init__(self, fenster):
        self.root=fenster
       
        self.wdict= {'aname': 10,
                     'cname': 30,
                     'bname': 20,
                     'dname': 40
                    }

        ##  Wofuer brauchst Du die Frames??
        #for xv in range(len(self.wdict)):
        #    setattr(self, 'of%s' %xv, Frame(self.root) )
           
        for name, wert in self.wdict.items():

            ##  Funktion die die Ausgabefunktion aufruft
            ##  der Wert koennte eventuell auch gleich hier ausgegben werden
            def command_function(wert = wert):
                self.ausgabe(wert)
                #print wert          ## Alternative

            Button(fenster, text=name, width=14, height=4,command=command_function)\
                  .pack(side=LEFT, padx=2, pady=2, expand=YES, fill=BOTH)
                                  
    def ausgabe(self, x):
        """Gibt den Parameterwert x aus"""
        print x
Sie legt aber keine Frames an, in denen nur ein Button liegt. Wenn das Anforderung ist, okay. Aber ich sehe darin im Normalfall keinen Sinn.
Und wenn die Ausgabe-Methode nur den Wert des Buttons ausgeben soll, kannst Du sie Dir auch sparen und den Wert gleich in der Funktion <command_function> ausgeben lassen.

Kurzfassung:

Code: Alles auswählen

class Demo:
    def __init__(self, fenster):
        self.root=fenster
        self.wdict= {'aname': 10, 'cname': 30, 'bname': 20, 'dname': 40}

        for name, wert in self.wdict.items():
            def command_function(wert = wert): print wert
            Button(fenster, text=name, width=14, height=4,command=command_function)\
                  .pack(side=LEFT, padx=2, pady=2, expand=YES, fill=BOTH)
Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

Donnerstag 31. August 2006, 10:13

Hallo Michael,
ersteinmal danke für deine so ausführliche Antwort , es hat mir sehr geholfen.
Michael Schneider hat geschrieben: wow, ich bin mir nicht sicher, ob ich mit meiner jetzigen Erfahrung einen solch anspruchsvollen Code zusammenbekommen hätte (so dass er auch noch funktioniert)! Wie kommst Du auf diese (sorry)
in einem Buch von mir, wird so ein ähnlicher Codestück gezeigt.

Auch neige ich sehr oft dazu, für einfache Dinge sehr Kompliziert zu denken. ( ( ist das normal ? ) nur was natürlich python angeht )

Danke&Gruss
pyStyler


p.s vlt hat noch jemand ne andere Idee nur interessenhalber
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Donnerstag 31. August 2006, 17:34

Hi PyStyler,

wie wäre es, wenn Du einfach mal mit der Aufgabe anfängst? :) Das hilft ungemein, wenn man Code optimieren möchte. :D Man kann sie auch grob aus dem Inhalt entnehmen, aber beispielsweise ob die Frames da drin gefordert waren, kann man so nicht wissen.

Es ist wirklich schwierig, trivial genug für Python zu denken. Formuliere einfach, was das Programm machen soll, und schreib es auf. Dann noch einrücken und Dein Programm ist fertig. ;-)

Okay, ganz so einfach ist das auch wieder nicht, aber Du kannst in Python wirklich viele Dinge so programmieren, wie Du normal denkst, nicht wie Du in C denken würdest.

Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

Donnerstag 31. August 2006, 19:58

Hi,

Frame wird ( wurde ) doch gebraucht um die Buttons daran anzubinden oder sehe ich das falsch ?
Python GE-Packt hat geschrieben:

Code: Alles auswählen

setattr(object, name, value)
"""
Die Argumente sind ein Objektbezeichner, ein String mit dem Namen
eines Atributes des Objektes und ein Wert.
"""
Gruss
pyStyler
Zuletzt geändert von pyStyler am Donnerstag 31. August 2006, 22:02, insgesamt 2-mal geändert.
BlackJack

Donnerstag 31. August 2006, 21:38

pyStyler hat geschrieben:Frame wird doch gebraucht um die Buttons anzubinden oder sehe ich das falsch ?
Woran anbinden? Michaels Code funktioniert doch auch ohne Frames, oder nicht!?

Einen Frame verwendet man üblicherweise um dort mehrere Widgets zu platzieren und diese dann als ein ganzes Objekt in die GUI einzufügen.
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

Donnerstag 31. August 2006, 22:00

BlackJack hat geschrieben: Woran anbinden? Michaels Code funktioniert doch auch ohne Frames, oder nicht!?
ja stimmt der Code funktioniert Wunderbar aber das hier unten von Michael
Michael hat geschrieben: die Frames da drin gefordert waren, kann man so nicht wissen
habe ich es eher auf den ersten Post von mir bezogen.

hier das gemeinte Codestück

Code: Alles auswählen

setattr(self, 'of%s' %xv, Frame(self.root) )
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Donnerstag 31. August 2006, 23:41

Hi PyStyler,

nein, mit "gefordert" meine ich eine Anforderung per Spezifikation.

Das wie ich finde größte Problem bei der commerziellen Softwareentwicklung ist häufig, dass eine Gruppe A Anforderungen stellt, die Gruppe B programmiert um dann von Gruppe C praktisch verwendet zu werden. Nun muss aber B genau das programmieren, was A wünscht, auch wenn es besser wüsste, was C tatsächlich will und sich A mal wieder viel zu weit aus dem Fenster lehnt, indem es sich in Dinge einmischt von denen es keine Ahnung hat und demzufolge völlig unnötige Einschränkungen vorgibt (z.B. einfach mal Frames zu verwenden, vielleicht weil das grad so Mode ist...).
Alles klar? Wer schonmal beruflich programmiert hat wird wissen, wovon ich rede. :idea:

Jedenfalls sind getattr und setattr hier völlig überflüssig, weil meiner Meinung viel zu kompliziert dafür, dass man mit einfachen Strukturen klarkommt. Heb Dir das am besten für Wrapper-Klassen und dergleichen auf. :-)

Grüße und gute Nacht,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten