Seite 1 von 1

zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 15:53
von anymagical
Hallo Miteinander,

ich habe mir das Buch "Einstieg in Python" von Galileo Computing gekauft. In diesem Buch werden viele Codebsp. Anhand eines Mathespieles erklärt. Um die Erklärungen etwas nachcoden zu können wollte ich ein ähnliches Spiel benutzen. In diesem soll der Benutzer nach dem Wert eines Buchstaben gefragt werden, welcher daraufhin den richtigen Wert dazu eingibt. Wie muss der Code aussehen damit ein zufälliges Item aus dem Dict gefragt wird statt stur der Reihenfolge.

Code: Alles auswählen

import random
Werte={"A":1,"B":2,"C":3,"D":4,"E":5,"F":6,"G":7,"H":8,"I":9,"J":10}
werte=Werte.items()
for buchstabe, zahl in random.randrange(int(werte)+1):
    print (buchstabe)
    eingabe=input()
    if eingabe==zahl:
        print ("richtig")
    else:
        print ("falsch")
gibt einen "TypeError: int() argument must be a string or a number, not 'dict_items'" Fehler aus. Was wohl darauf schließen lässt das in der Variablen "werte" die Items und nicht die Anzahl deser gespeichert wird oder?

Mit freundlichen Grüßen
Anymagical

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 16:20
von deets
ja. ein einfaches print von werte vor der for-schleife erzaehlt dir das.

schau dir mal random.shuffle an - das sollte eigentlich klappen. unter umstaenden musst du dazu noch

werte = list(werte)

machen, falls dict_items ein typ ist, mit dem random.shuffle nicht klarkommt.

oh, und das buch wird hier uebrigens allgemein als eher schlecht angesehen - die autoren haben nicht wirklich viel ahung von python.

http://www.marc.rintsch.de/python_openbook.html

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 17:05
von Hyperion
Ich würde vor allem vorschlagen, an Stelle des Dictionaries eine Liste von Tupeln zu nutzen. Den Schlüssel benutzt Du ja gar nicht wirklich - wozu also das Dictionary?

Code: Alles auswählen

In [33]: list(enumerate("ABCDEFGHIJ"))
Out[33]: 
[(0, 'A'),
 (1, 'B'),
 (2, 'C'),
 (3, 'D'),
 (4, 'E'),
 (5, 'F'),
 (6, 'G'),
 (7, 'H'),
 (8, 'I'),
 (9, 'J')]
Das kannst Du dann prima mischen:

Code: Alles auswählen

In [34]: pairs = list(enumerate("ABCDEFGHIJ"))

In [35]: random.shuffle(pairs)

In [36]: pairs
Out[36]: 
[(9, 'J'),
 (4, 'E'),
 (0, 'A'),
 (6, 'G'),
 (2, 'C'),
 (3, 'D'),
 (7, 'H'),
 (1, 'B'),
 (8, 'I'),
 (5, 'F')]
Hoffe das war nicht zu viel Spoiler ;-)

Edit: Ok, wenn man bei "1" anfangen will, dann muss man bei `enumerate` den Aufruf so ändern: `enumerate("ABCDEFGHIJ", 1)`.

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 17:15
von anymagical
Vielen Dank!

hat wunderbar geklappt mit random.shuffle.

Ich besitze das Buch "Einstieg in Python" nicht "Das Umfassende Handbuch" oder macht das keinen Unterschied da beide von GC sind? Sollte ich lieber zu A Byte of Python greifen?

Code: Alles auswählen

import random
Werte={"A":1,"B":2,"C":3,"D":4,"E":5,"F":6,"G":7,"H":8,"I":9,"J":10}
werte=Werte.items()
Bst=list(werte)
random.shuffle(Bst)
del Bst[0:7]
for buchstabe, zahl in Bst:
        print (buchstabe)
        eingabe=int(input())
        if eingabe==zahl:
            print ("richtig")
        else:
            print ("falsch")
Ich habe jetzt auf weniger elegante Art und Weise erreicht das nur 3 Keys abgefragt werden. WIe wäre dies anderst gelöst worden?


@ Hyperion
verändern sich dann nicht die Werte auch? Also bleibt A=1 und C=3 ...?

Nachtrag\\
Gibt es irgendwo Aufgaben welche man scripten kann und auch die Lösungen dazu sieht?
z.B. Erstellen sie ein Script welches Besucher zählt die an einer Lichtschranke vorbei gehen.

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 17:33
von BlackJack
@anymagical: Das hätte man mit `itertools.islice()` oder direkt mit „slicing” auf der Liste lösen können. Also nicht 7 Elemente aus der Liste löschen, sondern eine neue Liste mit drei Elementen aus der alten erstellen.

Die Namen sind teilweise unschön. `Werte` und `werte` sind ziemlich ähnlich. Und bei Python verwendet man Namen die mit einem Grossbuchstaben anfangen üblicherweise für Klassen. `Bst` ist ein Name der nicht gerade beim Verständnis hilft. Man muss auch nicht jeden Zwischenwert an einen eigenen Namen binden.

