partial mit Methoden-Parameter

Fragen zu Tkinter.
Antworten
deets

Goswin hat geschrieben: Geschätzter deets, du weißt gar nicht, wie beliebt du wärest, wenn du bei deiner Hilfestellung uns vergessliche Handbuchleser nicht gleich ausschimpfen würdest :wink: !
Das unterstellt, das mir Beliebtheit wichtiger waere als Spass an provokanten Formulierungen zu haben! Und ich versuche meine schandmaeuligkeit mit dem Willen des Posters zu korrelieren, den Fehler erstmal bei sich statt bei Python oder dem Rest der Welt zu suchen ;)
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

lunar hat geschrieben:@Goswin: Bist Du Dir sicher, dass Du wirklich dieses Verhalten wünschst?
Du hast recht, lambda lässt sich für callbacks nicht verwenden: bei Python nimmt das Argument der Funktion den Wert an, den es beim *Aufruf* des Callbacks hat, und nicht den Wert bei der *Definition* des Callbacks. :( Und das ist *nicht*, was ich brauche.
lunar

@Goswin: "i" ist kein Argument, sondern ein sogenannter „freier Name“. Python bindet freie Namen nicht über ihren Wert, sondern über ihren Namen. "i" innerhalb des "lambda"s ist also keine Kopie von "i", sondern eine Referenz darauf. "i" verhält sich zum "lambda" wie eine globale Variable zu einer normalen Funktion.
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

@lunar: Richtig.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

@Goswin
Ob man 'lambda' oder 'partial' verwendet, haengt im allgemeinen nicht vom Problem ab, man muss die Sachen nur richtig anwenden.
Um das Ganze mal aufzudröseln, ein einfaches Beispiel mit lambda:

Code: Alles auswählen

import Tkinter as tk


class Gui(object):

    def __init__(self):
        self.root = tk.Tk()
        self.buttons = [tk.Button(self.root, width=20, text='{0}'.format(i),
                                  command=lambda j=i: self.do_command(j)) for i in xrange(9)]
        for but in self.buttons:
            but.pack()
        for i, but in enumerate(self.buttons):
            but.bind('<Button-1>', lambda event, j=i: self.do_binding(event, j))


    def do_command(self, i):
        print 'command {0}'.format(i)


    def do_binding(self, event, i):
        print 'binding {0} {1}'.format(i, event.widget)


    def run(self):
        self.root.mainloop()


if __name__ == '__main__':
    Gui().run()
Und hier mit partial:

Code: Alles auswählen

import Tkinter as tk
from functools import partial


class Gui(object):

    def __init__(self):
        self.root = tk.Tk()
        self.buttons = [tk.Button(self.root, width=20, text='{0}'.format(i),
                                  command=partial(self.do_command, i)) for i in xrange(9)]
        for but in self.buttons:
            but.pack()
        for i, but in enumerate(self.buttons):
            but.bind('<Button-1>', partial(self.do_binding, i))


    def do_command(self, i):
        print 'command {0}'.format(i)


    def do_binding(self, i, event):
        print 'binding {0} {1}'.format(i, event.widget)


    def run(self):
        self.root.mainloop()


if __name__ == '__main__':
    Gui().run()
Antworten