01 - Podstawy języka Python
Podstawy przetwarzania danych
Politechnika Poznańska, Instytut Robotyki i Inteligencji Maszynowej
Ćwiczenie laboratoryjne 1: operacje wejścia/wyjścia w języku Python; typy danych i podstawowe operacje matematyczne
Powrót do spisu treści ćwiczeń laboratoryjnych
O języku
Python to język programowania wysokiego poziomu ogólnego przeznaczenia, o rozbudowanym pakiecie bibliotek standardowych, którego ideą przewodnią jest czytelność i klarowność kodu źródłowego. Jego składnia cechuje się przejrzystością i zwięzłością.
Python wspiera różne paradygmaty programowania: obiektowy, imperatywny oraz w mniejszym stopniu funkcyjny. Posiada w pełni dynamiczny system typów i automatyczne zarządzanie pamięcią, będąc w tym podobnym do języków Perl, Ruby, Scheme czy Tcl. Podobnie jak inne języki dynamiczne jest często używany jako język skryptowy. Interpretery Pythona są dostępne na wiele systemów operacyjnych.
Python rozwijany jest jako projekt Open Source zarządzany przez Python Software Foundation, która jest organizacją non-profit. Standardową implementacją języka jest CPython (napisany w C), ale istnieją też inne (źródło: Wikipedia).
Cechą szczególną języka jest interpretacja znaków białych. Inaczej niż w przypadku większości pozostałych języków programowania, mają one ogromne znaczenie i odpowiadają m.in. za przynależność pojedynczej linii lub bloku kodu do danej klasy, czy instrukcji sterującej.
Funkcjonalność języka może zostać rozszerzona poprzez użycie
darmowych bibliotek. Ich repozytorium jest dostępne pod adresem https://pypi.org, a instalację umożliwia
narzędzie konsolowe pip
domyślnie instalowane wraz z
interpreterem.
Dostępna jest darmowa dokumentacja języka.
Zmienne
Definiowanie zmiennych
Język Python, podobnie jak na przykład język MATLAB, charakteryzuje się dynamicznym typowaniem zmiennych. Oznacza to, że po przypisaniu wartości do zmiennej, Python sam określi jaki typ będzie dla niej odpowiedni.
Do zmiennej musi być przypisana wartość w momencie tworzenia - nie możemy zadeklarować samej nazwy “na później”. Linijka:
new_variable
skutkuje następującym błędem (tzw. wyjątkiem):
NameError: name 'new_variable' is not defined
Mimo że zmienne nie mają jawnie zadeklarowanych typów, wartości w nich przechowywane już tak, i posiadają one swoje właściwości czy funkcje. Obowiązuje tak zwane silne typowanie. Dla przykładu: typy liczbowe nie zostaną automatycznie zamienione na tekst i na odwrót. Możliwe jest tego typu działanie:
= 10
variable_int_1 = 20
variable_int_2 + variable_int_2 variable_int_1
natomiast poniższy kod nie wykona się ze względu na niezgodność typów:
= 10
variable_int_1 = "abc"
variable_string_1 + variable_string_1 variable_int_1
Typ zmiennej możemy zawsze sprawdzić przy pomocy wbudowanej funkcji
type()
:
print(type(42))
print(type("abc"))
Definiując zmienne należy pamiętać o kilku zasadach dotyczących ich nazw:
- nazwa musi zaczynać się literą lub znakiem “podłogi”
(
_
), - nazwa nie może zaczynać się od cyfry,
- nazwy mogą zawierać tylko litery (A-z), cyfry (0-9) oraz znak “podłogi”,
- rozróżniane są wielkości liter,
- zdecydowanie zalecane są nazwy zmiennych w języku angielskim,
- nazwy zmiennych powinny zawsze jasno informować o tym co się w nich znajduje.
💥 Zadanie 1 💥
Uruchom konsolę języka Python. Jest ona dostępna na przykład w środowisku PyCharm po utworzeniu projektu (ikona węży w panelu w lewym dolnym narożniku).
Wykonaj poniższe komendy w konsoli Pythona. Sprawdź jakie typy zmiennych zostały do nich przypisane.
= 10
a = "Tekst" # cudzysłów pojedynczy (') oraz podwójny (") działają tak samo b
Konwersje typów
Programista ma możliwość skorzystania z mechanizmu konwersji typów
zmiennych. Działa to podobnie jak w przypadku rzutowania znanego z
języków C i C++. Operacja ta realizowana jest jednak odmiennie, bo za
pośrednictwem dedykowanych funkcji str()
,
float()
oraz int()
.
💥 Zadanie 2 💥
Wpisz w konsoli kod c = str(a)
. Jakiego typu jest
zmienna c
?
Stałe
Wiele języków programowania pozwala na definiowanie stałych, czyli wartości lub struktur, które w ogólności nie ulegają, a przynajmniej nie powinny ulegać zmianie w trakcie działania programu.
Przykładem stałej może być liczba \(Pi\). Python nie pozwala na tworzenie stałych, znanych np. z języka C, czy C++. Przyjęta została jednak konwencja, że nazwy wszystkich niezmiennych wartości zapisywane są wersalikami (wielkimi literami). Nie zmienia ona faktu, że wartości te mogą zostać zmodyfikowane, ale jednocześnie jasno sugeruje, żeby tego nie robić.
= 3.14159265359
PI = 8849 MOUNT_EVEREST
Zasady tworzenia nazw dla stałych są identyczne jak w przypadku zmiennych.
Operacje na liczbach
Python pozwala operować na danych liczbowych, podobnie jak ma to miejsce w innych językach wysokiego poziomu. Do dyspozycji programisty pozostawiono zbiór operatorów, przedstawiony w tabeli poniżej. Za ich pomocą można wykonywać operacje zarówno na liczbach całkowitych jak i zmiennoprzecinkowych.
Operator | Działanie |
---|---|
+ | Dodawanie |
- | Odejmowanie |
* | Mnożenie |
/ | Dzielenie |
% | Reszta z dzielenia |
// | Dzielenie całkowite |
** | Potęgowanie |
Szczególną uwagę należy zwrócić na operatory dzielenia. O ile typ
zmiennej, do której zwracany będzie wynik, zwyczajowo jest zależny od
operandów i wyniku samej operacji, o tyle w przypadku dzielenia przy
użyciu /
wynik zawsze będzie zmienną zmiennoprzecinkową.
Efekt ten nie zawsze jest pożądany, stąd twórcy dodali drugi operator
dzielenia - //
. Wartość zwracana za jego pośrednictwem jest
zawsze całkowita. Cześć liczby znajdująca się po przecinku jest
pomijana, niezależnie od jej wartości.
💥 Zadanie 3 💥
Przetestuj działanie każdego z operatorów zawartych w tabeli
wykorzystując zmienne zdefiniowane poniżej. Porównaj wyniki operacji
x = e / f
oraz y = e // f
.
= 77
d = 10
e = 0.10001 f
Operacje na ciągach znaków
Ciągi znakowe w języku Python muszą zostać umieszczone w ramach odpowiednich znaczników. Do dyspozycji są trzy różne kombinacje:
'text'
- tekst w pojedynczej linii,"text"
- tekst w pojedynczej linii (działa identycznie jak poprzedni wariant),"""text"""
- tekst w wielu liniach.
Długość tekstu zwraca funkcja len()
. Ma ona zastosowanie
zarówno w stosunku do zmiennych tekstowych jak i do samych ciągów:
= 'Test'
my_text len(my_text)
len('Test')
Ciągi znakowe można ze sobą łączyć, tworząc dłuższe wyrażenia. Służy
do tego operator +
. W ciągach tekstowych można także
umieszczać liczby. Niezbędna jest wtedy stosowna konwersja typów:
= my_text + ' numer ' + str(e) my_text_with_number
Możliwe jest także odwołanie się do pojedynczego znaku przy użyciu
operatora []
. Należy pamiętać, że ciąg znaków jest,
podobnie jak w większości języków programowania, numerowany od 0.
= 'Test'
my_text print(my_text[0] + my_text[1] + my_text[2] + my_text[3])
Do podziału ciągu na podciągi służy metoda split()
. Jako
argument przyjmuje ona separator, czyli frazę, względem której ma
nastąpić podział:
= 'Test_1;Test_2'
j = j.split(';')
k print(k)
💥 Zadanie 4 💥
Przeanalizuj wynik wywołania dla powyższego wyrażenia.
Obsługa wejścia/wyjścia
Konsola interpretera Python pozwala na interakcję z użytkownikiem.
Możliwe jest wczytanie danych podanych przez użytkownika oraz wypisanie
danych na ekranie. Służą do tego odpowiednio funkcje
input()
oraz print()
.
Funkcja input()
przyjmuje jako argument tekst, który
zostanie wyświetlony na ekranie, jeszcze przed pobraniem wejścia od
użytkownika. Zwracana jest zmienna typu tekstowego. Przed wykonaniem
operacji arytmetycznych należy pamiętać, aby dokonać konwersji na
właściwy typ.
= input('Podaj pierwszą liczbę: ')
first_number = int(input('Podaj drugą liczbę: ')) second_number
Funkcja print()
wypisuje na ekranie zadany tekst. Nie ma
konieczności stosowania ciągów formatujących - poszczególne części
tekstu są łączone operatorem +
.
= int(first_number)
first_number print('Suma liczb: ' + str(first_number + second_number))
💥 Zadanie 5 💥
Przetestuj działanie powyższego kodu. Zmodyfikuj go tak, aby wczytane zostały dwa ciągi tekstowe. Następnie połącz je w jedno wyrażenie i wyświetl.
Skrypty
Wykonywanie poleceń z poziomu konsoli interpretera ogranicza się w praktyce do pojedynczych komend. Dużo lepszym rozwiązaniem jest użycie skryptów. W przypadku Pythona, są to pliki z rozszerzeniem *.py. Wraz z pierwszym projektem, utworzony został plik skryptowy main.py.
Usuń zawartość pliku main.py jeśli nie jest on pusty. Nie będzie ona przydatna na tych i kolejnych zajęciach.
💥 Zadanie 6 💥
Przetestuj działanie kodu z podrozdziału Obsługa wejścia/wyjścia.
Debugger
Często, szczególnie w przypadku większych projektów, zachodzi potrzeba znalezienia błędów, które nie powodują błędu krytycznego programu, ale wpływają na wynik obliczeń. Do tego celu idealnie nadaje się debugger wbudowany w narzędzie PyCharm. Klikając pomiędzy numerem linii a obszarem roboczym, użytkownik może dodać punkt zatrzymania (tzn. break point). Gdy interpreter dotrze do wykonywania danej linii kodu, zostanie on zatrzymany, a na ekranie pojawią się dodatkowe informacje diagnostyczne, takie jak na przykład obecna wartość zmiennych przechowywanych w pamięci. Aby uruchomić tryb debugowania, można użyć skrótu klawiszowego SHIFT+F9 lub kliknąć ikonę z robakiem. Tryb ten będziemy używać na zajęciach tylko okazjonalnie, ale warto mieć świadomość jego istnienia.
💥 Zadanie 7 💥
Napisz program, który wczyta od użytkowników dwie liczby (podstawę oraz wykładnik potęgi), wykona operację potęgowania i wypisze wynik na ekranie. Przetestuj działanie debuggera.
💥 Zadanie 8 💥
Napisz program, który wczyta od użytkownika dwie liczby, podzieli je i wypisze na ekranie wartość całkowitą oraz resztę z dzielenia.
Komentarze
Przygotowując skrypt, nierzadko konieczne jest opisanie funkcjonalności poszczególnych fragmentów lub bloków kodu. Jest to czynność szczególnie istotna, gdy do kodu powraca się po dłuższej przerwie lub udostępnia się go innym osobom. Komentowanie treści, przydaje się także w trakcie poszukiwania błędów w kodzie, dzieląc kod na mniejsze fragmenty. Komentarze powinny używać języka angielskiego.
Należy przy tym pamiętać, że priorytetem jest odpowiednie nazewnictwo zmiennych oraz funkcji. Dzięki nazwom, które dobrze oddają to, co dana zmienna przechowuje lub dana funkcja robi, kod w dużej mierze komentuje się sam. Dodatkowe komentarze wymagane są wtedy głównie w wyjątkowo skomplikowanych lub nietypowych miejscach.
W języku Python dostępne są dwa podstawowe typu komentarzy –
jednoliniowe oraz wieloliniowe. Pierwsze z nich, jak sama nazwa
wskazuje, służą do komentowania pojedynczej linii kodu lub do dopisania
komentarza za kodem właściwym. Komentarz taki tworzy się za pomocą
znacznika #
.
# the value of 5 will be assigned to the xyz variable below
= 5 # the assignment happens here xyz
Druga możliwość to dodanie komentarza blokowego, który obejmuje jedną
lub wiele linii kodu. Służą do tego znaczniki """
i muszą
one zostać użyte dwukrotnie, aby rozpocząć blok oraz go zamknąć.
"""
Kod opracował:
Jan Kowalski
100100
"""
= 5 xyz
W ramach pojedynczego skryptu można używać obu typów komentarzy.
Podstawowe struktury danych
Twórcy języka Python przewidzieli cztery podstawowe struktury danych. Są nimi listy, krotki, zbiory oraz słowniki. Każda ze struktur posiada swoją specyfikę oraz przeznaczenie.
Listy służą do przechowywania dużej liczby pojedynczych wartości.
Kolejność elementów na liście może być zmieniana po jej utworzeniu.
Dopuszczalne są także duplikaty wartości. Dostęp do pojedynczego
elementu uzyskuje się za pośrednictwem nawiasów kwadratowych. Elementy
są numerowane od zera. Na potrzeby dodawania oraz usuwania elementów,
zdefiniowane zostały odpowiednio metody append()
oraz
remove()
. Długość listy można uzyskać za pośrednictwem
funkcji len()
.
= ['A', 'B', 'C']
my_list 2] = 'X'
my_list['D')
my_list.append('A')
my_list.remove(print(my_list[0])
print(len(my_list))
Krotki, podobnie jak listy, służą do przechowywania zbioru
pojedynczych wartości. Podstawową różnicą jest fakt, że ich bezpośrednia
zawartość nie może zostać zmieniona po ich utworzeniu. W praktyce
oznacza to, że niemożliwe jest użycie operatora przypisania (poskutkuje
błędem). Dostęp do pojedynczego elementu uzyskuje się za pośrednictwem
nawiasów kwadratowych. Elementy są numerowane od 0. Możliwe jest
pobranie wartości wskazującej na długość krotki, za pośrednictwem
funkcji len()
.
= ('A', 'B', 'C')
my_tuple print(my_tuple[0])
print(len(my_tuple))
Zbiory stanowią kolekcje, służące do przechowywania unikalnych
wartości. Wartości te nie posiadają zdefiniowanej kolejności
wystąpienia, a tym samym nie ma możliwości pobrania konkretnej wartości.
Co więcej, kilkukrotne wypisanie zawartości zbioru, może skutkować inną
kolejnością elementów przy każdym wywołaniu. Dodawanie oraz usuwanie
elementów odbywa się przy pomocy metod add()
oraz
remove()
. Rozmiar zbioru można pobrać przy użyciu funkcji
len()
.
= {'A', 'B', 'C'}
my_set 'D')
my_set.add('A')
my_set.remove(print(my_set)
print(len(my_set))
Dostęp do elementów zbioru odbywa się za pośrednictwem pętli for.
Ostatnią strukturą są słowniki. Podobnie jak zbiory, służą one do przechowywania unikalnych elementów, przy czym są to pary postaci klucz:wartość, gdzie tylko klucz musi być unikalny w ramach danego słownika. Dostęp odbywa się za pośrednictwem klucza podanego w nawiasach kwadratowych. Możliwe jest dodawanie i usuwanie elementów oraz zmiana ich wartości. Bardzo często kluczem jest ciąg tekstowy, ale obsługiwane są również inne typy.
= {'el_A': 'A', 'el_B': 'B', 'el_C': 'C'}
my_dict 'el_D'] = 'D'
my_dict[del my_dict['el_A']
print(my_dict)
print(my_dict['el_B'])
print(len(my_dict))
💥 Zadanie 9 💥
Przetestuj każdą z omówionych struktur.
Instrukcje sterujące
Instrukcja warunkowa if
Instrukcje warunkowe pozwalają na kontrolę procesu wykonywania kodu
źródłowego. Umożliwiają one wskazanie, które fragmenty kodu powinny
zostać wykonane w zależności od spełnienia (lub nie) warunków
wejściowych. Każda instrukcja warunkowa rozpoczyna się słowem kluczowym
if
. Za słowem if
zawsze musi pojawić się
warunek do sprawdzenia oraz znak :
. Można tu wykorzystać
operatory porównania oraz - w celu budowy bardziej złożonych warunków -
operatory logiczne.
Operator | Działanie |
---|---|
== |
Równy |
!= |
Różny |
> |
Większy |
< |
Mniejszy |
>= |
Większy lub równy |
<= |
Mniejszy lub równy |
Operator | Działanie |
---|---|
and |
Iloczyn logiczny |
or |
Suma logiczna |
not |
Negacja |
Instrukcja warunkowa może być bez alternatywy i składać się tylko ze
słowa kluczowego if
. Należy pamiętać, że głębokość wcięcia
tekstu wskazuje przynależność danego wyrażenia lub bloku tekstu do danej
klauzuli (białe znaki mają tu znaczenie). Instrukcja if
opcjonalnie może zawierać alternatywę, definiowaną przy użyciu słowa
elif
oraz else
. Poniższy przykład ilustruje
zasadę działania instrukcji warunkowej dla przypadku dzielenia
przez 0.
# poprawny kod
= 5
a = 0
b if b == 0:
print('Division by 0 error!')
else:
= a / b
c print(c)
# niepoprawny kod
= 5
a = 0
b if b == 0:
print('Division by 0 error!')
else:
= a / b
c print(c)
💥 Zadanie 10 💥
Przygotuj kod instrukcji warunkowej, która sprawdzi czy wartość
zmiennej a
jest większa od 100, mniejsza od 100, czy równa
100. Zwrócona powinna zostać informacja w formie tekstowej (np.
'Liczba jest mniejsza niż 100.'
).
Pętla while
Przetwarzanie dużej ilości danych wymusza konieczność użycia dedykowanych instrukcji danego języka programowania. Pętle pozwalają na wykonanie danego bloku kodu wielokrotnie, bez konieczności jego zwielokrotniania w pliku źródłowym.
Pętla while
to pętla, która jest wykonywana dopóki dany
warunek jest spełniony (logiczna prawda). Stosuje się ją, gdy nie jest
znana liczba iteracji (powtórzeń) do wykonania. Takimi przypadkami są
m.in. wczytywanie liczb od użytkownika, do czasu podania konkretnej
wartości, czy losowanie liczb, do czasu uzyskania wartości
oczekiwanej.
Pętlę tę definiuje się za pomocą słowa kluczowego while
.
Następnie należy podać warunek, który jest sprawdzany przy każdym obiegu
pętli. Warunek musi zostać zakończony znakiem :
.
Poniższy kod ukazuje przykładowe zastosowanie pętli
while
.
= 1
value while value > 0:
= int(input('Enter number: '))
value print('Received number ' + str(value))
💥 Zadanie 11 💥
Napisz program, który będzie wczytywał kolejne liczby podawane przez użytkownika dopóki ich suma będzie mniejsza niż 1000. Program powinien na bieżąco informować o ostatnim wyniku sumowania.
Pętla for
Pętlę for
definiuje się przy użyciu słów kluczowych
for
oraz in
. Za słowem for
należy
umieścić nazwę iterowalnej zmiennej, kolejno słowo in
i strukturę, która ma zostać poddana iteracji. Należy też pamiętać o
znaku :
. Do zmiennych iterowalnych można zaliczyć
wspomniane wcześniej struktury: listę, krotkę, zbiór oraz słownik.
Możliwe jest także użycie funkcji range()
. Przyjmuje ona
następujące argumenty: wartość początkową, wartość końcową, krok. Warto
zaznaczyć, że mamy tutaj do czynienia z przedziałem otwartym tzn.
wywołanie range(2,6,1)
wykona pętle dla wartości 2, 3, 4 i
5. Jedynie pierwszy argument range()
jest obowiązkowy.
Istnieją w związku z tym alternatywne wywołania tej funkcji:
range(a)
- wartości z przedziału \(<0; a)\) z krokiem 1,range(a, b)
— wartości z przedziału \(<a; b)\) z krokiem 1.
W ciele każdej pętli można zagnieżdżać inne pętle, instrukcje warunkowe oraz definiować zmienne. Możliwe jest przygotowanie np. skryptu sumującego liczby parzyste z zadanego przedziału, co przedstawiono w przykładzie poniżej.
= 0
sum_of_elements for element in range(1, 101):
if element % 2 == 0:
= sum_of_elements + element # one can also use sum_of_elements += element
sum_of_elements print(sum_of_elements)
💥 Zadanie 12 💥
Napisz program, który znajdzie i wypisze liczby pierwsze z zakresu od
1 do b
, gdzie b
to wartość nie mniejsza niż
1000.
💥 Zadanie 13 💥
Napisz program, który wczyta od użytkownika tekst i sprawdzi, czy jest on palindromem.
Funkcje
Podstawową strukturą, która umożliwia uporządkowanie i ograniczenie
rozmiaru kodu są funkcje. Funkcja pełni rolę bloku wykonawczego, który
realizuje pewne, specyficzne zadanie. Zaletami takiego podejścia są
przede wszystkim częściowa niezależność od pozostałej części kodu oraz
możliwość wielokrotnego wykonania tego samego fragmentu kodu, bez
konieczności jego duplikowania. Deklaracja funkcji składa się ze słowa
kluczowego def
, nazwy własnej funkcji (zgodnie z zasadą
deklaracji zmiennych) oraz argumentów, o ile są one potrzebne. Co
więcej, argumenty mogą być obowiązkowe lub opcjonalne.
def function_a(): # funkcja bez argumentów wejściowych
return True
def function_b(a): # funkcja z jednym, obowiązkowym argumentem wejściowym
return a * a
def function_c(a, b=1): # funkcja z dwoma argumentami wejściowymi, w tym z jednym opcjonalnym
return a * b
Wartość wyjściowa funkcji może zostać zwrócona za pośrednictwem słowa
kluczowego return
. Poniżej przedstawiony został przykład,
który obrazuje zasadę konstruowania i działania funkcji. Oba bloki kodu
realizują to samo zadanie, przy czym drugi z nich został zdefiniowany z
użyciem funkcji.
= 5
value_a = 8
value_b = value_a + value_b * value_a
result_a
= 7
value_a = 9
value_b = value_a + value_b * value_a result_b
def my_function(a, b):
return a + b * a
= my_function(5, 8)
result_a = my_function(7, 9) result_b
Funkcje w języku Python mogą zwracać kilka wartości. W rzeczywistości zwracana jest wtedy krotka (tuple), która następnie jest rozpakowywana do kilku zmiennych:
def my_function_that_returns_multiple_values():
return 'my text', 42
= my_function_that_returns_multiple_values() some_text, some_number
Nazwy funkcji powinny jednoznacznie opisywać co dana funkcja
robi (albo raczej: ma zrobić) i używać języka angielskiego. W
związku z tym, że funkcje wykonują pewne zadania, ich nazwy zazwyczaj
powinny zawierać czasownik. Przykłady dobrych nazw funkcji to
add_numbers
, sum_values
,
load_data
, read_text
. Do kiepskich nazw
funkcji można, co ciekawe, zaliczyć funkcję wbudowaną
input()
- brakuje jej czasownika informującego o
wykonywanej czynności.
Szablon skryptu w języku Python
O ile w plikach źródłowych języka Python kod można pisać bez jakiegokolwiek podziału na funkcje, zalecane jest korzystanie z następującego szablonu:
def main():
print('Here goes my code')
if __name__ == '__main__':
main()
Kod powinien znajdować się w funkcji main()
. Jej nazwa
jest tylko konwencją i można ją zmieniać (choć pewnie nie warto).
Tajemniczo wyglądający warunek wywołania tej funkcji zyska więcej
sensu w przyszłości. Na ten moment warto pamiętać, że w odróżnieniu od
wielu innych języków funkcja main()
nie zostanie wywołana
automatycznie i dlatego jej wywołanie pojawia się w kodzie.
Poniżej znajduje się przykład nieco bardziej skomplikowanego pliku źródłowego języka Python:
def main():
= load_number()
first_user_number = load_number()
second_user_number
print(sum_numbers(first_user_number, second_user_number))
def load_number():
return int(input("Enter a number: "))
def sum_numbers(a, b):
return a + b
if __name__ == '__main__':
main()
Zadania dodatkowe
💥 Zadanie dodatkowe 1 💥
Napisz program, który wczyta od użytkownika dwa teksty i w osobnej funkcji sprawdzi, czy są one anagramami.
💥 Zadanie dodatkowe 2 💥
Napisz program, który wczyta od użytkownika liczbę n
i
obliczy wartość silni \(n!\). Wyniki
pośrednie zapisz na liście, której zawartość zostanie następnie
wyświetlona wraz z końcowym wynikiem obliczeń. Obliczenie silni powinno
zostać wykonane w funkcji, która powinna zwrócić zarówno wspomnianą
listę, jak i obliczoną wartość do kodu wywołującego.