Redundanzen vermeiden

Code-Stücke können hier veröffentlicht werden.
Antworten
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

Hallo Alle,

ich brauche mal einen Arschtritt, weil ich nicht drauf komme wie ich sinnvoll, die Wiederholung der Funktion eliminiere.

Code: Alles auswählen

    def control1(self):
        if not self.lock:
            if self.right_ans != self.a1:
                self.answer_button1.configure(bg="red")
            else:
                self.right += 1
            self.right_ans_button.configure(bg="green")
            self.lock = True
Das Script funktioniert so, aber es sind noch einige Schönheitsfehler drin, also erstmal diesen.
Die Funktion soll das Ergebnis kontrollieren. Leider funktioniert das nur korrekt, wenn ich die Funktion in 4 verschiedenen Ausführungen
implementiere. Das geht mit Sicherheit besser und eleganter. Kann wer was dazu sagen?

Danke


hier nochmal der ganze code zum besseren Verständnis

Code: Alles auswählen

from tkinter import Button, Label, Tk, Text, END
import random

root = Tk()
root.title("Quizzz")
root.geometry("800x700")

questions = [["Wessen Mutter schwitzt nicht beim kacken?", "Merkels Mom", "Merkel selbst", "Söders Mom", "Chuck Norris Mom"],
             ["Wer oder was ist ein 'Spahn?", "Patient Zero", "Füllmaterial für Hamsterkäfig", "berühmte Trümmerfrau", " aktueller Gesundheitsminister"]]


def clear():
    line = root.grid_slaves()
    for n in line:
        n.destroy()

class Quiz:
    def __init__(self,quest):
        clear()
        self.questions = []
        for n in quest:
            self.questions.append(n)
        self.a1 = ""
        self.a2 = ""
        self.a3 = ""
        self.a4 = ""
        self.right_ans = ""

        self.right_ans_button = Button(root, text="", font=("Arial", 14))
        self.answer_button1 = Button(root, text="", font=("Arial", 14))
        self.answer_button2 = Button(root, text="", font=("Arial", 14))
        self.answer_button3 = Button(root, text="", font=("Arial", 14))
        self.answer_button4 = Button(root, text="", font=("Arial", 14))
        self.next = Button(root, text="nächste Frage", font=("Arial", 14), command=self.question)
        self.lock_button = Button(root, text="bestätigen", font=("Arial", 14), command=self.lock_it)

        self.lock = False
        self.right = 0
        self.number = 0
        self.Max = 2  # input button erstellen
        self.question()

    def lock_it(self):
        pass          # lock funktion schreiben

    def question(self):
        self.next.grid(column=0, row=6, pady=5)
        self.lock_button.grid(column=0, row=5, pady=5)
        if len(self.questions) > 0 and self.number < self.Max:
            self.number += 1
            self.lock = False
            rand_num = random.randint(0, len(self.questions) - 1)
            quest_line = self.questions[rand_num][0]
            self.right_ans = self.questions[rand_num][-1]
            answers = []
            for i in range(1,5):
                answers.append(self.questions[rand_num][i])
            random.shuffle(answers)

            self.a1 = answers[0]
            self.a2 = answers[1]
            self.a3 = answers[2]
            self.a4 = answers[3]

            the_question = Text(root, font=("Arial", 14), width=40, height=2)
            the_question.insert(END, quest_line)
            the_question.grid(column=0, row=0, padx=80, pady=(75, 0))

            self.answer_button1 = Button(root, text=self.a1, font=("Arial", 14), width=39, command = self.control1)
            self.answer_button2 = Button(root, text=self.a2, font=("Arial", 14), width=39, command = self.control2)
            self.answer_button3 = Button(root, text=self.a3, font=("Arial", 14), width=39, command = self.control3)
            self.answer_button4 = Button(root, text=self.a4, font=("Arial", 14), width=39, command = self.control4)

            self.answer_button1.grid(column=0, row=1, pady=5)
            self.answer_button2.grid(column=0, row=2, pady=5)
            self.answer_button3.grid(column=0, row=3, pady=5)
            self.answer_button4.grid(column=0, row=4, pady=5)

            if self.a1 == self.right_ans:
                self.right_ans_button = self.answer_button1
            elif self.a2 == self.right_ans:
                self.right_ans_button = self.answer_button2
            elif self.a3 == self.right_ans:
                self.right_ans_button = self.answer_button3
            elif self.a4 == self.right_ans:
                self.right_ans_button = self.answer_button4
            self.questions.pop(rand_num)
        else:
            clear()
            lb = Label(root, text="Du hast " + str(self.right) + " von " + str(self.Max) + " Fragen richtig beantwortet!", font=("Arial", 14))
            lb.grid(column=0,row=0,padx=120,pady=(170,15))
            to_menu = Button(root, text="zurück zum Start", font=("Arial", 14), command=create_menu)
            to_menu.grid(column=0,row=1)

    def control1(self):
        if not self.lock:
            if self.right_ans != self.a1:
                self.answer_button1.configure(bg="red")
            else:
                self.right += 1
            self.right_ans_button.configure(bg="green")
            self.lock = True

    def control2(self):
        if not self.lock:
            if self.right_ans != self.a2:
                self.answer_button2.configure(bg="red")
            else:
                self.right += 1
            self.right_ans_button.configure(bg="green")
            self.lock = True

    def control3(self):
        if not self.lock:
            if self.right_ans != self.a3:
                self.answer_button3.configure(bg="red")
            else:
                self.right += 1
            self.right_ans_button.configure(bg="green")
            self.lock = True

    def control4(self):
        if not self.lock:
            if self.right_ans != self.a4:
                self.answer_button4.configure(bg="red")
            else:
                self.right += 1
            self.right_ans_button.configure(bg="green")
            self.lock = True



