.. _przyklad6:
Moduły i zbiory
###############
.. note::
W tym przykładzie zobaczysz, jak korzystać z **modułów**, a także
poznasz i wykorzystasz **zbiór**, kolejną obok list i krotek złożoną strukturę danych.
Zadanie
*******
Napisz program :file:`oceny.py`, który umożliwi wprowadzanie ocen z wybranego / wprowadzonego przedmiotu,
następnie policzy i wyświetla średnią, medianę i odchylenie standardowe wprowadzonych ocen.
Funkcje pomocnicze i statystyczne umieść w osobnym module.
**Dane**:
- ``przedmiot`` – nazwa dodawanego przedmiotu i/lub przedmiotu, z którego będą wprowadzane oceny,
ciąg znaków pobierany z klawiatury,
- ``ocena`` – ocena pobierana z klawiatury, liczba całkowita.
**Wynik**:
– wypisana na ekranie średnia, mediana i odchylenie podanych ocen, np.:
.. code::
Średnia: 3.62
Mediana: 3.50
Odchylenie: 1.58
.. raw:: html
Plik oceny.pyKod nr
.. literalinclude:: przyklad06.py
:linenos:
**Moduły**
Moduły to pliki zawierające często wykorzystywane stałe, funkcje i klasy. Wiele modułów, tzw. wbudowanych,
jest częścią standardowej instalacji Pythona, programista może również tworzyć własne moduły.
Dostęp do zawartości modułu uzyskujemy dzięki **importom**. Nazwa modułu to nazwa pliku z kodem bez rozszerzenia ``.py``.
Moduł musi znajdować się w ścieżce przeszukiwania, aby import był udany. Przykłady:
- ``import math`` – import całego modułu, dostęp do zawartości uzyskujemy dzięki notacji z kropką,
np. ``math.pi`` lub ``math.sqrt()``,
- ``from math import pi, sqrt`` – import tylko wybranych elementów, których nazw używamy bezpośrednio, np.:
``pole = pi * r**2``, ``c = sqrt(a**2 + b**2)``.
.. note::
W przypadku prostych programów zapisuj moduły w tym samym katalogu co program główny.
**Zbiór**
Do przechowywania nazw przedmiotów wykorzystujemy :term:`zbiór`, czyli nieuporządkowany zestaw niepowtarzalnych (!)
elementów. Operacje na zbiorach:
- ``przedmioty = {'polski', 'angielski'}`` – tworzy zbiór, można również używać funkcji ``set(sekwencja)``;
- ``.add(x)`` – dodaje element x do zbioru, jeżeli go w zbiorze nie ma;
- ``element (not) in kolekcji`` – operator zawierania ``(not) in`` sprawdza, czy podany element
jest lub nie w kolekcji, tj. liście, zbiorze, krotce (tupli) lub innej sekwencji; wynikiem jest prawda
lub fałsz.
.. note::
Porządek elementów w zbiorach, inaczej niż w listach i krotkach, jest nieokreślony.
Przedmioty pobieramy w nieskończonej pętli warunkowej ``while True``. Jeżeli użytkownik poda przynajmniej 2-znakową
nazwę przedmiotu (``if len(przedmiot) > 1:``) i przedmiotu nie ma w zbiorze (``if przedmiot not in przedmioty:``),
zostanie on dodany. W przeciwnym razie wypisujemy przedmioty zawarte w zbiorze i pobieramy nazwę przedmiotu, z którego
użytkownik chce wprowadzić oceny. Jeżeli podanej nazwy nie ma w zbiorze, wypisujemy odpowiedni komunikat,
jeżeli jest, przerywamy pętlę instrukcją ``break`` i przechodzimy do wprowadzania ocen.
W drugiej pętli warunkowej pobieramy oceny, dopóki użytkownik nie wprowadzi 0 (zera).
Blok ``try...except`` pozwala przechwycić wyjątki, czyli w tym przypadku błąd przekształcenia
wartości na liczbę całkowitą. Jeżeli funkcja ``int()`` zwróci wyjątek, wykonywane są instrukcje
w bloku ``except ValueError:``, w przeciwnym razie po sprawdzeniu poprawności oceny dodajemy ją
do listy: ``oceny.append(ocena)``.
Metoda ``.capitalize()`` zmienia pierwszy znak napisu na wielką literę.
Do wypisania komunikatów używamy sformatowanych ciągów znaków (:term:`f-strings`) i specyfikatorów formatu.
Zapis ``{s:8.2f}`` oznacza, że wartość zmiennej ``s`` ma zostać wypisana w polu o szerokości 8 znaków
jako liczba zmiennoprzecinkowa z dokładnością do dwóch miejsc po przecinku.
Więcej informacji nt. formatowania danych wyjściowych: `PyFormat `_.
.. raw:: html
**Funkcje** wykorzystywane w programie **oceny**, umieszczamy w osobnym pliku :file:`ocenyfun.py`.
.. raw:: html
Plik oceny_funkcje.pyKod nr
.. literalinclude:: oceny_funkcje.py
:linenos:
Instrukcja ``import math`` udostępnia wszystkie metody z modułu matematycznego, wykorzystujemy
funkcję obliczającą pierwiastek kwadratowy: ``math.sqrt()``.
Funkcja ``wypisz(sekwencja, kom='...')`` wypisuje podany komunikat, a następnie za pomocą pętli
``for e in sekwencja`` odczytuje i wypisuje elementy podanej sekwencji (zbioru, listy ip.) w jednym wierszu.
Argument ``kom`` jest opcjonalny, ponieważ przypisujemy mu wartość domyślną, która zostanie użyta,
jeżeli użytkownik nie poda innej w wywołaniu funkcji.
Funkcja ``srednia()`` do zsumowania wartości ocen wykorzystuje funkcję ``sum()``.
Funkcja ``mediana()`` sortuje niemalejąco otrzymaną listę "w miejscu" (``oceny.sort()``),
tzn. trwale zmienia porządek elementów listy. Jeżeli liczba ocen jest parzysta ``if len(oceny) % 2 == 0:``,
zwraca średnią arytmetyczną dwóch środkowych wartości. Indeks drugiego ze środkowych elementów
obliczamy w wyrażeniu ``half = len(oceny) // 2``. Operator ``//`` oznacza dzielenie całkowite.
Notacja wycinkowa ``oceny[half-1:half+1]`` zwraca dwa środkowe elementy z listy.
Jeżeli liczba ocen jest nieparzysta, zwracamy wartość środkową: ``oceny[len(oceny) // 2]``.
W funkcji ``wariancja()`` pętla ``for`` odczytuje kolejne oceny i korzysta z operatorów skróconego dodawania (``+=``)
i potęgowania (``**``), aby wyliczyć sumę kwadratów różnic kolejnych ocen i średniej: ``suma += (ocena - srednia)**2``.
Funkcja zwraca średnią arytmetyczną obliczonej sumy: ``suma / len(oceny)``.
Ćwiczenia
----------
W konsoli Pythona utwórz listę ``wyrazy`` zawierającą elementy: *abrakadabra* i *kordoba*.
- utwórz zbiór ``w1`` za pomocą polecenia ``set(wyrazy[0])`` oraz zbiór ``w2`` za pomocą polecenia ``set(wyrazy[1])``,
- wykonaj kolejno polecenia ilustrujące użycie klasycznych operatorów na zbiorach, czyli:
różnica (-) , suma (|), przecięcie (część wspólna, &) i elementy unikalne (^):
.. code-block:: bash
>>> print(w1 – w2)
>>> print(w1 | w2)
>>> print(w1 & w2)
>>> print(w1 ^ w2)
- w pliku :file:`oceny_funkcje.py` dopisz funkcję, która wyświetli wszystkie oceny oraz ich odchylenia
od wartości średniej; wywołanie funkcji umieść w pliku :file:`oceny.py`.
.. admonition:: Pojęcia
:term:`moduł`, :term:`importowanie`, :term:`zbiór`, :term:`f-strings`, :term:`notacja wycinkowa`