Zu Deiner Frage an Hyperion: Es geht schneller so etwas auszuprobieren als eine Frage zu posten und auf Antwort zu warten. Ausserdem siehst Du doch in seinem Beitrag was passiert!?

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 17:40
von Hyperion
anymagical hat geschrieben: Ich besitze das Buch "Einstieg in Python" nicht "Das Umfassende Handbuch" oder macht das keinen Unterschied da beide von GC sind? Sollte ich lieber zu A Byte of Python greifen?
Wenn der / die Autor(en) immer noch gleich sind, dann hat sich nur etwas geändert, wenn sie dazu gelernt haben ;-) Evtl. kann dazu noch jemand etwas konkretes sagen?

Ich würde Dir aus dem Bauch heraus dennoch zu etwas hier etablierten raten, wie eben ABoP. Ansonsten wird gerne noch "Learn python the hard way" empfohlen.

Wozu dient diese Zeile?

Code: Alles auswählen

Bst=list(werte)
Du kannst ja mal überprüfen, was `Werte.items()` als Typen zurückliefert (mittels `type()`). Und dann überlege mal, ob Du diesen Aufruf noch brauchst.
anymagical hat geschrieben:

Code: Alles auswählen

del Bst[0:7]
Ich habe jetzt auf weniger elegante Art und Weise erreicht das nur 3 Keys abgefragt werden. WIe wäre dies anderst gelöst worden?
In der Tat ist das unschön. Damit veränderst Du ja die gesamte Liste unwiederbringlich... Du suchst `random.sample`. Damit kannst Du eine beliebige Anzahl an einzigartigen Elementen aus Deiner Ursprungsliste herausholen. Lies Dir das mal in der Doku durch. Die Doku ist *unverzichtbar*. Am besten Du lernst möglichst früh, dort nach Funktionalitäten zu suchen :-)
anymagical hat geschrieben: @ Hyperion
verändern sich dann nicht die Werte auch? Also bleibt A=1 und C=3 ...?
Ein einfacher Blick auf meine geposteten Ausgaben hätte Dir das beantworten können ;-) Zudem stellt sich die Frage: Wieso sollte sich da etwas ändern? `random.shuffle` verändert die Reihenfolge von Objekten in einer Liste - nicht deren Beschaffenheit! Ein Tupel ist zudem nicht änderbar; wenn dann muss man ein neues generieren.

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 18:01
von /me
Die Liste mit den Zuordnungen könntest du dynamisch erstellen. Dazu sehe ich zwei verschiedene Möglichkeiten.

Variante 1 arbeitet mit den zueinander inversen Funktionen ord() und chr().

Code: Alles auswählen

>>> ord('A')
65
>>> chr(66)
'B'
Mit dem Wissen kannst du deine Buchstabenliste dynamisch aufbauen.

Code: Alles auswählen

characters = []
for key in range(10):
    char = chr(key + ord('A'))
    characters.append((char, key + 1))

print(characters)
Den ganzen Code kann man auch mit einer list comprehension darstellen.

Code: Alles auswählen

characters = [(chr(key + ord('A')), key + 1) for key in range(10)]
Variante 2 für die Erstellung der Liste wäre die Verwendung von string.ascii_uppercase

Code: Alles auswählen

import string
characters = [(char, ord(char) - ord('A') + 1) for char in string.ascii_uppercase[:10]]

Und dann setzt man wie folgt fort

Code: Alles auswählen

random.shuffle(characters)
for char, key in characters[:3]:
    print(char)
    number = int(input())
    if number == key:
        print("richtig!")
    else:
        print("falsch!")
Probiere es aus und streu dir am besten ein print immer da ein, wo du den Programmablauf genauer verfolgen möchtest.

Der nächste Schritt wäre dann eine Fehlerbehandlung bei ungültigen Eingaben.

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 18:09
von Hyperion
/me hat geschrieben:Die Liste mit den Zuordnungen könntest du dynamisch erstellen. Dazu sehe ich zwei verschiedene Möglichkeiten.
Du hast die von mir vorgeschlagene vergessen:

Code: Alles auswählen

list(enumerate("ABCDEFGHIJ"), 1)
;-)

Die kann man ja auch prima bei 65 starten lassen oder auch mit `string.ascii_uppercase` kombinieren.

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 18:13
von anymagical
@ BlackJack

Das üblicherweise Großbuchstaben für Klassen verwendet werden wusste ich nicht.
Das die Werte unglücklich gewählt sind ist mir auch schon aufgefallen.

Mit itertools.islice sieht das ganze schon besser aus!


@ Hyperion

Na ist ein ganz anderer Autor. Werde mir deine Buchempfehlung die Tage mal ansehen.

Ich habe bei deiner Möglichkeit nicht genau hingesehen, und dachte da würde sich etwas ändern, aber es bleibt ja alles beim alten.

Die Zeile(n) ist/sind wirklich schrecklich untötig. Über einen wahnsinns Umweg erreiche ich das was du direkt von Anfang an hast :D

Re: zufälliges Item eines dict mit einem input abgleichen

Verfasst: Montag 2. April 2012, 19:21
von /me
Hyperion hat geschrieben:Du hast die von mir vorgeschlagene vergessen:

Code: Alles auswählen

list(enumerate("ABCDEFGHIJ"), 1)
Ähmmmm ... ich dachte ich könnte mal noch was Neues bringen, sonst lernt der Fragesteller ja nichts. :mrgreen: