Seite 1 von 1

Verstehe den Code nicht

Verfasst: Samstag 10. April 2021, 15:41
von Kahnbein.Kai
Guten Tag,
ich habe gerade ein Codebeispiel gefunden das ich nicht verstehe, evtl. kann mir das jemand erläutern und Licht in die Dunkelheit bringen.
Es geht um folgenden Post bei stack overflow https://stackoverflow.com/questions/624 ... er-but-got
Der Code ist folgender:

Code: Alles auswählen

from tkinter import *

def callback(text, wid):
    if str.isdigit(text) or not text:
        text = text if text else 0
        if wid == str(entry3):
            n = entry2.get() if entry2.get() else 0
        if wid == str(entry2):
            n = entry3.get() if entry3.get() else 0
        ent1.set(int(n) + int(text))
        return True
    return False

root = Tk()

ent1 = IntVar()

vcmd = (root.register(callback), '%P', '%W')
frame = Frame(root)
frame.pack()

entry1 = Entry(frame, width=5, textvariable=ent1)
entry2 = Entry(frame, width=5, validate='all', validatecommand=vcmd)
entry3 = Entry(frame, width=5, validate='all', validatecommand=vcmd)

entry1.pack(side=LEFT)
entry2.pack(side=LEFT)
entry3.pack(side=LEFT)

root.mainloop()
Der Code ermöglicht nur die Eingabe von den Zeichen 0-9.

Ich verstehe mehrere Zeilen in der Methode Callback nicht.
Es geht los mit:

Code: Alles auswählen

if str.isdigit(text) or not text:
- Laut Python Doku übernimmt die Methode isdigit keine Argumente, warum wird hier die Variable Text übergeben ? Müsste es nicht "text.isdigit()" sein ?
- Laut Python Doku gibt isidigit boolean zurück, warum wird dieser Wert dann in einen String umgewandelt ?
- Warum funktioniert diese If-Abfrage, wird dort nicht ein boolen mit einem String (text) verglichen ?

Code: Alles auswählen

text = text if text else 0
- Diese Zeile verstehe ich auch nicht. Ist das eine Variablenzuweisung mit eingebauter If-Abfrage ? Wenn ja warum, die Variable text, kann ja innerhalb der Zeile nicht geändert werden.
Variable text ist gleich variable text wenn variable text sonst 0 ?


Über ein wenig Aufklärung würde ich mich freuen :)
Gruß Kai

Re: Verstehe den Code nicht

Verfasst: Samstag 10. April 2021, 16:09
von __blackjack__
@Kahnbein.Kai: Ja, das sollte eigentlich ``text.isdigit()`` heissen. Da wird aber nichts in eine Zeichenkette umgewandelt. Da steht ``str.isdigit(text)`` und nicht ``str(…)`` was etwas in eine Zeichenkette umwandeln würde. Die rufen da die `isdigit()`-Methode auf der *Klasse* `str` auf und übergeben das `str`-Objekt das geprüft werden soll. ``str.isdigit(text)`` ist letztlich das gleiche wie ``text.isdigit()`` *wenn* `text` vom Typ `str` ist. Denn für normale Methoden gilt immer ``obj.method()`` ist das gleiche wie ``type(obj).method(obj)``.

Beim zeiten Code steht auf der rechten Seite der Zuweisung ein bedingter Ausdruck der Form ``a if condition else b`` der zu `a` ausgwertet wird wenn `condition` wahr ist, sonst zu `b`.

Wenn `text` im boole'schen Kontext wahr ist, dann ergibt das `text`, ansonsten 0. `text` ist eine Zeichenkette, und nur die leere Zeichenkette ist ”unwahr”:

Code: Alles auswählen

In [45]: bool("")                                                               
Out[45]: False

In [46]: bool("anything but the empty string")                                  
Out[46]: True

In [47]: text = ""                                                              

In [48]: text if text else 0                                                    
Out[48]: 0

In [49]: text = "42"                                                            

In [50]: text if text else 0                                                    
Out[50]: '42'
Ist nicht wirklich schön das `text` dann mal an eine Zeichenkette und mal an eine ganze Zahl gebunden werden kann. Sauberer wäre ``text = text if text else "0"``. Wenn man sicher ist, dass `text` keinen gültigen ”unwahren” Wert haben darf der nicht durch "0" ersetzt werden soll, kann man auch ``text = text or "0"`` an der Stelle schreiben.

Re: Verstehe den Code nicht

Verfasst: Samstag 10. April 2021, 17:06
von Sirius3
*-Importe sind schlecht. Wenn die erste wid-Bedingung erfüllt ist, kann die zweite nicht mehr wahr werden, also muß das zweite if ein elif sein.
Alles was eine Funktion braucht, muß sie auch über ihre Argumente bekommen, entry2 und entry2 kommen aber aus dem nichts. Ebenso ent1 wobei da bei dem Namen die 1 keinen Sinn macht, und das ent irgendwie nichts aussagt.
Wenn wid weder das eine noch das andere ist, dann ist n nicht definiert, was dann irgendwann später zu einem NameError führt.

Die Funktion müsste also so aussehen:

Code: Alles auswählen

def callback(entry2, entry3, sumvar, text, wid):
    if not text:
        n = 0
    elif text.isdigit():
        n = int(text)
    else:
        return False
    if wid == str(entry3):
        n += int(entry2.get()) if entry2.get() else 0
    elif wid == str(entry2):
        n += int(entry3.get()) if entry3.get() else 0
    sumvar.set(n)
    return True
Jetzt macht die Funktion aber zwei Dinge auf einmal:
1. Testen, ob der eingegebene Text eine Zahl ist und
2. zwei Zahlen zusammenaddieren.

Das sollte aber zwei Funktionen sein. Die dann zusammen auch viel einfacher sind als die eine:

Code: Alles auswählen

import tkinter as tk
from functools import partial

def validate_int(text):
    return not text or text.isdigit()

def calculate_sum(var1, var2, sumvar, _var, _index, _mode):
    sumvar.set(int(var1.get() or 0) + int(var2.get() or 0))

def main():
    root = tk.Tk()
    sumvar = tk.IntVar(root, 0)
    var1 = tk.StringVar(root)
    var2 = tk.StringVar(root)
    var1.trace_add("write", partial(calculate_sum, var1, var2, sumvar))
    var2.trace_add("write", partial(calculate_sum, var1, var2, sumvar))
    validator = (root.register(validate_int), '%P')
    tk.Entry(root, width=5, textvariable=sumvar).pack(side=tk.LEFT)
    tk.Entry(root, width=5, textvariable=var1, validate='all', validatecommand=validator).pack(side=tk.LEFT)
    tk.Entry(root, width=5, textvariable=var2, validate='all', validatecommand=validator).pack(side=tk.LEFT)
    root.mainloop()
                                       
if __name__ == "__main__":
    main()

Re: Verstehe den Code nicht

Verfasst: Sonntag 25. April 2021, 21:22
von Kahnbein.Kai
Vielen Dank für die ausführlichen Antworten, jetzt wird es mir um einiges klarer.

Das ärgert mich das ich mich so verlesen habe str. und str(...). :cry:

Gruß Kai