class Menu:
    def __init__(self):
        clear()
        self.Quiz = Button(root, text="das Quiz beginnen", font=("Arial", 14), command=create_quiz, width=15, height=3)
        self.Quiz.grid(column=0,row=0,padx=275,pady=200)

def create_menu():
   return Menu()

def create_quiz():
  return Quiz(questions)

create_menu()
root.mainloop()
Cours, camarade, le vieux monde est derrière toi!
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Lou Cyphr3: Du musst halt schauen wie die sich unterscheiden. Soweit ich das sehe durch den Antwort-Button. Der darf nicht fest in der Methode stehen, sondern muss als Argument übergeben werden. `functools.partial()` ist das was man da üblicherweise nimmt um aus einer Funktion/Methode eine neue Funktion zu erstellen bei der Argumente an Werte gebunden sind.

Als nächstes solltest Du die ganzen nummerierten Namen loswerden und diese Werte in Listen stecken.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

@__blackjack__
cool danke das seh ich mir Mal an.

Das mit den Listen kann ich mir gerade nur bedingt vorstellen. Kannst du mir einen kleines Beispiel geben?
Cours, camarade, le vieux monde est derrière toi!
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Code: Alles auswählen

liste_von_dingen = [Ding(), AnderesDing()]
for ding in liste_von_dingen:
       ding.machwas()
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

__deets__ hat geschrieben: Samstag 24. Oktober 2020, 16:37

Code: Alles auswählen

liste_von_dingen = [Ding(), AnderesDing()]
for ding in liste_von_dingen:
       ding.machwas()

okay gut, aber wie kann ich die liste dazu benutzen um nummerierte Namen und dummy's zu vermeiden?

Code: Alles auswählen

	self.a1 = ""
        self.a2 = ""
        self.a3 = ""
        self.a4 = ""
        
[...]
        
        self.answer_button1 = Button(root, text="", font=("Arial", 14))
        self.answer_button2 = Button(root, text="", font=("Arial", 14))
        self.answer_button3 = Button(root, text="", font=("Arial", 14))
        self.answer_button4 = Button(root, text="", font=("Arial", 14))
Cours, camarade, le vieux monde est derrière toi!
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Indem du

self.answer_buttons = [Button(...), Button(...), ...]

machst.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Und als nächster Schritt dann da wo es Sinn macht, Schleifen verwendest um die Listen zu erstellen. Also in dem Beispiel würde man ja nicht viermal den gleichen `Button`-Aufruf schreiben wollen, sondern eine Schleife schreiben, die das macht. Ein Methodenaufruf zum anordnen des Widgets (`pack()` oder `grid()`) gehört da ja auch noch dazu der für jedes dieser Objekt gleich, oder fast gleich ist.

Edit: Und Dummywerte sollte man in der Regel ganz weg lassen. Wenn Du eine Liste mit leeren Zeichenketten hast die aber nie irgendwo benutzt werden, solltest Du diese Liste mit den leeren Zeichenketten auch nicht erstellen.

Falls man irgendwo etwas hat, wo man eine Definition braucht, beispielsweise weil das Attribut in der `__init__()` angelegt werden soll, wo man aber zu dem Zeitpunkt noch keinen Wert dafür hat, dann ist der dafür vorgesehene Wert, der dem Leser sagt, hier gibt es (noch) keinen Wert: `None`.
Zuletzt geändert von __blackjack__ am Samstag 24. Oktober 2020, 17:32, insgesamt 1-mal geändert.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

okay, ich versuchs mal. danke schön!
Cours, camarade, le vieux monde est derrière toi!
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

@__blackjack__

ich bin gerade noch am rum probieren und frage mich ob du das so meinst oder ich auf dem Holzweg bin.

Ich bekomme eine Ausgabe, die mich glauben lässt das 3 Buttons erstellt wurden.

