1.4.7. Słownik słówek

ZADANIE: Przygotuj słownik zawierający obce wyrazy oraz ich możliwe znaczenia. Pobierz od użytkownika dane w formacie: wyraz obcy: znaczenie1, znaczenie2, ... itd. Pobieranie danych kończy wpisanie słowa “koniec”. Podane dane zapisz w pliku. Użytkownik powinien mieć możliwość dodawania nowych i zmieniania zapisanych danych.

POJĘCIA: słownik, odczyt i zapis plików, formatowanie napisów, format csv.

Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import os  # moduł udostępniający funkcję isfile()

slownik = {}  # pusty słownik
sPlik = "slownik.txt"  # nazwa pliku zawierającego wyrazy i ich tłumaczenia


def otworz(plik):
    if os.path.isfile(sPlik):  # czy istnieje plik słownika?
        with open(sPlik, "r") as pliktxt:  # otwórz plik do odczytu
            for line in pliktxt:  # przeglądamy kolejne linie
                # rozbijamy linię na wyraz obcy i tłumaczenia
                t = line.split(":")
                wobcy = t[0]
                # usuwamy znaki nowych linii
                znaczenia = t[1].replace("\n", "")
                znaczenia = znaczenia.split(",")  # tworzymy listę znaczeń
                # dodajemy do słownika wyrazy obce i ich znaczenia
                slownik[wobcy] = znaczenia
    return len(slownik)  # zwracamy ilość elementów w słowniku


def zapisz(slownik):
    # otwieramy plik do zapisu, istniejący plik zostanie nadpisany(!)
    pliktxt = open(sPlik, "w")
    for wobcy in slownik:
        # "sklejamy" znaczenia przecinkami w jeden napis
        znaczenia = ",".join(slownik[wobcy])
        # wyraz_obcy:znaczenie1,znaczenie2,...
        linia = ":".join([wobcy, znaczenia])
        pliktxt.write(linia)  # zapisujemy w pliku kolejne linie
        # można też tak:
        # print(linia, file=pliktxt)
    pliktxt.close()  # zamykamy plik


def oczysc(str):
    str = str.strip()  # usuń początkowe lub końcowe białe znaki
    str = str.lower()  # zmień na małe litery
    return str


def main(args):
    print("""Podaj dane w formacie:
    wyraz obcy: znaczenie1, znaczenie2
    Aby zakończyć wprowadzanie danych, podaj 0.
    """)

    # wobce = set() # pusty zbiór wyrazów obcych
    # zmienna oznaczająca, że użytkownik uzupełnił lub zmienił słownik
    nowy = False
    ileWyrazow = otworz(sPlik)
    print("Wpisów w bazie:", ileWyrazow)

    # główna pętla programu
    while True:
        dane = input("Podaj dane: ")
        t = dane.split(":")
        wobcy = t[0].strip().lower()  # robimy to samo, co funkcja oczysc()
        if wobcy == 'koniec':
            break
        elif dane.count(":") == 1:  # sprawdzamy poprawność danych
            if wobcy in slownik:
                print("Wyraz", wobcy, " i jego znaczenia są już w słowniku.")
                op = input("Zastąpić wpis (t/n)? ")
            # czy wyrazu nie ma w słowniku? a może chcemy go zastąpić?
            if wobcy not in slownik or op == "t":
                znaczenia = t[1].split(",")  # znaczenia zapisujemy w liście
                znaczenia = list(map(oczysc, znaczenia))  # oczyszczamy listę
                slownik[wobcy] = znaczenia
                nowy = True
        else:
            print("Błędny format!")

    if nowy:
        zapisz(slownik)

    print(slownik)

    print("=" * 50)
    print("{0: <15}{1: <40}".format("Wyraz obcy", "Znaczenia"))
    print("=" * 50)
    for wobcy in slownik:
        print("{0: <15}{1: <40}".format(wobcy, ",".join(slownik[wobcy])))
    return 0


if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

Słownik (zob. słownik) to struktura nieuporządkowanych danych w formacie klucz:wartość. Kluczami są najczęściej napisy, które wskazują na wartości dowolnego typu, np. inne napisy, liczby, listy, tuple itd. W programie wykorzystujemy słownik, którego kluczami są wyrazy obce, natomiast wartościami są listy możliwych znaczeń.

Operacje na słowniku:

  • slownik = { 'go':['iść','pojechać'] } – utworzenie 1-elementowego słownika;
  • slownik['make'] = ['robić','marka'] – dodanie nowego elementu;
  • slownik['go'] – odczyt elementu.

Aby zilustrować niektóre operacje na napisach i listach, elementy słownika zapisywać będziemy do pliku w formacie wyraz_obcy:znaczenie1,znaczeni2,.... Funkcja otworz() przekształca format pliku na słownik, a funkcja zapisz() słownik na format pliku.

