Funktionsauswahl per Random

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
Robokopp
User
Beiträge: 64
Registriert: Mittwoch 3. November 2010, 12:04

Hallo

ich möchte ein Quiz programmieren, wobei dem die Fragen und Antworten wegen der Übersichtlichkeit in einer separaten Datei liegen(fragenkatalog.py).

mein ursprünglicher Plan war es, jede Frage mit samt ihren Antworten in jeweils eine eigene Funktion unterzubringen (def frage1(self):, def frage2(self): usw), die ich dann per Random aufrufe, doch leider klappt das nicht so wie ich es mir vorstelle.

Das sieht ca so aus:

Code: Alles auswählen

fragennummer=random.randint(1,20)
fragenkatalog.frage+str(fragennummer)
print frage
print antwort

Fragenkatalog:

Code: Alles auswählen

def frage1(self):
frage="Dies ist die erste Frage"
antwort="Dies ist die erste Antwort"
Die Ausgabe ist hierbei allerdings: Dies ist die erste Frage1


Wie bekomme ich es hin, dass genau die Funktion aufgerufen und die Variable übergeben wird, die zu der Nummer des Zufallsgenerators passt?

MfG
BlackJack

@Robokopp: Bei dem Fragenkatalog gibt es einen Syntaxfehler, weil die Einrückung nicht stimmt.

Das kann so auch nicht wirklich funktionieren, denn wenn die Einrückung stimmen würde, dann hättest Du eine Funktion, die einfach nur zwei Zeichenketten an lokale Namen binden würde und das war es dann auch schon. Wenn Du die Aufrufst, passiert rein gar nichts.

Was sollte das `self`-Argument eigentlich bedeuten?

Letztlich willst Du die Fragen und Antworten auch gar nicht als Funktionen haben. Funktionen *tun* etwas. Fragen und Antworten sind einfach nur passive Daten. Steck die in eine passende Datenstruktur. Das jeweilige Frage/Antwort-Paar in ein Tupel und die Tupel dann in eine Liste. Aus der kannst Du dann ganz einfach mit `random.choice()` ein Tupel zufällig auswählen. Wenn man anfängt Namen durch zu nummerieren, dann will man in den meisten Fällen eigentlich eine Liste verwenden.

Falls mehrere Fragen hintereinander gestellt werden sollen, dann wäre es vielleicht besser die Tupel zu mischen (`random.shuffle()`) und dann der Reihe nach abzuarbeiten. So hat man keine Frage doppelt.
Robokopp
User
Beiträge: 64
Registriert: Mittwoch 3. November 2010, 12:04

Sry, die Einrückung stimmt nur hier im Forum nicht.

Programmiere in PyQt, deswegen self
Ja richtig, ich will damit bewirken, dass die Strings an die Variablen gebunden werden.Diese greife ich dann in main.py ab und gebe sie an QTextBrowser weiter und die Antworten an QPushButtons.

Okay, das mit den Tupeln klingt gut, aber ich muss mein Programm wissen lassen, welche der Antworten richtig ist....deswegen benötige ich doch eigentlich Texte, die an Variablen gebunden sind oder liege ich da falsch?
falscheantwort1=""
falscheantwort2=""
falscheantwort3=""
richtigeantwort=""
BlackJack

@Robokopp: Du programmierst nicht in PyQt sondern in Python. Und selbst wenn Du Qt als GUI-Toolkit verwendest ist das kein Grund für das `self` beziehungsweise keine vernünftige Antwort auf die Frage warum Du eine Funktion hast, die ein Argument mit dem Namen `self` entgegen nimmt. Was sollte denn beim Aufruf der Funktion an dieses Argument gebunden werden?

Wenn das richtig eingerückt ist, dann werden die Zeichenketten wie gesagt einfach nur an lokale Namen innerhalb der Funktion gebunden. Dann kann es aber nicht zu der Ausgabe kommen, die Du angeblich hast, denn dann sind diese Namen nicht auf Modulebene und `fragenkatalog.frage` würde zu einem `AttributeError` führen. Also entweder stimmt der Quelltext nicht, den Du zeigst, oder die Ausgabe die Du mit dem gezeigten Quelltext bekommst, kann so nicht sein.

Wenn Du mehrere Antworten hast, dann könntest Du die auch wieder in einem Tupel oder einer Liste zusammen fassen und die erste sollte immer die richtige sein. Bevor Du die Antwortmöglichkeiten dem Benutzer anzeigst, kannst Du sie auch mischen, damit er nicht einfach immer nur die erste Möglichkeit auswählen muss.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Das mit dem `self` finde ich an dieser Stelle so oder so komisch. Denn wenn man "ordentlich" programmieren will, dann sollte man Logik und GUI voneinander trennen. Idealerweise ruft man daher in der gesonderten Datei, welche die Anweisungen für die grafische Benutzeroberfläche enthält, fast ausschließlich PyQt-bezogene Funktionen auf (wohl eher Methoden). Nur an relativ wenigen Stellen (von irgendwo her muss der Input ja kommen) greift man auf die interne Logik zurück, welche in ein anderes Modul ausgelagert worden ist. Dort hat man sich entsprechend ein eigenes Interface erstellt, von dem man passende Funktion oder Klassen benutzen kann. :)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Es ist keine gute Idee, Funktionsnamen aus Strings zusammenbauen zu wollen und diese dann im Modul zu suchen. Warum nicht besser so?

Code: Alles auswählen

class Question:
    def __init__(self, question, answer):
        self.question, self.answer = question, answer

questions = [
    Question("Wieviele Stunden hat der Tag", "24"),
    Question("Wieviele Tage hat die Woche?", "7"),
    Question("Wieviele Monate hat das Jahr?", "12"),
]

question = random.choice(questions)

print(question.question)
print(question.answer)
Stefan
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Oder gleich so:

Code: Alles auswählen

>>> from collections import namedtuple
>>> Question = namedtuple('Question', ['question', 'answer'])
>>> question = Question('Wieviele Stunden hat der Tag?', '24')
>>> question.question
'Wieviele Stunden hat der Tag?'
>>> question.answer
'24'
>>> question
Question(question='Wieviele Stunden hat der Tag?', answer='24')
Robokopp
User
Beiträge: 64
Registriert: Mittwoch 3. November 2010, 12:04

Ja das mit dem self ist im Prinzip quatsch, das sehe ich ein^^
@Stefan, Vielen Dank, das hat mir unheimlich weitergeholfen =)
Antworten