Anzeige

 Python Dictionary Wert aus gefragtem Schlüssel ausgeben lassen


#1
Hi,
Ich würde gerne wissen wie ich mit meinem Code nicht mehr den Wert eines zugehörigen Schlüssels nach der Eingabe des Schlüssels ausgegeben bekomme sondern halt umgekehrt
also den Schlüssel nachdem nach dem Wert gefragt wurde. :D

Code:
woerter = {}
fobj = open("Woerterbuch.txt", "r")
for line in fobj:
    line = line.strip()
    zuordnung = line.split(" ")
    woerter[zuordnung[0]] = zuordnung[1]
fobj.close()
while True:
    wort = input("Worteingabe: ")
    if wort in fobj:
            print("Der Wert lautet", woerter[wort])
    elif wort == "stop":
        print("Das Programm wird beendet")
        break
    else:
        print("Der Wert ist unbekannt")
 

Technipion

Erfahrenes Mitglied
#2
Hallo RetroVision,
oh oh, ich nehme mal an du möchtest für ein bestimmtes wort, das in woerter unter einem schlüssel key vorkommt, gerne den Schlüssel key herausfinden. Das ist aus unterschiedlichen Gründen schlecht:
Pythons dict()-Klasse ist im Grunde genommen nichts anderes als eine Hashtabelle. Für eindeutige Schlüssel werden beliebige Python-Referenzen (Zeiger auf Objekte) gespeichert. Aber das ist eine Einbahnstraße, die Abbildung ist nicht bijektiv. Stell dir z.B. vor du speicherst die Farben von Autos, die von einem Autohaus innerhalb einer Woche verkauft wurden, in einem dict:
Python:
car_colors = dict(black=22, silver=13, red=8, blue=3, green=3, white=8)
Wenn dein "Chef" wissen möchte, wie viele grüne Autos verkauft wurden, ist das sehr einfach: car_colors['green']...
Aber: Stell dir vor dein Chef möchte wissen, welche Farbe sich insgesamt 8 mal verkauft hat. Was würdest du antworten? Er könnte rot oder weiß meinen, es ist nicht eindeutig. Ein ähnliches Problem hast du. Am besten erklärst du mal, was genau das Programm tun soll. Dann ließe sich der Code neu designen (und hoffentlich eleganter).

Falls du garantieren kannst, dass die Werte niemals mit den Schlüsseln kollidieren, könntest du sowas versuchen:
Python:
.
.
.
woerter[zuordnung[0]] = zuordnung[1]
woerter[zuordnung[1]] = zuordnung[0] # macht Rückwärtssuche möglich
.
.
.
Alternativ könntest du zwei dicts benutzen:
Python:
.
.
.
woerter_forward[zuordnung[0]] = zuordnung[1]
woerter_backward[zuordnung[1]] = zuordnung[0]
.
.
.
Gutes Design ist das aber natürlich nicht.

Eine Anmerkung noch: In deinem Code in Zeile 7 schließt du mit fobj.close() deine Datei. Ist das Absicht, dass du dann in Zeile 10 mit if wort in fobj in einer geschlossenen Datei liest?

Gruß Technipion
 
#3
Danke für die Antwort.
bin noch Anfänger was Python betrifft und bin gerade bei Dictionaries angekommen.
Ziel war es nur aus einer Datei die Werte eines Schlüssels auszugeben,falls diese existieren und halt auch umgekehrt was ich aber nicht geschissen bekommen habe,wobei ich genau nach deiner dritten Methode gesucht habe (wieso ist das Design kacke? :D)
Und was die erste Methode betrifft ist das ja praktisch das gleiche was ich hatte nur ohne externe Datei die es galt aufzurufen.
1.
Aber: Stell dir vor dein Chef möchte wissen, welche Farbe sich insgesamt 8 mal verkauft hat. Was würdest du antworten?
das war meine Frage :D
wie macht man das bei deinem Beispiel das er dann beide Farben ausgibt?
2.
Für eindeutige Schlüssel werden beliebige Python-Referenzen (Zeiger auf Objekte) gespeichert. Aber das ist eine Einbahnstraße, die Abbildung ist nicht bijektiv.
was meinst du mit beliebigen Python-Referenzen? das es mehrere Schlüssel für einen Wert gibt(falls dieser öfters vorkommt?)
3.Was ist eine bijektive Abildung?

zu deiner Anmerkung.
ist das falsch oder sollte man erst dann die Datei schließen wenn sie nicht mehr verwendet wird, da ich mich nach den Beispielen eines Lehrbuchs richte (Python 3 von Rheinwerk).

Grüße RetroVision
 
Zuletzt bearbeitet:

Technipion

Erfahrenes Mitglied
#4
Hallo RetroVision,
bin noch Anfänger was Python betrifft und bin gerade bei Dictionaries angekommen.
Dann bist du tatsächlich noch ziemlich am Anfang. Da du ziemlich viele Fragen auf einmal gestellt hast (was natürlich gut ist! ;)), versuche ich mal alles Stück für Stück abzuhandeln.
zu deiner Anmerkung.
ist das falsch oder sollte man erst dann die Datei schließen wenn sie nicht mehr verwendet wird, da ich mich nach den Beispielen eines Lehrbuchs richte (Python 3 von Rheinwerk).
Eigentlich ist das falsch. Komisch, dass sich bei Rheinwerk so ein Fehler eingeschlichen hat. Wenn du versuchst in einer geschlossenen Datei zu lesen, sollte dir eigentlich ein ValueError geworfen werden (guckst du hier https://docs.python.org/3/tutorial/inputoutput.html:
After a file object is closed, either by a with statement or by calling f.close(), attempts to use the file object will automatically fail.
).
Hier ist ein Minimalbeispiel, das bei mir genau den oben genannten Fehler erzeugt:
Python:
# Lege Beispieldatei an:
with open('beispieldatei.txt', 'w') as ofile:
    ofile.write('Ein Zeile.\nNoch eine Zeile.')

# Öffne Datei zum Lesen:
with open('beispieldatei.txt', 'r') as ifile:
    for zeile in ifile:
        print(zeile)

# Die Datei ist hier geschlossen, da das with-statement
# ab hier zu Ende ist, und der contextmanager von open()
# die Datei automatisch schließt.

# Versuchen wir trotzdem darin zu lesen:
for zeile in ifile:
    print(zeile)

# Reproduzierbar:
##Traceback (most recent call last):
##  File "/home/privater_pfad/tutorials.de/dateizeugs.py", line 15, in <module>
##    for zeile in ifile:
##ValueError: I/O operation on closed file.

3.Was ist eine bijektive Abildung?
In der Mengenlehre bezeichnet man mit bijektiv Abbildungen die eindeutig umkehrbar sind. Beispiel: Das Dict mit den Autos von oben ist nicht bijektiv. Es gibt zwar für jeden Schlüssel einen eindeutigen Wert, aber nicht für jeden Wert einen eindeutigen Schlüssel. Im Prinzip kann ein Python-Dict bijektiv sein, wenn man eben jedem Wert eindeutig seinen Schlüssel zuordnen kann. Hier ist das obige Dict so abgewandelt, dass es bijektiv ist:
Python:
car_colors = dict(black=22, silver=13, red=8, blue=3, green=5, white=4)
Egal nach welcher Farbe dich dein Chef jetzt fragt, du hast immer eine eindeutige Antwort parat ;)
Aber denk dran: Ein Python-Dict muss nicht bijektiv sein. Grundsätzlich wird nur eindeutigen Schlüsseln jeweils ein beliebiges Python-Object zugeordnet.

was meinst du mit beliebigen Python-Referenzen? das es mehrere Schlüssel für einen Wert gibt(falls dieser öfters vorkommt?)
Nein. Für die Schlüssel gilt: Entweder sie kommen gar nicht im Dict vor, oder es gibt sie genau ein einziges Mal. Jedem Schlüssel ist ein Python-Object zugeordnet.

**********

Kurzer Ausflug in die Welt von Python:

Das am weitesten verbreitete Python ist CPython (auch wenn es noch andere Python-Interpreter gibt). CPython ist - wie der Name schon sagt - in C geschrieben. Wenn ich von einem Python-Object spreche, dann meine ich damit die zugrunde liegende Datenstruktur, die im Code als PyObject_GEDÖNS definiert ist. Wenn du einen Python-Code ausführst, z.B.
Python:
name = 'RetroVision'
dann legt der Python-Interpreter ein "Namensobjekt" name an, das intern eine Referenz (implementiert als C-Pointer) auf ein PyObject bereithält. In diesem Fall auf ein PyStringObject.

Um das Verständnis etwas zu vereinfachen, sagen wir in der Regel "name ist ein Python-Objekt vom Typ str()"...

Prinzipiell können Python-Objekte verschachtelt werden. So kannst du z.B. mit ['Retro', 'Vision'] eine "Liste" von zwei Strings anlegen. Das ist ziemlich mächtig, und lässt dich praktisch jede erdenkliche Datenstruktur schnell und einfach aufbauen, und das alles zur Laufzeit.

**********

Also kurzgesagt: Ein Dict() kann mit Schlüsseln gefüllt werden, wobei jeder Schlüssel nur maximal ein einziges Mal vorkommt, und jedem Schlüssel können beliebige Python-Objekte zugeordnet werden (ein Objekt pro Schlüssel).

wie macht man das bei deinem Beispiel das er dann beide Farben ausgibt?
Mit dem Wissen im Hinterkopf, können wir mein Beispiel umschreiben um uns die Autofarben ausgeben zu lassen. Achtung: Mein Dict() ist nicht bijektiv, also müssen wir etwas mehr Arbeit reinstecken. Hier ist ein Minimalbeispiel:
Python:
car_colors = dict(black=22, silver=13, red=8, blue=3, green=3, white=8)

# Chef fragt: Wie viele silberne Autos wurden verkauft?
print('Antwort:', car_colors['silver'])

# Chef fragt: Welche Farbe hat sich 8 mal verkauft?
antworten = [] # lege Liste an, falls es mehrere Antworten gibt

for key, value in car_colors.items():
    # key enthält die Farbe
    # value enthält die Anzahl
    if value == 8:
        # falls dies ein Treffer ist
        antworten.append(key) # hänge es an die Liste an

print('Antwort:', antworten)

"kacke" geht jetzt vielleicht ein bisschen weit :D

Ich würde eher sagen das Design ist unpraktisch. Ein Dict() wird in der Regel dann verwendet, wenn du in einer großen Menge von Schlüsseln schnell suchen musst. Dafür ist es als Hashtabelle optimiert. Es jedoch rückwärts zu benutzen, macht den Vorteil zunichte. Dafür hast du beim Erstellen eines Dicts einen relativ großen Overhead (wegen Tabellenbildung, etc.). Es gibt also optimalere Strategien. Aber für ein vergleichsweise einfaches Beispiel zur Übung isses denke ich noch okay.
Falls du deinen Code noch optimieren möchtest (gerne auch erst nachdem du dich ein bisschen tiefer in Python eingelesen hast), stehen wir dir natürlich zur Verfügung :p

Gruß Technipion
 
Anzeige
Anzeige