Python

Krótki, praktyczny, podstawowy samouczek z języka Python.

Przeprowadzimy Cię od najprostszych tematów takich jak "czym jest Python i skąd go wziąć" przez podstawowe pojęcia i zastosowania aż po przykłady użycia zewnętrznych bibliotek, które otwierają drzwi do prawdziwego oblicza programowania :)

Autorem tego samouczka są Mateusz Legięcki i Joanna Ziemska

Wstęp

Jeśli tu jesteś, to prawdopodobnie jest to Twój pierwszy kontakt z programowaniem i wiesz tylko mniej więcej na czym to polega. Jeśli tak nie jest, to nie musisz się martwić, ukończysz ten samouczek błyskawicznie i od razu przejdziesz do potwierdzenia swojej wiedzy rozwiązując zadania.

Nie przejmuj się, jeśli nie zrozumiesz czegoś ze wstępu, ale z czasem zrozumiesz jeśli nie będziesz się zrażać i będziesz czytać dalej.

Czym jest Python?

Python to język_skryptowy, co w jego przypadku oznacza możliwość interakcji z użytkownikiem i bardzo rozbudowane funkcjonalności. Języki skryptowe odróżniają się od innych tym, że do uruchomienia skryptu nie wystarczy on sam, potrzebna jest jeszcze aplikacja, nazywana interpreterem, która potrafi ten skrypt uruchomić. Za to nie musimy tych programów kompilować i zawsze możemy zobaczyć ich kod źródłowy.

Czemu Python?

Ten język ma dosyć naturalną składnię, co oznacza tyle, że właściwie piszemy komendy w języku podobnym do angielskiego i Python to robi, bez nadmiernego przeładowania składni nawiasami i znakami przestankowymi. Dodatkowo, Python posiada domyślnie duży zasób funkcjonalności i naprawdę wiele dodatkowych bibliotek dostępnych w sieci, co daje nam szeroki wybór narzędzi już dostępnych w samym języku bez konieczności ich własnego implementowania. Niezależnie od bogactwa gotowych funkcji w pythonie,  w tym samouczku lub zadaniach napiszemy pewnie niejeden program który w Pythonie już jest (jak chociażby sortowanie listy).

 

Przygotowanie

Na samym początku warto zaznaczyć, że jeśli jakakolwiek część samouczka jest dla Ciebie niejasna możesz do nas napisać na adres python@davinci.mimuw.edu.pl. Jeśli problem będzie leżał w zadaniu, wtedy skontaktuj się z autorem zadania (na dole każdej strony z zadaniem jest link), postaramy się pomagać indywidualnie jeśli tylko będzie to możliwe. Ważne żeby nie zrazić się na samym początku, potem już idzie z górki :)

Jeśli przypadkiem zainstalowałeś Pythona i masz pewność, że działa możesz spokojnie pominąć tą stronę. Jak już wspominaliśmy, do uruchomienia skryptu napisanego w Pythonie niezbędne jest posiadanie programu który go uruchomi. Program ten to interpreter, co oznacza, że program jest interpretowany "na żywo" w momencie jego wykonywania (nie, nie musisz tego na razie rozumieć). Pythona najlepiej pobrać z oficjalnej strony https://www.python.org/

UWAGA!

Istnieją dwie aktualne wersje Pythona: 2 i 3. Wersja 3 jest poprawioną 2 i zawiera nowe przydatne fukncjonalności. Istnieje wiele dodatkowych pakietów, które przenoszą programy z wersji 2 do 3. Może się też zdarzyć, że dodatkowe pakiety są niedostępne w którejś z wersji (częściej w wersji 3, ponieważ jest nowsza a niektórzy twórcy porzucili swoje pakiety lub po prostu nie wydali ich na którąś z wersji). Nasz  samouczek zawiera przykłady w wersji 2, ale w miarę możliwości wskażemy różnice z wersją 3.

Instalacja

Jeśli używasz systemu operacyjnego z rodziny Linux, najprawdopodobniej Pythona w wersji 2 masz domyślnie zainstalowanego i gotowego do pracy. Jeśli nie, zainstaluj go w sposób odpowiedni dla swojego systemu (instrukcje znajdziesz na stronie python.org).

Jeśli zaś używasz Windowsa, instalator z wyżej podanej strony zrobi wszystko automatycznie. Polecamy mimo wszystko nie zmieniać domyślnej lokalizacji instalacji Pythona.

Na komputery z systemem MacOS X również istnieje instalator, który także nie powinien sprawić problemów.

Sprawdź czy działa (Hello World)

Aby sprawdzić czy Python został poprawnie zainstalowany uruchom konsolę (na systemach MacOS i linux) lub znajdź pythona wśród zainstalowanych programów (na Windows).

Na linuksie na pewno jest też dostępny program terminalowy, n.p. gnome-terminal, konsole, xterm lub podobny. Jeśli twoja dystrybucja nie ma żadnego z tych programów, to na pewno informuje na swojej stronie jaki program realizuje tę funkcję.

Na Windowsie konsolę otwiera się prawie równie prosto. W dowolnym folderze należy wcisnąć klawisz Shift oraz kliknąć prawy przycisk myszy. Powinna pojawić się nowa opcja umożliwiająca uruchomienie konsoli. (jeśli robisz to poraz pierwszy prawdopodobnie czcionka będzie praktycznie niewidoczna, kilkając prawym przyciskiem na pasek stanu możemy to zmienić klikając "domyślne" lub "właściwości").

UWAGA:

Składnia Pythona, w przeciwieństwie do innych języków programowania, nie jest obojętna na znaki białe, co dla Ciebie znaczy tyle, że musisz bardzo uważać na wszelkie spacje, tabulatory na początku linii oraz na "entery". Jak na razie na początku linii nie powinno być żadnego znaku białego. Pomagają tego pilnować lepsze edytory tekstu (o czym niżej).

Po otwarciu konsoli należy wpisać słowo python. To otworzy nam interaktywny interpreter Pythona. Jeśli nic się nie stało oznacza to najprawdopodoniej brak dopisanego folderu instalacji Pythona do  ścieżki środowiskowej. W przypadku Windowsa należy we właściwościach komputera znaleźć "Zmienne środowiskowe" i edytując zmienną PATH dopisać na końcu średnik a następnie ścieżkę do katalogu bin w miejscu w którym zainstalowaliśmy Pythona. Sprawdź jak to zrobić w sposób odpowiedni dla Twojego systemu, w internecie znajduje się wiele instrukcji jak to zrobić.

No dobrze, mamy uruchomiony interpreter ale co z tego? Właściwie to bierzmy się za pierwszy program, nie ma na co czekać. Nie odchodząc od tradycji pierwszym co napiszemy będzie "Hello World" czyli program który potrafi tylko (lub aż) wyświetlić takie przywitanie ze światem.

Wpisz

print "Hello World"

 

i wciśnij enter

Co się stało? Jak widać na ekranie pojawił się napis "Hello world". Czemu? To widać na pierwszy rzut oka na naszą pierwszą linijkę. Polecenie print każe Pythonowi "wydrukować" na ekranie to co następuje dalej czyli napis "Hello World". Użyliśmy tutaj cudzyłowu - zapamiętaj, napisy zawsze należy umieszczać wewnątrz nich! Inaczej program się nie wykona. Zresztą sam sobie sprawdź :P i pamiętaj, że jeśli masz ochotę odejść od samouczka i poeksperymentować na własną rękę jest to jak najbardziej wskazane.

 