Code: Alles auswählen

from tkinter import Button

root = None
answer_button = Button(root, text="", font=("Arial", 14), width=39 )

buttons = []

for button in range(0,3):
    buttons.append(answer_button)
    
    
print(buttons)    
   
Ausgabe

Code: Alles auswählen

[<tkinter.Button object .!button>, <tkinter.Button object .!button>, <tkinter.Button object .!button>]

Process finished with exit code 0
Cours, camarade, le vieux monde est derrière toi!
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

In welcher Zeile erstellst du denn Buttons? Und wie viele sind das?
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

na ich fülle mit der for Schleife ( die 3 mal läuft) besser wäre wohl in range(1, 4), weil sie eigentlich 4 Buttons rein schreiben soll, die Liste mit 4 answer_button
oder nicht?
Cours, camarade, le vieux monde est derrière toi!
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Beantworte die Frage präzise: in welcher Zeile wird der Button erzeugt?
Und welchen Button packst Du dann drei mal in eine Liste?
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

@sirius

Der Button wird in Zeile 4 ( answer_button...) erzeugt und genau diesen pack ich in die Liste.
Ich gehe davon aus, jetzt 3 Exemplare von Button in der Liste zu haben oder irre ich hier?
Ich bin mir ziemlich sicher, dass du das gefragte selbst weißt, weiß allerdings nicht auf was du hinaus willst..
Cours, camarade, le vieux monde est derrière toi!
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du dreimal dasselbe Ding in eine Liste packst, warum erwartest du dann, dass da dreimal was unterschiedliches drin ist? Und was ist der Unterschied zu deinem Vorgehen und dem, dass ich schon Samstag skizziert habe?
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

@ deets

der Unterschied zu dem was du Samstag skizziert hast, ist das was __ Blackjack__ geschrieben hat. Ich wollte eine Schleife benutzen um die Liste zu erstellen. Letztlich ist
der Button ja auch 3x Mal das gleiche. Es ging ja darum die Redundanz zu vermeiden, was ich nicht tue indem ich das gleiche Objekt mehrfach händisch in die Liste schreibe oder?
Cours, camarade, le vieux monde est derrière toi!
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Du hast aber nicht 3x den gleichen Button sondern 3x den selben Button in der Liste.
Und wenn du 3x den selben Button hast, dann kannst du dir die Liste auch sparen.

Wenn wir uns beide jeweils ein identisches Auto kaufen und damit jeweils zu unserem gemeinsamen Arbeitgeber fahren, dann werden unsere Kollegen feststellen, dass wir das gleiche Auto fahren.
Wenn wir beide eine Fahrgemeinschaft bilden, dann werden sie bemerken, dass wir im selben Auto ankommen.

Das ist hier sehr wichtig. Ich kann das selbe Objekt in 20 Listen stecken - oder in 20 verschiedene. Aber es bleibt ein Objekt. Es wird nicht magisch kopiert.
Du möchtest aber 3 verschiedene Buttons haben.
Zuletzt geändert von sparrow am Mittwoch 28. Oktober 2020, 11:38, insgesamt 1-mal geändert.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Du sollst ja nicht das gleiche Objekt mehrfach in die Liste schreiben, du sollst drei verschiedene Instanzen des Buttons in die Liste schreiben, also es soll drei mal ein Button erzeugt werden. Es soll nicht einmal ein Button erzeugt werden und drei mal in eine Liste gepackt werden.

Vielleicht hilft dir das Snippet hier:

So machst du es im Moment:

Code: Alles auswählen

import random

random_number = random.randint(0,9)

numbers = []

for i in range(0,3):
    numbers.append(random_number)

print(numbers)
So sollte es sein:

Code: Alles auswählen

import random

numbers = []
for i in range(0,3):
    random_number = random.randint(0,9)
    numbers.append(random_number)

print(numbers)
Das kann mann dann noch kürzer als List comprehension schreiben:

Code: Alles auswählen

import random

numbers = [random.randint(0,9) for i in range(0,3)]

print(numbers)
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

okay dann macht natürlich auch der hint von sirius3 mehr Sinn

also sollte dann das zielführender sein, ja?

Code: Alles auswählen

from tkinter import Button

root = None

buttons = []

for button in range(0,3):
    answer_button = Button(root, text="", font=("Arial", 14), width=39 )
    buttons.append(answer_button)
        
print(buttons)
Cours, camarade, le vieux monde est derrière toi!
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Jupp. Wenn man es als reines Beispiel betrachtet. Anmerkungen zu Code auf Modul Ebene etc findest du ja vielfach.
Lou Cyphr3
User
Beiträge: 59
Registriert: Donnerstag 6. Juli 2017, 00:04

sehr schön. vielen dank an alle!
Cours, camarade, le vieux monde est derrière toi!
Antworten