PPy3/Moduły
Moduły i biblioteki
Wspomnieliśmy wcześniej, że problemu raz rozwiązanego nie warto rozwiązywać po raz drugi, trzeci, ... (no chyba, że mamy pomysł na jakieś jakościowo nowe rozwiązanie). Zgodnie z tą zasadą, kod stanowiący rozwiązanie opakowuje się w funkcję - z której następnie można korzystać wielokrotnie. Ale na razie wiemy tylko, że z funkcji możemy korzystać w obrębie programu, w którym występuje definicja tejże funkcji. A co z innymi programami? Metoda kopiuj/wklej to nie jest najlepszy pomysł - wyobraźmy sobie chociaż, że w kodzie funkcji wykryliśmy drobny błąd (albo możliwość istotnego ulepszenia); będziemy teraz wyszukiwać wszystkich programów, w których ten kod uprzednio wkleiliśmy, aby je skorygować? Zamiast tego, lepiej jest skorzystać z stworzonego dokładnie w tym celu mechanizmu modułów - plików, w których umieszczamy definicje funkcji (i ewentualnie innych obiektów), z których będzie można korzystać w wielu różnych programach.
Ułatwienie wielokrotnego użytku kodu nie jest jedyną korzyścią z dzielenia kodu programu na funkcje. Warto to robić również, gdy wielokrotnego użytku się nie przewiduje - o ile zadanie do wykonania przez program nie jest trywialne proste, a kod je realizujący bardzo krótki. Wprowadzenie do kodu pewnej struktury wynikającej z podziału różnych elementów algorytmu pomiędzy funkcje sprzyja czytelności programu i ułatwia jego ewentualną modyfikację w przyszłości.
Najprostszy moduł
Jako moduł może służyć dowolny plik zawierający kod w Pythonie, opatrzony nazwą z końcówką .py (tutaj nazwa ma znaczenie). Zazwyczaj w module umieszcza się jedynie definicje (funkcji, klas, ewent. stałych nazwanych), a nie - kod faktycznie wykonywany.
Nazwijmy plik o poniższej treści witaj.py:
#! /usr/bin/python3
def witaj(imie):
print('Witaj {}!'.format(imie))
Wykorzystaliśmy tu znaną już nam metodę format do zgrabnego wstawienia imienia do treści powitania. Ten sam skutek dałoby się osiągnąć stosując operację sklejania napisów:
print('Witaj ' + imie + '!')
użycie formatowania jednak jest zalecane, zwłaszcza w bardziej złożonych przypadkach.
Uruchomienie pliku witaj.py jako programu nie spowoduje żadnego widocznego skutku - funkcja witaj zostanie wprawdzie zdefiniowana, ale program zakończy działanie zanim zostanie ona w ogóle użyta (wywołana). Chcąc wykorzystać tę funkcję w oddzielnym programie, musimy najpierw w kodzie tego programu wskazać, gdzie znajduje się definicja tej funkcji. Do tego służy polecenie import:
#! /usr/bin/python3
import witaj
witaj.witaj('Heleno')
Notacja witaj.witaj w tym przypadku wskazuje, że chodzi o funkcję witaj (słowo po kropce) z modułu o nazwie witaj (to przed kropką). Oczywiście nazwy te równie dobrze mogą brzmieć różnie, a w jednym module można zdefiniować wiele funkcji. Polecenie import witaj nadaje, w ramach tego programu, znaczenie nazwie witaj - będzie ona oznaczać moduł, którego zawartością (elementami) są funkcje (i ew. inne obiekty) zdefiniowane w pliku witaj.py.
Można również inaczej:
#! /usr/bin/python3
from witaj import witaj
witaj('Heleno')
Przy tej postaci instrukcji import, udostępniona w ramach programu zostaje tylko funkcja witaj i należy się do niej odwoływać przez ,,gołą" nazwę. Obiektów importowanych z modułu o nazwie wskazanej po słowie from może być więcej, należy podać ich nazwy po słowie import, oddzielone przecinkami.
Można też jeszcze inaczej:
#! /usr/bin/python3
from witaj import *
witaj('Jakubie')
Taka instrukcja poleca udostępnić wszystkie nazwy, jakie zostały zdefiniowane w module witaj. W tym akurat przypadku jest tylko jedna taka nazwa, nie dzieje się więc nic innego niż w poprzednim przykładzie. Jeżeli jednak moduł witaj zostanie w przyszłości wzbogacony o dalsze definicje, to używając instrukcji import z gwiazdką jak powyżej, będziemy te definicje importować do swojego programu zupełnie nieświadomie; nie będzie w tym nic złego, dopóki się nie okaże np. że nazwa któregoś z obiektów zdefiniowanych w tym module pokrywa się z jakąś nazwą występującą w bibliotece standardowej, i to nazwą obiektu, z jakiego postanowiliśmy również skorzystać w naszym kodzie - może się wtedy zdarzyć, że będziemy wywoływać wcale nie tę funkcję, o którą nam chodziło... Więcej o możliwych konfliktach nazw powiemy dalej, na dziś warto zapamiętać: instrukcja from ... import * nie powinna występować w ostatecznej wersji kodu żadnego programu (nie ma nic złego w używaniu jej np. przy interakcyjnym testowaniu działania funkcji z danego modułu, itp.).