Interpretera możesz używać też jak kalkulatora. Oto podstawowe operacje (możesz także używać nawiasów do określania kolejności wykonywania działań):

  • + dodawanie
  • - odejmowanie
  • / dzielenie (patrz uwaga poniżej).
  • // dzielenie całkowite bez reszty
  • % reszta z dzielenia
  • * mnożenie
  • ** potęgowanie

 

UWAGA:

przy operacjach dzielenia jest bardzo istotna różnica w wersjach Pythona 2 i 3. W wersji 2  znak / działa różnie w zależności od tego czy mamy do czynienia z liczbą całkowitą czy nie. Dla spójności z wynikami w wersji 3 warto  zawsze pisać liczby całkowite w formie 8.0 zamiast 8 aby uzyskać ten sam  wynik dzielenia w obu wersjach . Jest to związane z typami o czym będziemy mówić w rozdziale Typy.

 

Pewnie zastnawiasz się czy wszystkie programy pisze się tak w interaktywnym interpreterze? Otóż wcale niekoniecznie. Programy wpisane w interpreterze nie są nigdzie zapisywane, a po co komu program który znika po wyłączeniu okienka z terminalem? Jeśli chcesz zachować treść programu, wystarczy zapisać w zwykłym pliku tekstowym. Otwórz notatnik (lub inny edytor _tekstowy_) i wpisz to samo co wpisałeś w interpreterze, zapisz plik koniecznie z rozszerzeniem .py, w folderze w którym zapisałeś plik otwórz terminal i wpisz python nazwa_pliku_który_przed_chwilą_zapisałeś.py

 

Powinien wyświetlić się napis tak samo jak za poprzednim razem.

 

Jeśli przeszedłeś przez cały ten wstęp, masz już działający interpreter Pythona i wiesz jak napisać i uruchomić pierwszy program. Gratulacje!

 

Programy pomagające programować

Ta sekcja nie jest obowiązkowa, wiele osób na początek pomija dopasowanie sobie środowiska pracy odkładając to na moment, w którym już wiadomo co się w programowaniu lubi, a czego nie. Ale warto zrobić to od razu, dzięki temu wejście w świat programowania będzie trochę lżejsze, ponieważ dobre edytory pomagają pilnować odpowiedniej składni a niektóre mają jeszcze mnóstwo innych przydatnych funkcji.

Na początek polecamy któryś z prostych edytorów tektsu, takich jak gedit lub kwrite które są najprawdopodobniej zainstalowane w Twojej dystrybucji linuksa. Są też takie edytory jak Geany (darmowy) czy Sublime Text (komercyjny), które oprócz typowych dustrybucji linuksa można zanstalować na systemach Mac OS i Windows. Oba te programy potrafią kolorować odpowiednie fragmenty kodu tak, by program wyglądał bardziej intuicyjnie i potrafią też uruchomić od razu program napisany w Pythonie co znacznie przyśpiesza testowanie i jest bardzo wygodne.

Bardziej rozbudowanym programem jest PyCharm którego możliwości nawet w darmowej wersji są zdecydowanie większe niż wspomnianych edytorów.  Potrafi informować o błędach w programach i sugerować poprawki, upomina też użytkownika jeśli jego kod nie jest zgodny z konwencjami "ładnego" kodu w pythonie. Jeśli lubisz tak rozbudowane edytory, będziesz pewnie zadowolony z takiego zintegrowanego środowiska, jednak tak  rozbudowany interfejs może powodować, że na początku trudniej będzie Ci się odnaleźć w gąszczu funkcji.

Wybór należy do Ciebie, zachęcamy do spróbowania choć jednego z tych edytorów, ale jeśli przytłacza cię zbyt wiele opcji w nich dostępnych, nie trać teraz na to czasu, lepiej przejdźmy tymczasem do dalszej  części samouczka.

Podstawy podstaw

Poprzedni program który wyświetlał napis był raczej mało użyteczny. Napis "Hello world" wyświetlił się i na tym koniec. Jeśli chcieli byśmy raz jeszcze go wyświetlić ponownie musieli byśmy wpisać: print "Hello world" Nie jest to specjalnie uciążliwe, bo napis jest bardzo krótki, załóżmy więc że chcemy wyświetlić większą ilość tekstu dwa razy.

"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed odio sed ante consequat vestibulum. Donec pellentesque non orci in viverra. Sed quis ornare est."

Co z takim tekstem? No niezbyt fajnie wpisywać go więcej niż raz prawda? Tak, owszem, można go skopiować, ale kopiowanie podczas programowania  często prowadzi do błędów, więc lepiej go unikać. Co więc jeśli chcemy powyższy tekst wyświetlić dwa razy bez kopiowania tego kodu?

print "Lorem ipsum ..."

Już śpieszę z pomocą. Możemy sobie ten tekst zapisać w naszym programie pod jakąś nazwą (trochę tak jak byśmy zapisali go w pliku) i używać go za pomocą jego nazwy. Wydaje mi się że to dość naturalne i intuicyjne. Przykład:

tekst = "Lorem ipsum dolor sit amet, ..."
print tekst
print tekst

A teraz przeanalizujmy ten kod:
W linicje pierwszej mówimy że tekst to będzie pewna #zmienna która ma być równa "Lorem ipsum ..."

Wszędzie tam, gdzie wpiszemy  tekst jako nazwę zmiennej będzie tak jak byśmy wpisali "Lorem ipsum ..."

Zwróć uwagę na brak cudzysłowów. Jeśli by tam były, to interpreter wyświetlił by słowo "tekst" zamiast "Lorem ipsum ..."

Tak samo możesz zrobić z liczbami, co pozwala zapisać sobie wynik jakiegoś bardzo długiego wyrażenia, żeby móc użyć go w jakimś miejscu w programie np. wyobraźmy sobie sytuację w której liczymy całkowity koszt podróży samochodem, z przejazdem przez autostradę i z przeprawą promową.

Mamy do przejechania najpierw 67 km do autostrady, następnie 124 km autostradą, potem drogą gruntową 11.7 km do miejsca przeprawy promowej.

Koszt paliwa to 8.50
Cena za kilometr na autostradzie to 0.17
Koszt przeprawy to 50

Załóżmy, że samochód na zwykłej drodze spala 0.1 litra na kilometr 0.15 na autostradzie i 0.18 na drodze gruntowej.

Chcemy podzielić koszty na kilka osób, ale nie wiemy jeszcze ile osób zdecyduje się nam towarzyszyć. Policzmy więc sobie sam koszt i zapiszmy go na zmienną.

paliwo = 8.5 * (67*0.1 + 124*0.15 + 11.7*0.2)
autostrada = 124*0.17
prom = 50
koszt = paliwo + autostrada + prom
print koszt
print koszt / 2
print koszt / 3
print koszt / 4
print koszt / 5

Jak widzisz jest to całkiem praktyczne i użyteczne, bo  nie ma sensu zabierać aż 4 dodatkowych osób (koszt podróży nie będzie o wiele niższy niż przy zabraniu 3 a w samochodzie będzie więcej miejsca). Możesz też wyświetlić sobie ile łącznie zapłacisz za paliwo, ile za przejazd autostradą i ile za przeprawę promową.

Zmienne mogą przechowywać dla nas różne rzeczy, wiesz już o liczbach i o napisach, w kolejnym rozdziale powiemy nieco więcej o #typach

Typy

O typach wspominaliśmy już dwa razy, warto więc wyjaśnić co to takiego. Zacznijmy może od stwierdzenia, że Python jest językiem z dynamicznym typowaniem, co jak na razie znaczy dla Ciebie tylko tyle, że możesz napisać