Operacje na plikach:

  • os.path.isfile(plik) – sprawdzenie, czy istnieje podany plik;
  • open(plik, "w") – otwarcie pliku w podanym trybie: “r” – odczyt(domyślny), “w” – zapis, “a” – dopisywanie;
  • with open(plik) as zmienna: – otwarcie pliku w instrukcji with ... as ... zapewnia obsługę błędów, dba o zamknięcie pliku i udostępnia jego zawartość w zmiennej;
  • for linia in zmienna: – pętla, która odczytuje kolejne linie pliku;
  • plik.write(tresc) – zapisuje do pliku podaną treść;
  • plik.close() – zamyka plik.

Operacje na napisach:

  • .split(":") – zwraca listę części napisu wydzielone według podanego znaku;
  • ",".join(lista) – zwraca elementy listy połączone podanym znakiem (w tym wypadku przecinkiem);
  • .lower() – zamienia znaki na małe litery;
  • .strip() – usuwa początkowe i końcowe białe znaki (spacje, tabulatory);
  • .replace("co","czym") – zastępuje w ciągu wszystkie wystąpienia co – czym;
  • .count(znak) – zwraca ilość wystąpień znaku w napisie.

W pętli głównej programu dane pobrane w formacie wyraz_obcy:znaczenie1,znaczeni2,... rozbijamy na wyraz obcy i jego znaczenia, które zapisujemy w liście t. Wszystkie elementy oczyszczamy, tj. zamieniamy na małe litery i usuwamy białe znaki. Funkcja map(oczysc, znaczenia) pozwala zastosować podaną jako pierwszy argument funkcję oczysc do wszystkich elementów listy znaczenia podanej jako argument drugi. Instrukcja list() przekształca zwrócony przez funkcję map() obiekt z powrotem na listę.

Formatowanie napisów

Metoda napisów format() pozwala na drukowanie przekazanych jej jako argumentów danych zgodnie z ciągami formatującymi umieszczanymi w nawiasach klamrowych w napisie, np. {0: <15}{1: <40}. Pierwsza cyfra wskazuje, do którego z kolejnych argumentów metody format() odnosi się ciąg formatujący. Po dwukropku podajemy znak wypełnienia (” ” – spacja), symbol “<” oznacza wyrównanie do lewej, a ostatnia cyfra (“15”) to szerokość pola. Zob. dokumentację Format String Syntax.

1.4.7.1. Zapis w pliku csv

Dane można też wygodnie zapisywać do pliku w formacie csv. Jest to rozwiązanie wygodniejsze, ponieważ zwalnia nas od konieczności ręcznego przekształcania odczytywanych z pliku linii na struktury danych.

Na początku pliku dodajemy import modułu: import csv. Następnie zmieniamy funkcje otworz() i zapisz() na podane niżej:

Kod nr
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def otworz(plik):
    if os.path.isfile(sFile):  # czy istnieje plik słownika?
        with open(sFile, newline='') as plikcsv:  # otwórz plik do odczytu
            tresc = csv.reader(plikcsv)
            for linia in tresc:  # przeglądamy kolejne linie
                slownik[linia[0]] = linia[1:]
    return len(slownik)  # zwracamy ilość elementów w słowniku


def zapisz(slownik):
    # otwieramy plik do zapisu, istniejący plik zostanie nadpisany(!)
    with open(sFile, "w", newline='') as plikcsv:
        tresc = csv.writer(plikcsv)
        for wobcy in slownik:
            lista = slownik[wobcy]
            lista.insert(0, wobcy)
            tresc.writerow(lista)

Format csv polega na zapisywaniu wartości oddzielonych separatorem, czyli domyślnie przecinkiem. Jeżeli wartość zawiera znak separatora, jest cytowana domyślnie za pomocą cudzysłowu. W naszym wypadku przykładowa linia pliku przyjmie postać: wyraz obcy,znaczenie1,znaczenie2,...

W powyższym kodzie używamy metody csv.reader(plik), która interpretuje podany plik jako zapisany w formacie csv i każdą linię zwraca w postaci listy elementów. Instrukcja slownik[linia[0]] = linia[1:] zapisuje dane w słowniku, kluczem jest wyraz obcy (1 ellement listy), wartościami – lista znaczeń.

W funkcji zapisującej dane w formacie csv, na początku tworzymy obiekt tresc zwrócony przez metodę csv.writer(plik). Po przygotowaniu listy zawierającej wyraz obcy i jego znaczenia zapisujemy ją za pomocą metody writerow(lista).

1.4.7.1.1. Zadania dodatkowe

  • Kod drukujący słownik zamień w funkcję. Wykorzystaj ją do wydrukowania słownika odczytanego z dysku i słownika uzupełnionego przez użytkownika.
  • Spróbuj zmienić program tak, aby umożliwiał usuwanie wpisów.
  • Dodaj do programu możliwość uczenia się zapisanych w słowniku słówek. Niech program wyświetla kolejne słowa obce i pobiera od użytkownika możliwe znaczenia. Następnie powinien wyświetlać, które z nich są poprawne.

Licencja Creative Commons Materiały Python 101 udostępniane przez Centrum Edukacji Obywatelskiej na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.

Utworzony:2018-04-12 o 19:31 w Sphinx 1.5.3
Autorzy:Patrz plik “Autorzy”