Lambda

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
HardwareManager
User
Beiträge: 59
Registriert: Freitag 31. Mai 2013, 21:18

Ich will ein Programm mit Tkinter machen das mehrere Buttons hat und jeder soll eine andere wirkung haben. Ich versuche es gerade mit lambda weil es muss ja nur

Code: Alles auswählen

button = tk.Button(root, text = "test", command=g(1))
das ausführen wobei es aber nichts macht.
g() ist

Code: Alles auswählen

g = lambda x: x + 1
aber wenn ich auf den Button klicke dann passiert nichts
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Code: Alles auswählen

>>> g = lambda x: x + 1
>>> g(1)
2
>>> g
<function <lambda> at 0x1207230>
g ist eine Funktion. Wenn du g(1) aufrufst, bekommst du keine (neue) Funktion zurück, sondern den Rückgabewert von g, wenn es mit dem Argument 1 aufgerufen wurde (in dem Fall 2). tk.Button erwartet aber eine Funktion als `command`-Parameter. Was kann man also machen? Die Frage ist, was für eine Funktion du übergeben möchtest: Soll sie einen Parameter erwarten und den übergebenen Wert um eins erhöht zurückgeben? Dann übergib einfach g, also: ``button = tk.Button(root, text = "test", command=g)``. Oder soll die Funktion keinen Parameter erwarten und in jedem Fall 2 zurückgeben? Das kannst du entweder mit einem weiteren lambda erledigen oder, noch viel besser, mit functools.partial:

Code: Alles auswählen

>>> lambda: g(1)
<function <lambda> at 0x13f71b8>
>>> (lambda: g(1))()
2
>>> from functools import partial
>>> f = partial(g, 1)
>>> f
<functools.partial object at 0x13765d0>
>>> f()
2
In deinem Fall siehe das dann so aus: ``button = tk.Button(root, text = "test", command=partial(g, 1))``

Mir fehlt die Erfahrung mit Tkinter um sagen zu können, was du in deinem Fall brauchst.
BlackJack

Um dann noch die Erfahrung bezüglich Tkinter ins Spiel zu bringen: Was die Funktion die als `command` übergeben wird als Rückgabewert hat ist vollkommen egal weil das Tkinter nicht interessiert. Der Wert wird einfach ignoriert. Also selbst wenn man die Funktion richtig definiert und übergibt, sieht man da nirgends einen Effekt, solange die Funktionen keinen Effekt hat sondern nur einen Rückgabewert.

Ich denke hier sollte man besser objektorientierte Programmierung lernen und mit dem Wissen ausgestattet dann eine entsprechende Klasse schreiben und bei `command` eine Methode übergeben die dann den Zustand des Objekts so ändert, dass man nach dem Druck auf die Schaltfläche auch den Effekt davon sehen und verwenden kann.
HardwareManager
User
Beiträge: 59
Registriert: Freitag 31. Mai 2013, 21:18

DAnke für die schnelle Antwort! Ich dachte lambda setzt die variable neu x neu!
Weil da sollen noch 8 andere Buttons hin die X auch größer machen. Der 1. Button um 1, der 2. Button um 2 usw
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Wie soll denn `x` veraendert werden, wenn da ueberhaupt keine Zuweisung ist?

Aber selbst mit `x += 1` funktioniert das nicht, weil `x` ein lokaler Name ist.
Was du willst ist was BlackJack schon angedeutet hat: Ein Objekt, dass dein `x` als Attribut speichert und eine Methode zum erhoehen hat, die du dann als `command` uebergibst.
BlackJack

Mal als kleines Beispiel:

Code: Alles auswählen

import Tkinter as tk
from functools import partial


class CounterFrame(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.value = 0
        self.value_label = tk.Label(self)
        self.value_label.pack()
        button_frame = tk.Frame(self)
        for i in xrange(1, 6):
            tk.Button(
                button_frame, text=str(i), command=partial(self.increase, i)
            ).pack(side=tk.LEFT)
        button_frame.pack()
        self._update_value_display()

    def _update_value_display(self):
        self.value_label['text'] = str(self.value)

    def increase(self, amount):
        self.value += amount
        self._update_value_display()


def main():
    root = tk.Tk()
    counter = CounterFrame(root)
    counter.pack()
    root.mainloop()


if __name__ == '__main__':
    main()
HardwareManager
User
Beiträge: 59
Registriert: Freitag 31. Mai 2013, 21:18

mein Programm sieht aber im moment so aus:

Code: Alles auswählen

from tkinter import *
import tkinter as tk
x = 0
def GUI():
    while x == 0:
        root = Tk()
        w = Canvas(root, width=500, height=500)
        w.pack()
        button = Button(root, text = "b1", command=b1())
        button.place(x=100,y=100)
        
        button = Button(root, text = "b2", command=b2())
        button.place(x=150,y=100)

        button = Button(root, text = "b3", command=b3())
        button.place(x=200,y=100)

        button = Button(root, text = "b4", command=b4())
        button.place(x=100,y=150)

        button = Button(root, text = "b5", command=b5())
        button.place(x=150,y=150)

        button = Button(root, text = "b6", command=b6())
        button.place(x=200,y=150)

        button = Button(root, text = "b7", command=b7())
        button.place(x=100,y=200)

        button = Button(root, text = "b8", command=b8())
        button.place(x=150,y=200)

        button = Button(root, text = "b9", command=b9())
        button.place(x=200,y=200)
    return x

def b1():
    global x
    x += 1

def b2():
    global x
    x += 2

def b3():
    global x
    x += 3

def b4():
    global x
    x += 4

def b5():
    global x
    x += 5

def b6():
    global x
    x += 6

def b7():
    global x
    x += 7

def b8():
    global x
    x += 8

def b9():
    global x
    x += 9
    
print(GUI())
und so soll es in etwa am Ende auch aussehen
aber ich weis nicht wie ich 2 befehle in einen Button packe.
Und ein anderes Problem ist Wenn ich auf einen Button klicke verändert sich die zahl nicht die Zahl bleibt immer auf 45 was die summe von allem ist.
ImmmerEineGuteIdee
|=|=|=|=|=|=|=|
HardwareManager
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

HardwareManager hat geschrieben:und so soll es in etwa am Ende auch aussehen
Dann ist doch alles gut, oder?
HardwareManager hat geschrieben:aber ich weis nicht wie ich 2 befehle in einen Button packe.
Das weiß wahrscheinlich niemand...
HardwareManager hat geschrieben:Und ein anderes Problem ist Wenn ich auf einen Button klicke verändert sich die zahl nicht die Zahl bleibt immer auf 45 was die summe von allem ist.
Dann solltest Du vielleicht doch von Deinem Code Abschied nehmen und Dir BlackJack's Beispiel anschauen und verstehen...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@HardwareManager: Wenn das *so* aussehen soll, dann kann man Dir nicht wirklich helfen. :twisted:

Edit: Tipp: Solange da noch `place()` und ``global`` drin sind, ist das nichts vernünftiges.
Antworten