jakas_zmienna = "To jest jakis napis" 
print jakas_zmiennna 
jakas_zmienna = 8.5 
print jakas_zmienna

I program zadziała poprawnie, nie przejmując się tym, że początkowo jakas_zmienna była napisem a zaraz potem była liczbą.

Tak więc typ to rodzaj wyrażenia, podstawowe typy zmiennych to:

Wartość logiczna

Jest to wartość prawda (reprezentowana przez napis True) lub fałsz (odpowiednio False)
Używana do określania zawartości, która może przyjmować tylko dwie możliowe wartości, takich jak: lubie_placki = True

Napis

Ten typ już poznałeś

Liczba całkowita

Służy do zapisu liczb takich jak 1 lub -115741
UWAGA: przypominamy, że operacja dzielenia dwóch liczb całkowitych w Pythonie 2 daje wynik również będący liczbą całkowitą!

Liczba zmienno przecinkowa

Jak sama nazwa wskazuje są to liczby takie jak 1.57524 lub nawet 18.0
Ważne by używać kropki do ich zapisu

Bardziej złożone typy, o których wystarczy wiedzieć że są, bo omówimy je na kolejnej stronie:

(umieszaczamy je tu, aby łatwo było przypomnieć sobie informacje o wszystkich typach)

Lista

Zawiera więcej uporządkowanych elementów dowolnego typu
Tworzy się ją za pomocą nawiasów kwadratowych, a kolejne wartości oddziela przecinkami
lista = [1,2,3,4,"napis", True, False, 8.5, 11]

Słownik

Bardzo użyteczny typ
Nazwa jest odpowiednia do tego jak działa, ma bowiem "klucz" i "wartość"
slownik = {"jablecznik" : "ciasto z jablek", "czy lubisz jablecznik" : True}

 

Skoro znamy już proste typy, możemy przejść do nieco bardziej złożonych typów danych.

Struktury danych

Struktury danych są bardzo istotnym elementem całego informatycznego świata. Każda rzecz jest jakąś daną zapisaną w jakiejś mniej lub bardziej skomplikowanej strukturze. Najprostszym przykładem może być liczba zapisana na zmiennej x=8. Jednak w praktyce zapisywanie wszystkiego na zmienne jest zupełnie niewygodne. Wyobraźmy sobie, że mamy do zapisania 100 kolejnych wyników jakiegoś doświadczenia. Dla przykładu możemy myśleć o bardzo życiowej (dla hodowców drożdży ;) sytuacji: mamy hodowle drożdży i badamy jak wysokie stężenie alkoholu są w stanie znieść, bez większego problemu z mnożeniem się. Możemy oczywiście napisać:

d0=10
d1=8
d2=10
d3=12
d4=6
d5=8
d6=7
d7=12
d8=10
d9=16
d10=16
d11=9
d12=14
d13=9
d14=11
d15=17
d16=18
d17=9
d18=5
d19=17
d20=11
d21=17
d22=7
d23=7
d24=12
d25=9
d26=5
d27=18
d28=6
d29=7
d30=9
d31=9
d32=6
d33=8
d34=8
d35=11
d36=13
d37=16
d38=8
d39=8
d40=12
d41=5
d42=18
d43=15
d44=17
d45=18
d46=7
d47=8
d48=13
d49=5
d50=12
d51=11
d52=11
d53=12
d54=5
d55=17
d56=7
d57=15
d58=10
d59=14
d60=18
d61=5
d62=8
d63=9
d64=10
d65=14
d66=15
d67=13
d68=16
d69=14
d70=17
d71=16
d72=10
d73=7
d74=14
d75=15
d76=17
d77=11
d78=10
d79=18
d80=18
d81=9
d82=12
d83=18
d84=12
d85=13
d86=7
d87=10
d88=16
d89=12
d90=16
d91=8
d92=11
d93=15
d94=8
d95=7
d96=7
d97=10
d98=13
d99=13

Ten zapis już na pierwszy rzut oka nie wygląda najlepiej: trzeba wymyślić bardzo dużo nazw zmiennych oraz trzeba te nazwy zapamiętać, żeby mieć jak sprawdzić jaką tolerancją cechuje się szczep hodowany w cylindrze51518155. W tym wypadku pamiętamy, że wszystkie zmienne wyglądają podobnie i możemy wpisać nazwę odpowiedniej zmiennej aby wyświetlić jej wartość. Ale co jeśli chcieli byśmy dowiedzieć się jaka jest maksymalna tolerancja? #Funkcja max(x1, x2, x3, ...) #zwraca maksymalną wartość z podanych zmiennych.

O funkcjach więcej dowiemy się w odpowiednim rozdziale, ale już w tym miejscu warto o nich wspomnieć . Na razie przyjmijmy, że funkcja to zbiór poleceń zapisany pod pewną nazwą (trochę jak zmienna), może przyjmować argumenty czyli w tym wypadku argumentami są x1, x2 , x3 i tak dalej (zmienne które zawierają liczby). Funcja może też coś zwrócić. Łatwo zrozumieć zwracanie jeśli spojrzymy na prosty  przykład:

1+2 zwróci nam 3, czli jeśli wpiszemy wynik = 1+2, to zmienna wynik będzie równa 3, tak samo możemy zrobić z funkcją max(1,2) która zwróci nam liczbę 2, więc po wpisaniu wynik = max(1,2) ustawi wartość zmiennej na 2. Nie wszystkie funkcje muszą coś zwracać i nie wszystkie muszą przyjmować jakieś argumenty. Więcej o funkcjach powiemy na następnej stronie.

Lecz wpisanie:

max(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,d18,d19,d20,d21,d22,d23,d24,d25,d26,d27,d28,d29,d30,d31,d32,d33,d34,d35,d36,d37,d38,d39,d40,d41,d42,d43,d44,d45,d46,d47,d48,d49,d50,d51,d52,d53,d54,d55,d56,d57,d58,d59,d60,d61,d62,d63,d64,d65,d66,d67,d68,d69,d70,d71,d72,d73,d74,d75,d76,d77,d78,d79,d80,d81,d82,d83,d84,d85,d86,d87,d88,d89,d90,d91,d92,d93,d94,d95,d96,d97,d98,d99)

 kosztuje nas sporo pracy, więc na pewno jest prostszy sposób, aby osiągnąć ten sam efekt, bez takiego wysiłku.

Zauważmy, że nazwy zmiennych ustaliliśmy według dość logicznego wzoru dN gdzie d jest skrótem od drożdże a N to numer hodowli. To sugeruje nam, że skoro coś się powtarza wiele razy to można to w jakiś sposób pominąć i pamiętać tylko raz. Taka chęć uproszczenia zapisu wyników prowadzi nas do dużo wygodniejszej struktury danych - listy.

 

Listy

Lista jest strukturą danych, w której możemy w ciągu zapisać dane. Dzięki niej nie musimy definiować wielu zmiennych. Wystarczy, że na liście zapiszemy nasze dane:

d=[10, 8, 10, 12, 6, 8, 7, 12, 10, 16, 16, 9, 14, 9, 11, 17, 18, 9, 5, 17, 11, 17, 7, 7, 12, 9, 5, 18, 6, 7, 9, 9, 6, 8, 8, 11, 13, 16, 8, 8, 12, 5, 18, 15, 17, 18, 7, 8, 13, 5, 12, 11, 11, 12, 5, 17, 7, 15, 10, 14, 18, 5, 8, 9, 10, 14, 15, 13, 16, 14, 17, 16, 10, 7, 14, 15, 17, 11, 10, 18, 18, 9, 12, 18, 12, 13, 7, 10, 16, 12, 16, 8, 11, 15, 8, 7, 7, 10, 13, 13]

a następnie użyjemy tej samej funkcji co poprzednio, jako argument wprowadzając listę, czyli pisząc max(d). Dzięki temu jak interpreter python'a jest skonstruowany, takie użycie daje pożądany efekt.

A co jeśli interesuje nas konkretna, np. siedemnasta wartość z listy? Możemy wpisać to:

print d[16]

dzięki temu dostaniemy wartość siedemnastego elementu z listy. Proste? Nie? Coś nie gra? Już tłumaczę: w programowaniu najczęściej numeracja nie zaczyna się od 1 tylko od zera, stąd w nawiasach kwadratowych jest liczba 16 a nie 17. Przy okazji, te liczby oznaczające pozycję w liście będziemy nazywać ich indeksami. Teraz jasne? No to super, wiemy, że w zbiornikach od 10 do 15 są specjalne, bardzo drogie gatunki drożdży i chcieli byśmy zobaczyć jak wygląda ich tolerancja. Możemy jak poprzednio wpisać

print d[9]
print d[10]
print d[11]
print d[12]
print d[13]
print d[14]

ale to aż 6 linijek kodu który jest bardzo podobny. Skoro tak jest, to chyba spodziewasz się już, że i na to jest jakaś prostsza metoda. Owszem, oto ona: w nawiasach kwadratowych możemy wpisać zakres żeby wybrać fragment naszej długiej listy

print d[9:15]

I tu znów mamy pewną dziwną sytuację związaną z indeksami w liście. Już tłumaczę: pierwszą liczbą jest numer początkowego elementu, drugą liczbą jest numer do którego chcemy wybrać fragment listy (więc musi być o jeden większy niż ostatni numer cylindra który nas interesuje). Może to być mało intuicyjne ale tak już jest.

O naszych cylidnrach wiemy jeszcze jedną rzecz: są ustawione od najstarszego do najnowszego. Więc pewnie chcemy zobaczyć czy starsze hodowle radzą sobie lepiej niż nowe (powiedzmy do 5 hodowli). Możemy więc napisać tak jak poprzednio, ale możemy też zupełnie pominąć jedną z liczb zakresu, wtedy domyślnie brany jest początek lub koniec (w zależności od tego, którą liczbę pominiemy):

print d[:5]

Nie jest to może coś bardzo użytecznego samo z siebie ale warto o tym pamiętać (bo jak zwykle zaraz się przyda).

Logiczne wydało Ci się pewnie, że numeracja jest od lewej do prawej strony listy. Ale nic nie stoi na przeszkodzie, aby to odwrócić - robimy to za pomocą znaku minus

print d[-1]

ten kod weźmie ostatni element listy. Tu znów jest pewna niespójność, bo wpisujemy minus jeden... no cóż, nie istnieje coś takiego jak ujemne zero więc tak po prostu musi być.

Skoro już umiesz wybierać konkretne wartości z listy możesz też zaktualizować wyniki badań z cylindra 12, okazuje się że tolerancja spadła o 0.1. Oto jak można to zrobić:

d[11] = d[11] - 0.1

Zajmijmy się najpierw tym, co jest po znaku równości. Wybieramy 12 element z naszej listy i odejmujemy od niego 0.1. Następnie przypisujemy tą wartość w stare miejsce tak samo jak robiliśmy to ze zwykłymi zmiennymi. Wygodne, prawda?

Dostaliśmy przed chwilą od zaprzyjaźnionego laboratorium nowe drożdże, już są w cylindrze i mamy już pierwsze wyniki badań ich tolerancji. Ale co teraz? Trzeba by je jakoś dopisać do naszej listy. Robimy to za pomocą #metody append,  jako argument podając wartość jaką chcemy dopisać na końcu listy.

UWAGA metoda jest po prostu funkcją, tyle, że "należy" do obiektu (w tym wypadku do listy). Wywołując taką metodę "mówimy" liście, że ma dopisać sobie jeszcze jedną wartość.

d.append(14)
print d

Jak widać jest to dość proste, powyższa metoda zmodyfikowała naszą listę tak aby zawierała kolejny element.

Warto od razu przedstawić po krótce wszystkie dostępne metody (jednak te powyższe na codzień są zazwyczaj wystarczające):

  • Metoda extend służy do rozszerzenia naszej listy o jakąś inną listę.
  • Metoda insert służy do wstawienia wartości w dowolne miejsce na liście. Pierwszy argument to numer, który chcemy aby nasz wstawiany element (drugi argument) miał w kolejności w liście.
  • Metoda remove usuwa wartość z listy (jeśli wartość występuje więcej niż raz, usuwana jest ta, która na liście występuje jako pierwsza).
  • Metoda pop służy również do usuwania, ale jako argument przyjmuje numer elementu listy (zwany także najczęściej jako indeks) a dodatkowo zwraca nam wartość tego elementu. Uwaga, możemy nie podawać tej metodzie żadnego argumentu, wtedy domyślnie z listy jest wyrzucany ostatni element.
  • Metoda index służy do szukania wartości na liście, zwraca listę z numerami miejsc, na których występuje poszukiwana przez nas wartość.
  • Metoda sort służy do posortowania listy, może przyjmować argumenty, ale jak na razie zostawmy ją w jej najprostszej postaci.
  • Metoda reverse odwraca kolejność listy.

Dobra wiadomość jest taka, że znajmość tych metod jest w zupełności wystarczająca do pełnego wykorzystania możliwości list.

Oprócz metod, dla list dostępnych jest też wiele funkcji pomocniczych. Np. fajną funkcją, o której warto pamiętać jest range. Funkcja ta generuje listę o danej długości z kolejnymi liczbami całkowitymi od zera.

lista = range(15)
print lista

Słowniki

Kolejną wygodną strukturą danych są słowniki. Pozwalają nam uporządkować dane według kategorii, w formie "klucz:wartość". Zobaczmy to na przykładzie, którym będzie szczep drożdży, który otrzymaliśmy na płytkach z pożywką agarową (specjalne pojemniki, w których hoduje się mikroorganizmy). Na każdej z nich jest inna ilość kolonii (skupisk). Wpiszmy je do słownika w postaci "płytka1":101...

dictionary = {'plytka1':101, 'plytka2':201, 'plytka3': 302, 'plytka4':102}

Wygląda to pięknie, wszystko jest uporządkowane, dużo danych na jednej zmiennej... ale jak wyjąć stąd jakieś dane? Jeśli spróbujemy zrobić to tak samo jak z listami, dostaniemy błąd. Wyjątkiem jest, gdy kluczem jest liczba całkowita.

Do wartości w słowniku dostajemy się używając klucza, więc aby dowiedzieć się co mamy na konketnej płytce należy wpisać:

print dictionary['plytka1']

Jeśli chcemy zobaczyć cały słownik, robimy to w taki sam sposób jak w przypadku listy lub zmiennej.

print dictionary

Nasz słownik może zawierać bardzo dużo kluczy, gdy nie jesteśmy pewni, czy jest tam akurat ten którego szukamy oraz nie możemy znaleźć go przy wywołaniu "dictionary['plytka1']", może się okazać, że po prostu zrobiliśmy literówkę we wpisywaniu nazwy klucza. Dlatego, aby przejrzyście zobaczyć nazwy wszystkich kluczy możemy użyć metody keys().

Jeśli chcemy wiedzieć, czy jakaś płytka zawierała 20 koloni, to wtedy używamy metody values() .

Zobaczmy jak to wygląda w praktyce:

print dictionary.keys()
print dictionary.values()

UWAGA: Pamiętaj, że kolejność wstawiania kluczy do słownika nie musi odpowiadać kolejności wartości wyświetlonych dzięki tym metodom.

Teraz zastanówmy się, co jeśli zdecydujemy się założyć nową hodowlę na płytce... Trzeba wtedy dodać ją do naszego słownika. Niestety nie zadziała tu funkcja append(), ale możemy to zrobić w inny (może nawet prostszy) sposób:

dictionary['plytka5']=0

Ostatni przypadek jaki może sie nam zdarzyć z naszymi grzybami, to, to że mimo naszych najlepszych starań nie wyrosną. Podobnie jak w przypadku list użyjemy del na nieudanym doświadczeniu.

Tak samo możemy postąpić jeśli znudzi nam się hodowanie drożdży na płytkach z pożywką.

print dictionary
del dictionary['plytka5']
print dictionary
del dictionary
print dictionary

Zawarte tu informację, na pewno ułatwią Ci dalszą pracę z pisaniem kodu w pythonie, szczególnie w sytuacjach, kiedy potrzebne Ci będzie katalogowanie jakichś informacji. Wykorzystaj je we własnych programach.

Pod koniec tego samouczka pokażemy też specjaną, ulepszoną wersję słowników.

Powtarzanie wielokrotnie tych samych operacji (pętla for)

Okazuje się, że wyniki pomiarów tolerenacji z poprzedniego rozdziału były trochę zawyżone, bo aparatura badawcza była od początku rozregulowana. Musisz to poprawić! Ale chyba nie uśmiecha Ci się ręcznie zmieniać 100 wartości? Z pomocą przychodzi pętla for ,a przy okazji też przychodzi Ci się spotkać z wcięciami tekstu i operowaniem znakami białymi. Brzmi strasznie, też tak na początku myślałem, ale w rzeczywistości szybko się o tym zapomina i wszystko dzieje się bez bólu. Zobaczmy więc kawałek kodu, który zrobi za nas tą żmudną pracę:

for i in range(len(d)):
    d[i] = d[i]*0.1

Całe DWIE linijki kodu zamiast 100! Cudownie prawda? Fajnie było by jeszcze rozumieć co się stało, a wiedzy do przyswojenia jest naprawdę dużo w tych dwóch linijkach, więc zacznijmy od prostszego przykładu, w którym chcemy wyświetlić sobie pojedynczo wyniki:

for element in d:
    print element

Mówimy, że dla każdego (for) elementu z (in) listy nazwanej przez nas wcześniej literą d chcemy by został wyświetlony element.

Instrukcja for tworzy tymczasową zmienną, która kolejno przyjmuje wartości z listy. W naszym wypadku ta zmienna nosi nazwę element, możemy używać jej jako normanej zmiennej (z pewnym bardzo istotnym zastrzeżeniem, o którym za moment).

Bardzo istotne jest wcięcie kodu (może ono być zrobione przez dowolną ilość spacji lub tabulatorów, ale koniecznie trzeba trzymać się raz przyjętego schamatu. Najbardziej zgodne z normami jest użycie 4 spacji (co będziemy praktykować w dalszej części samouczka). Wygodniej jednak jest używać pojedynczego tabulatora (część edytorów i tak zamini go na cztery spacje), ponieważ to tylko jedo naciśnięcie klawisza i od razu widać jeśli użyje się o jeden za dużo).

Te wcięcia kodu możemy sobie porównać do struktury folderów:

Wewnątrz tego wcięcia możemy normalnie programować, definiować zmienne, pisać wyrażenia arytmetyczne, odwoływać się do zmiennych zdefiniowanych wcześniej. Wszystko "wewnątrz" tego wcięcia będzie zrobione za każdym razem kiedy zmienna element przyjmie kolejną wartość z listy. Najważniejszą różnicą jest to, że zmienna "element" w naszym programie po wyjściu z pętli będzie miała wartość z ostatniego obrotu pętli.

 

for element in [1,2,3,4,5]:
  print element
print "zrobimy sobie odstep"
print element

Wyświetli nam najpierw wszystkie liczby z listy, a potem jeszcze raz piątkę.

A teraz powróćmy do naszego zadania. Używamy tam pewnej "sztuczki" żeby móc modyfikować wartości na liście. Jak już powinieneś/powinnaś wiedzieć funkcja range generuje listę liczb całkowitych od zera aż do osiągnięcia żądanej długości. Zaś funkcja len jest dość uniwersalną funkcją, która wraca nam długość tego co podamy jako argument czyli:

print len([851, 1, 58])

Wyświetli nam liczbę 3, bo na liście znajdują się dokładnie 3 elementy. Korzystając z funkcji range możemy wygenerować listę o tej samej długości a jej elementów użyć jako indeksów w naszej liście, którą chcemy zmienić. Jest to bardzo ważny schemat postępowania jeśli chcemy modyfikować wartości listy.

W następnym rozdziale poznamy instrukcje warunkowe. A zaraz potem wrócimy do pętli poznając pętlę warunkową.

Instrukcje warunkowe

Instrukcje warunkowe pozwalają programowi "reagować" na różne sytuacje.

Weźmy sobie coś prostego na sam początek:

zmienna = 8
if zmienna > 5:
    print "Zmienna jest wieksza niz 5"

Konstrukcja instrukcji warunkowej jest dość logiczna i prosta:

if (czy) dowolne wyrażenie, które zwraca wartość logiczną (warunek jest spełniony):

Następnie robimy wcięcie w kodzie i piszemy co ma się stać jeśli warunek jest spełniony.

Jeśli nasz warunek nie zostanie spełniony również możemy coś zrobić. Odpowiada za to instrukcja "else"

zmienna = 8
if zmienna == 15:
    print "Zmienna jest rowna 15"
else:
    print "Zmienna nie jest rowna 15"

Warto wspomnieć w tym miejscu, że jeśli chcemy sprawdzić czy coś jest równe używamy podwójnego znaku równości (==). Czemu dwóch, a nie jednego? Powód jest prosty, pojedycznym (=) przypisujemy zmiennym wartości, podczas gdy podwójny znak == sprawdza, czy dwie wartości się różnią, bez zmiany ich zawartości.

Jak widać w tym przypadku sprawdzamy czy nasza zmienna jest równa 15, jeśli jest to mówimy że jest, w przeciwnym przypadku mówimy że nie jest równa 15.

Pewnie zastanawiasz się, co w sytuacji kiedy chcemy sprawdzić kilka warunków pod rząd i pewnie masz już na to swój (na razie jeszcze nie idealny) pomysł, który wygląda tak:
 

zmienna = 8
if zmienna == 1:
    print "Wartosc zmiennej to jeden"
else:
    if zmienna == 2:
        print "Wartosc zmiennej to dwa"
    else:
        print "Wartosc zmiennej nie jest ani jeden ani dwa"

Jeśli nie wpadłeś na to, że we wcięciu można zrobić jeszcze jedną instrukcję, która ma wcięcie to musisz wiedzieć, że można to robić. Jest to bardzo częsta sytuacja i kod w praktyce ma wiele poziomów wcięć. Jednak istnieje rozwiązanie powyższego problemu, które jest o wiele bardziej estetyczne: Python daje nam jeszcze jedną instrukcję "elif", dzięki której sprawdzimy kolejne warunki.

zmienna = 8
if zmienna == 5:
    print "Zmienna jest rowna 5"
elif zmienna == 8:
    print "Zmienna jest rowna 8"
elif zmienna > 5:
    print "Zmienna jest rowna 5 ale nie jest rowna 8"
else:
    print "Zmienna jest mniejsza od 5"

To już chyba najbardziej skomplikowany przykład. Jeśli przyjrzysz się warunkom to:

  1. zmienna == 5 jest nieprawdziwy
  2. zmienna == 8 jest prawdziwy
  3. zmienna > 5 jest prawdziwy

Co w tym wypadku się stanie? Zostanie wykonany blok kodu (tzn. to co znajduje się we wcięciu) pod warunkiem który zostanie spełniony jako pierwszy, ponieważ warunki sprawdzane są po kolei a Python jest leniwy i jak uda mu się jakiś znaleźć to reszty już nie sprawdza.

 

Sprawdź czy potrafisz już rozwiązać zadanie Instrukcje warunkowe !

Pętla warunkowa

Do instrukcji warunkowych możemy zaliczyć pętlę while. Ona, tak jak i pętla "for", również pozwala nam zapisać dużą ilość czynności w kilku linijkach kodu, z tą różnicą, że kończy się dopiero jak warunek zostanie spełniony. używamy jej, gdy chcemy robić coś dopóki jakiś warunek jest spełniony i nie wiemy ile razy dokładnie instrukcje zawarte w pętli powinny się wykonać. Zobaczmy przykład.

x=0
while x<5:
    print "zmienna x wynosi ", x
    x+=1

Co tutaj zrobiliśmy? Na zmienną X przypisujemy najpierw wartość 0, a potem z każdym obrotem pętli, dodamy 1 do zmiennej x, aż wartość x będzie wynosiła 5, wtedy pętla już więcej się nie wykona i program będzie wykonywany dalej.

Dziwny zapis? Tak, zamiast x=x+1 możemy napisac poprostu x+=1, są to zapisy równoważne. Podobnie możemy pisać *=, -=, a nawet /=.

Oczywiście w tak prosty przypadek z łatwością możemy zastąpić pętlą "for", ale znajdziesz w przyszłości przypadki kiedy zwyczajnie jest to niewygodne, a elastyczność zapisu jest w programowaniu bardzo potrzebna.

 

Jak jeszcze możemy używać pętli? A może stwórzmy taką, która nigdy nie kończy działania?

Jak ją zatrzymać?

używając słowa "break" kiedy na przykład zostanie spełniony jakiś warunek wewnątrz pętli

Kiedy jej używać?

Kiedy chcemy żeby na przykład kilka instrukcji w pętli wykonywało się nawet kiedy warunek pętli nie jest spełniony.

Spójrzmy na przykład:

x=0
while True:
    print "To wyswietli sie zawsze gdy warunek jest spelniony"
    if x==5:
        print "zmienna x wynosi ", x
        break
    else:
        print x
    x+=1 

Dodaliśmy tu instrukcję warunkową, wynikiem naszego programu będzie ten sam napis (za wyjątkiem oczywiście dodanego zdania "To wyswietli sie zawsze gdy warunek jest spelniony"), ale zamiast przerywać go poprzez warunek pętli, przerywamy go dopiero konstrukcją break, wywoływaną tylko gdy zostanie spełniony nasz warunek.

To może jeszcze jeden przykład?

x=[1,2,3,4,5]
while x:
    y=x.pop()
    print "ostatnia wartości z listy x to ", y
else:
    print 'koniec'

Gdy wywołamy powyższy kod, otrzymamy wypisane wartości listy x, tylko że od końca, ponieważ metoda pop(), której wynik przypisujemy na zmienną y zwraca ostatnią wartość listy, jednocześnie  ją usuwając, oraz napis "koniec" po skończonej pętli.

Warto dodać, że gdy użyjemy listy jako warunku, domyślnie znaczy on "dopóki są jakieś elementy na liście".

UWAGA: Instrukcje zawarte w "else" dodanym do pętli while, wykonają się jeśli warunek pętli nie zostanie spełniony (czyli po normalnym zakończeniu pętli), ale nie zostaną wykonane jeśli używamy instrukcji "break", wewnątrz pętli.

Możemy również nie pisać else, a nasz program będzie działał niemal tak samo, tyle że instrukcje z bloku else zostaną wykonane nawet w przypadkach, kiedy użyjemy "break".

 

x=[1,2,3,4,5]
while x:
    y=x.pop()
    print y
print 'koniec'

Jak widzisz, nawet pętle warunkowe nie są zbyt trudne. Teraz przejdźmy do kolejnego tematu, jakim są funkcje.

Funkcje

Funkcje są podstawową konstrukcją w programowaniu. Dzięki nim możemy używać fragmentów kodu wielokrotnie w programie. O użyteczności funkcji dowiedziałeś się już korzystając ze sprawdzenia długości listy czy też napisu - pomyśl o ile mniej wygodnie byłoby za każdym razem robić pętle "for" i za każdym jej przejściem do zmiennej dodawać 1.

Na potrzeby tego rozdziału załóżmy sobie, że będziemy często potrzebować policzyć wartość tej funkcji:

\(f(x) = \frac{2*x^3}{8.51}\)

W Pythonie przedstawia się to tak:

x = 15
wynik = (2 * (x**3))/8.51
print wynik

Ale kopiowanie tego i zmienianie zmiennej jest bardzo niewygodne. Możemy zdefiniować sobie funkcję, która jako argument przyjmie x i zwróci nam wartość policzonego wyrażenia:

def f(x):
    return (2 * (x**3))/8.51
 
print f(5)

aby zdefiniować funkcję używamy słowa def, po którym następuje nazwa funkcji. W nawiasach podajemy nazwy kolejnych argumentów (w szczególności, możemy nie podawać ich wcale jeśli nie chcemy). Ciało funkcji oznaczamy tak samo jak w przypadku pętli for lub instrukcji warunkowych, czyli wcięciem w kodzie.

Możemy (ale nie musimy) zwrócić jakąś wartość poprzez użycie return, dzięki czemu możemy zapisać wynik naszego działania do jakiejś zmiennej tak samo jak w przypadku kiedy sprawdzaliśmy długość listy funkcją len. Co bardzo ważne, jeśli dojdziemy do instrukcji "return" funkcja się kończy (nawet jeśli coś "za" słówkiem "return" było)! Możemy też nic nie zwracać, co spowoduje, że nasza funkcja wydawać się może mało użyteczna, ale stosuje się to często w przypadku funkcji działających przez efekty uboczne, które np. wypisują jakieś złożone dane na ekran, albo zmieniają jakiś obiekt (tak jest np. z metodami usuwającymi elementy z listy).

Co bardzo ważne, instrukcje wewnątrz ciała funkcji nie wykonają się jeśli nie wywołamy tej funcji. Zobacz jak zadziała ten kod:

def funkcja():
    print "wykonalo sie"

jak widzisz, nic kompletnie się nie stało. Dopiero gdy napiszesz "funkcja()" zostanie wyświetlony napis "wykonalo sie".

Wróćmy jednak do naszej funkcji obliczającej wyrażenie arytmetyczne. Załóżmy, że chcieli byśmy założyć, że często nie wiemy w jakim miejscu chcemy policzyć wartość funcji, więc chcieli byśmy ją liczyć dla powiedzmy zera, ot tak żeby tylko ją policzyć :)

W Pythonie jest to bardzo proste, wystaczy po nazwie argumentu napisać znak równości a po nim wartość, która ma być domyślnie używana.

def f(x=0):
    return (2 * (x**3))/8.51
 
print f()
print f(5)

Funkcje - poziom wyżej

Funkcje nie różnią się bardzo od zmiennych. Możemy naszą funkcję przypisać do jakiejś zmiennej (nie wywołując jej) w ten oto sposób, a następnie korzystać z niej w normalny sposób.
 

def f(x=0):
    return (2 * (x**3))/8.51
 
funkcja = f
 
print f()
print funkcja()

Nie jest to szczególnie przydatne ale prowadzi nas do pewnego odkrycia: skoro funkcji można użyć jako zmiennej to można też przekazać ją jako argument! A to rozwiązanie znajdzie całkiem sporo ciekawych zastosowań. Zobaczmy zatem jak to działa

def wyswietl(napis):
    print napis
 
def wez_napis_i_cos_z_nim_zrob(napis, zrob):
    zrob(napis)
 
wez_napis_i_cos_z_nim_zrob("Jakis napis", wyswietl)

To daje nam ciekawe możliwości, więc napiszmy kalkulator działający w ten sposób, który może zrobić coś z 2 liczbami. Od razu zauważ, że dzięki takiemu podjeściu będziemy mogli do naszego kalkulatora łatwo dodawać nowe funkcjonalności zupełnie nie zmieniając kodu, który napisaliśmy wcześniej.

def policz(jak, liczba1, liczba2):
    return jak(liczba1, liczba2)
 
def dodaj(x, y):
    return x+y
 
def podnies_do_potegi(x, y):
    return x**y
 
def pomnoz(x, y):
    return x*y
 
def podziel(x, y):
    #tutaj zamieniamy jedna z liczb
    #na zmiennoprzecinkowa na 
    #potrzeby Pyhona2
    return (x*1.0)/y

Możesz teraz dopisać samodzielnie funkcję, która odejmuje zupełnie nie zmieniając naszego kodu! To może być naprawdę użyteczne.

Kolejną (i już ostatnią w tym samouczku) ciekawą rzeczą dotyczącą funkcji jest rekurencja. Jest to mechanizm pozwalający na to, że funkcja może wywoałać samą siebie. Tak, to może wydać się na początku dziwne i nieintuicyjne ale zauważmy, że w matematyce jest to bardzo standardowa metoda opisu funkcji. Jako przykład pokażmy standardowo liczenie silni.

Jeśli nie wiesz co to silnia: zapisujemy ją za pomocą "!" a oznacza to mnożenie kolejnych liczb od 1 do podanej liczby. Czyli

\(5! = 1 * 2 * 3 * 4 * 5 = 120\)

(Warto nadmienić, że silnia z zera to 1)

Funkcja rekurencyjna w Pythonie wyglądać będzie tak:

def silnia(x):
    if x==1 or x==0:
        return 1
    else:
        return x*silnia(x-1)

Przeanalizujmy zatem co stanie się po wpisaniu silnia(3)

  1. Warunek wyjścia nie jest na początku spełniony, więc zostanie zwrócona 3 pomnożona przez silnię z liczby o jeden mniejszej (bo 3! to to samo co 3*2!)
  2. Zostanie więc wywołana funkcja silnia(2), warunek wyjścia znów nie zostanie spełniony, czli zostanie zwrócona 2 pomnożona przez silnię z 1
  3. Zostanie wywołana silnia(1), warunek x==1 zostanie spełniony, więc zostanie zwrócona jedynka
  4. Teraz "wracając" do wywołania silnia(2) ta jedynka jest mnożona przez 2 dzięki czemu uzyskujemy wynik silni dla 2
  5. Co za tym idzie ten wynik jest mnożony przez 3 aby uzyskać wynik silni dla 3
  6. Otrzymujemy nasz wynik, czyli 3*(2*(1)), a więc 6 :)

Na początku może wydawać się to trochę skomplikowane, więc dobrze jest to sobie samemu rozpisać lub nawet rozrysować na kartce.

Kiedy już zrozumiesz jak działa rekurencja musisz uświadomić sobie, że pisanie funckji rekurencyjnych wiąże się ze pewnym ryzykiem. Jeśli na przykład zapomnielibyśmy odejmować 1 od x, to funkcja wywoływała by się w nieskończoność! Na szczęście interpreter na to niepozwoli i zwróci nam błąd nadmiernego zagnieżdżenia pętli, ale  zawsze trzeba pamiętać, by rozważyć, czy funkcja jest skonstruowana tak, że wywołania kiedyś się zakończą.

 

Operacje na plikach

Olbrzymia większość programów używa plików do odczytania swojej konfiguracji, danych potrzebnych do działania programu, do wczytania danych użytkownika i do zapisania wyniku działania programu.

Prędzej czy później (a nawet już teraz) zajdzie potrzeba wczytania lub zapisania czegoś do pliku - program byłby do niczego jeśli dane wejściowe trzeba byłoby zapisywać bezpośrednio w kodzie programu. Mam nadzieję, że masz wystarczającą motywację żeby zaznajomić się z tym niezbędnym do dalszego rozwoju tematem. Zaczynajmy!

Pliki w pythonie można otwierać na kilka różnych sposobów. Zdania co do tego które rozwiązanie jest najlepsze są podzielone- wybierz to, które będzie najwygodniejsze lub poczytaj w innych źródłach jeśli potrzebujesz wybrać je do jakiegoś bardzo istotnego fragmentu programu.

Pierwszym i najprostszym sposobem otwarcia pliku jest użycie funkcji

plik = open('ścieżka/do/pliku.txt')

ścieżka może być bezwzględna (cała ścieżka do pliku) lub może to być ścieżka z miejsca, w którym uruchomiony jest program. Jeśli uruchamiasz program w folderze, w którym znajduje się plik wystarczy po prostu wpisać jego nazwę wraz z rozszerzeniem (to bardzo istotne żeby wpisać też rozszerzenie pliku jeśli plik takowe posiada, wyświetlanie rozszerzeń plików jest zależne od systemu operacyjnego, te informacje musisz znaleźć sam)

tak otwarty plik można przeczytać używając:

print plik.read()

po tej operacji można go już traktować jak wielolinijkowy napis. Najczęściej jednak jest to mało użyteczne, to tak jakby dać komuś ciasto do zjedzenia,  ale w całości, nie krojąc go na kawałki... Dużo lepiej jest podzielić plik na linie. Można go odczytać linijka po linijce w ten sposób:

for linia in plik:
    print linia

i tutaj spotka Cie niemiłe zaskoczenie, tekst rozłazi się bardziej niż to konieczne... dlaczego? A dlatego,  że każda linijka na końcu zawiera niewidoczny domyślnie "Enter" - znak przejścia do nowej linii, jest z nim trochę jak ze spacją, nie widać go bezpośrednio, ale bez niego plik wyglądałby dziwnie, jest to kolejny tak zwany znak biały (mówiliśmy już o spacji i tabulatorze). Tak więc polecenie "print" nie dość że samo zawsze przechodzi do nowej linii po wyświetleniu tego co miało wyświetlić, to mamy jeszcze taki "enter" zaszyty w tym napisie który wyświetlamy. Powinniśmy się go pozbyć. Można to osiągnąć metodą

linia.strip()

która to usuwa takie zbędne znaki końca linii (razem z innymi niepotrzebnymi białymi znakami).

Skoro możemy wygodnie podzielić sobie plik na linie to czemu by nie pójść krok dalej? Możemy podzielić linie na słowa! Uzyskamy to za pomocą metody split() która to z jednego długiego napisu zrobi nam listę wyrazów

tekst = "Jakis tam sobie tekst dla przykladu"
print tekst.split()

da nam listę napisów wyglądającą tak:

['Jakis', 'tam', 'sobie', 'tekst', 'dla', 'przykladu']

Co znacznie ułatwia ładowanie danych z plików do wygodnych, znanych i miejmy nadzieję lubianych przez Ciebie list.

Po tym jak skończysz "czytać" plik należy go zamknąć:

plik.close()

należy o tym pamiętać, ponieważ może się zdarzyć, że nie zamknięty plik ulegnie uszkodzeniu lub będzie blokowany gdy inny program będzie chciał mieć do niego dostęp.

Kolejną metodą jest otwarcie pliku w taki sam sposób i zastosowanie metody readlines() na nim. Zwróci nam to listę linii z jakimiś dziwnymi znaczkami. Te znaczki to nic innego jak znaki przejścia do nowej linii (\n), lub tabulatory (\t).

Innym sposobem otwarcia pliku jest użycie następującej konstrukcji

with open('plik.txt') as plik:
    for linia in plik:
        print linia.strip().split()

Dzięki temu mówimy, że chcemy wykonać coś wraz z otwarciem pliku i nie musimy przejmować się jego zamknięciem. To rozwiazanie ma też swoje wady - kiedy chcemy otworzyć w ten sposób wiele plików na raz, wcięcia w tekście robią się okropnie duże i ciężko ich pilnować. Jednakże do otwierania pojedyńczego pliku jak najbardziej warto tego używać, bo jasno widać gdzie dzieje się coś z plikiem i gdzie kończy się z nim coś dziać.

Świetnie, czytanie opanowane masz do perfekcji, ale zapewne chciałbyś też umieć coś w pliku zapisać? Niewiele to trudniejsze niż czytanie. Do pliku można zapisać dowony napis, ale uwaga, plik należy otworzyć w odpowiednim "trybie". Wcześniej otwieranie wyglądało jak poniżej, jak widzisz, pojawiła się tam dodatkowa literka 'r', nie wpisywaliśmy jej wcześniej bo jest to wartość domyślna i z powodzeniem można o niej zapomnieć jeśli zamierzamy tylko "czytać" (z angielskiego r <= read), więc jeśli chcemy "pisać" do pliku należy plik otworzyć w trybie zapisu (z angielskiego w <= write). Przykłady poniżej:

plik = open('plik.txt','r')
plik.close()
plik = open('plik.txt','w')
plik.close()

Dobrze, ale otwarcie pliku to nie wszystko, przecież trzeba wreszcie coś w nim zapisać. Robi się to bardzo prosto a mianowicie, gdy masz otwary plik w trybie zapisu możesz zapisać do niego cokolwiek co jest napisem:

plik.write(str(55552522))
plik.write("\n")
plik.write("Tutaj masz jakis napis")

Warto wspomnieć że wstawienie "Entera" robimy za pomocą "\n" a tabulację za pomocą "\t".

Po wszystkim plik należy oczywiście zamknać jeśli był otwarty pierwszą metodą.

Uwaga: kiedy otwierasz plik w trybie zapisu cała zawartość jest czyszczona bezpowrotnie!!! Pamiętaj o tym otwierając pliki. Jeśli chcesz coś dopisać na końcu istniejącego pliku,  możesz otwierać plik w trybie dopisywania (z angielskiego a <= append)

plik = open('plik.txt','a')

wtedy wszysto to co zapiszesz będzie dopisywane na końcu pliku i nie utracisz swoich danych.

Wskazówka: Kiedy otwierasz nieistniejący plik w trybie 'w' lub "a" jest on domyślnie tworzony.

Uwaga: powyższa wskazówka nie dotyczy plików w trybie odczytu ('r'), nie tworzy ona też folderów!

O plikach moglibyśmy jeszcze długo pisać (jeśli jesteś ciekaw, możesz poszukać w internecie informacji o metodach seek i rozmiarach buforów odczytu), ale z wiedzą tu przedstawioną powinieneś poradzić sobie z większością, jeśli nie wszystkimi zadaniami w serwisie.

 

Sprawdź czy potrafisz już zrobić zadanie Operacje na plikach !

Dodatkowe biblioteki

Załóżmy że chcemy stworzyć elektroniczną wersję planszowego RPG w którym używana jest kostka 20 ścienna. Będzie nam potrzebna jakaś funkcja, która wylosuje nam liczbę z zakresu od 1 do 20. Zagadnienia liczb losowych raczej nie są częścią tego samouczka, więc jak się spodziewasz w Pythonie powinno być już coś, co pozwoli nam losować takie liczby. Jeśli tak, to masz rację, ale musimy użyć dodatkowego modułu/biblioteki.

Biblioteki zawierają najczęściej tematyczny zbiór funkcji i klas (na razie nie musisz wiedzieć co to są klasy). W naszym przypadku będzie to zbiór dotyczący liczb losowych zawierający funkcję pozwalającą losować liczbę z danego zakresu.

Przejdźmy zatem do jego zaimportowania i przykładu użycia funkcji randint (której działania mam nadzieję nie muszę tłumaczyć)

import random
 
print random.randint(1,20)

kiedy importujemy jakiś moduł aby dostać się do funkcji w nim zawartej musimy użyć jego nazwy. Jest to związane z przestrzeniami nazw, to znaczy w naszym programie mogły by wystąpić funkcje o tej samej nazwie i nie mieli byśmy jak dostać się do funkcji z modułu random.

Jeśli jednak wiemy, że chcemy użyć tylko jednej funkcji z danej biblioteki możemy zaimportować tylko ją i mieć do niej bezpośredni dostęp. Zobaczmy to na przykładzie funkcji sleep z modułu time, która to funkcja pozwala odczekać daną ilość sekund.

 

from time import sleep
sleep(10)

Najważniejszą chyba wiadomością w tym rozdziale jest to, że tak samo możesz importować swoje funkcje!

Na potrzeby tego samouczka załóżmy, że wymaga to aby plik z którego będziemy chcieli zaimportować znajdował się w tym samym folderze (może też znajdować się w folderze ze wszystkimi dodatkowymi pakietami Pythona, ale nie oszukiujmy się, na początku nauki nie napiszesz czegoś na tyle dopracowanegoo by używać tego na stałe, a nie warto zaśmiecać folderów z instalacją Pythona).

Stwórzymy więc sobie plik o nazwie funkcje.py zawierający następujący kod

def a():
    print "A"
 
def b():
    print "B"

A następnie uruchom interpreter w tym folderze i zaimportuj wszystkie funkcje bezpośrednio za pomocą
 

from funkcje import *
a()
b()

Gwiazdka oznacza, że chcemy zaimportować wszystko a składnia mówi nam, że będziemy mieć do funkcji bezpośredni dostęp.

Ostanią rzeczą o krórej warto jest wspomnieć i która (przynajmniej według mnie) przydaje się niesamowicie często są "słowniki domyślne" z pakietu collections. Działają one podobnie do normalnych słowników z tą różnicą, że kiedy pytamy o wartość klucza którego w słowniku jeszcze nie ma, nie dostaniemy błędu, lecz wartość domyślną oraz para klucz:wartość zostanie zapisana w słowniku.

Jest to bardzo użyteczne we wszelkiego rodzaju zliczeniach.

from collections import defaultdict
d = defaultdict(int)
print  d['x']
 
napis = "aaabbccoooossasdk"
for litera in napis:
    d[litera] += 1
print d