In [1]:
# setup
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

1. Podstawy: zmienne i typy danych

Python podobnie jak większość języków skryptowych i interpretowalnych może pracować w dwóch trybach: trybie interakywnym i w trybie skryptowym. Oba tryby pracy są przeznaczone do różnych zadań: skrypty zawierają sprawdzony kod, który służy to wielokrotnego wykonywania tych samych czynności natomiast tryb interaktywny nadaje się przede wszystkim do przygotowywania i testowania rozwiązań. Tryb interaktywny doskonale nadaje się do nauki programowania - jest odporny na błędy - błędny fragmet po poprawieniu wystarczy uruchomić ponownie, ponadto pozwala natychmiast zobaczyć wynik i przekonać się czy planowane rozwiązanie spełnia nasze oczekiwania.

Pięrwsza część kursu będzie realizowana wyłącznie w trybie interaktywnym, tworzenie skryptów pojawi się jako osobny temat kursu. Tryb interaktywny uruchamia się poprzez uruchomienie środowiska pythona i jest sygnalizowany przez >>>.

Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Poprzez znak >>> Python pyta „Co mam teraz zrobić?” Po tym znaku należy podać operację/instrukcję, którą interpreter Pythona ma wykonać. Instrukcja musi być sformułowana zgodnie z zasadami języka.

Python jako kalkuator

Podstawowe operacje matematyczne mogą być wykonywane jako kalkulator, wynik każdej operacji zostanie natychmiast wyświetlony w konsoli. W poniższym przykładzie zostaną przedstawione proste operacje matematyczne. Operacja wykonana przy pomocy dwóch gwiazdek to potęgowanie.

In [2]:
5 + 6
4 * 2
2 / 3
10 - 11
10**2
Out[2]:
11
Out[2]:
8
Out[2]:
0.6666666666666666
Out[2]:
-1
Out[2]:
100

Zmienne

Jakiekolwiek operacje programistyczne, bardziej złożone niż prosta arytmetyka wymaga wprowadzenia pojęcia zmiennej.

Zmienna (ang. variable) – nazwa, której odpowiada określona wartość lub wyrażenie. Nowa zmienna tworzona jest poprzez przypisanie określonej wartości (lub wyrażenia) do podanej nazwy. Wyrażenie może być także pojedyńczą wartością. Każde wywołanie zmiennej powoduje przywołanie przypisanej do niej wartości.

Zmienna = wyrażenie

Python posiada kilk ograniczeń w kwestii nazywania zmiennych:

  • nazwa zmiennej musi zaczynać się od litery lub znaku '_'
  • nazwa zmiennej musi zawierać tylko litery, cyfry lub znaki '_'

Note: Komentarze

Pisząc kod w języku Python stosujemy komentarze czyli fragmenty tekstu, które mają pomóc użytkownikowi kodu zrozumieć co się w nim dzieje. Komentarze warto stosować zwłaszcza na etapie nauki. Prosty, jednolinijkowy komentarz poprzedzamy znakiem #

# to jest komentrz

Zawartość zmiennych można przywołać wypisując jej nazwę lub korzystając z fukcji print(). Na tym etapie będziemy zajmować się tylko prostymi typami zmiennych zawierających liczby, wartości logiczne lub lańcuchy tekstów. Oto kilka przykładów zmiennych:

In [3]:
napis = 'Nowy komunikat' # napis
calk = 17  # liczba całkowita
zmienn = 3.141592653589793 # liczba zmiennoprzecinkowa
logic = True # wartość logiczna
print(logic)
True

Note: Literały

Jeżeli wartość nie jest przypisana do żadnej zmiennej określamy ją jako literał (ang. literal). Literały występują najczęściej jako wyrażenia przypisywane do zmiennych ale mogą też występować jako niezależne byty - na przykład w operacjach porównania. Do literału można odwołać się jedynie w miejscu jego pojawienia się.

Typy zmiennych

W języku Python - a dokładnie w jego podstawowej wersji - typ zmiennych nie jest deklarowany. Typ zmiennej jest określany w momencie przypisania wartości do zmiennej. Proste zmienne, tworzone na bazie literałów mogą należeć do jedego z czterech typów:

  • boolean - wartość logiczna - przyjmuje tylko dwie wartości prawda i fłasz (True/False)
  • integer – liczby całkowite - liczby całkowite, nie posiadające części ułamkowej
  • float – liczby rzeczywiste - dowolne wartości
  • string – łańcuchy tesktowe - napisy dowolnej długości

Typ każdej zmiennej lub literału możemy określić przy pomocy funkcji type()

In [4]:
type(logic)
type(calk)
type(zmienn)
type(napis)
type(True)
type(10)
type("parasol")
Out[4]:
bool
Out[4]:
int
Out[4]:
float
Out[4]:
str
Out[4]:
bool
Out[4]:
int
Out[4]:
str

W zależności od typu zmiennych proste operacje będą prowadziły do innych rezultatów. Typy liczbowe: Boolean, Integer i Float mogą być poddane dowolnym operacjom matematycznym.

  1. Wartości logiczne True i False to w praktyce liczby całkowite o wartościach 1 i 0 i w trakcie dodawania ich do siebie zachowują się tak jak liczby całkowite. Wynikiem operacji jest liczba całkowita

  2. Operacje dodawania odejmowania i mnożenia liczb całkowitych dają w wyniku liczbę całkowitą

  3. Jeżeli jakakolwiek liczba w wyrażeniu będzie zmienną przecinkową, typ wyniku też będzie wartością zmiennoprzecinkową

In [5]:
x = True + True # 1 + 1
type(x)
y = 10 + True
type(y)
z = 10 * 10
type(z)
v = 1.0 + True
type(v)
Out[5]:
int
Out[5]:
int
Out[5]:
int
Out[5]:
float

W przeciwieństwie do wersji 2.x pythona podzielenie przez siebie dwóch liczb całkowitych da w wyniku liczbę zmiennoprzecinkową - jest to tzw prawdziwe dzielenie. W starszych wersjach pythona i w językach silnie typicznych podzielenie przez siebie dwóch liczb całkowitych dawało w wyniku jedynie część całkowitą liczby. W wersji 3.x pythona do uzyskania części całkowitej trzeba zastosować operator dzielenia całkowitego //. Co ciekawe, zastosowanie tego operatora dla liczb zmiennoprzecinkowych da w wyniku część całkowitą ale typu zmiennoprzecikowego.

In [6]:
10/3
10//3
10.0//3.0
Out[6]:
3.3333333333333335
Out[6]:
3
Out[6]:
3.0

Analogicznie do uzyskania reszty z dzielenia służy operator modulo %. Podobnie jak w przypadku dzielenia całkowitego w zależności od komponentów da w wyniku liczbę całkowitą lub zmiennoprzecikową. Co ciekawe zastosowanie operatora modulo dla dwóch liczb zmiennoprzecikowych może dać nie do końca sensowne.

In [7]:
10%3
10//3.1
10.0%3.1
Out[7]:
1
Out[7]:
3.0
Out[7]:
0.6999999999999997

Konwersja między typami

Tak naprawdę Python, podobnie jak wszystkie inne języki programowania, może wykonywać operacje tylko na liczbach tego samego typu. W przypadku jeżeli w wyrażeniu występują operandy (czyli elementy wyrażenia) różnego typu możliwe są dwie reakcje:

  1. Konwersja niejawna (ang. implicit) pomiędzy typami do typu bardziej ogólnego
  2. Komunikat o niemożliwości wykonania operacji (błąd)

Typ bardziej ogólny to taki do którego konwersja może być wykonana bez utraty informacji. Najbardziej ogólnym typem liczbowym jest typ zmiennoprzecinkowy - dowlona liczba może być przedstawiona w tym formacie, następnie typ całkowity a najmniej ogólnym jest typ logiczny. Do konwersji pomiędzy liczbami służą następujące funkcje:

  • float() - do konwersji do liczby zmiennoprzecinkowej
  • int() - do konwersji do liczby całkowitej
  • bool() - do konwersji do wartości logicznej

Konwersja do typu mniej ogólnego zawsze wiąże się z utratą informacji. Konwersja do liczby całkowitej powoduje utratę części ułamkowej liczby, natomiast konwersja do typu logicznego każdą wartość różną od 0 zamieni w True a 0 w False.

Note: funkcje wbudowane

Python podobnie jak wszystkie inne języki obok struktur danych posiada pewien (ograniczony) zestaw funkcji, które nazywamy funcjami wbudowanymi. Służą one przede wszystkim do wykonywania operacji na strukturach danych, które inaczej albo nie były by możliwe albo bardzo trudne do wykonania. Klasycznym przykładem są wspomniane wyżej fukcje służące do konwersji typów, czy proste funkcje matematyczne. Lista tych funkcji znajduje się w dokumentacji [https://docs.python.org/3/library/functions.html]

Wszystkie inne funkcje znajdują się w różnych modułach albo w ramach biblioteki standardowej albo w bibliotekach zewnętrznych. Wbudowane funkcje są umieszczone w specjalnym module o nazwie builtin (nazwa z dwoma znakami podkreślenia przed i po nazwie).

Ogólna postać każdej funkcji to:

nazwa_funkcji(argument)

Aby uzyskać pomoc na temat określonej funkcji należy podać help(nazwa_funkcji), np. help(round).

Funkcje mogą być bezargumentowe (nieliczne), jednoargumentowe i wieloargumentowe. Część argumentów (te na początku listy argumentów) to argumenty obowiązkowe, pozostałe argumenty są opcjonalne. Przykładem może być funkcja pow (power, potęga), gdzie dwa pierwsze argumenty są obowiązkowe, trzeci arguemnt jest opcjonalny

pow(...) pow(x, y[, z]) zapis [,z] oznacza że trzeci argument funkcji pow() jest opcjonalny.

Note: Metody obiektów

Python jest językiem struturalno-obiektowym. Metody to grupa funkcji związana z określonym typem danych. Każdy typ danych ma pewną grupę funkcji przystosowanych do pracy z takim typem danych. Mamy metody związane z łańcuchami tekstowymi, listami itd. Każdy typ danych ma swój własny zbiór metod.

Istnieją 2 sposoby sprawdzenia, jakie metody dostępne są dla określonego obiektu: Funkcja dir() daje możliwość sprawdzenia jakie metody dostępne są dla danego obiektu. Wyświetla ona jedynie nazwy dostępnych metod. Jeśli chcemy uzyskać opis danej metody, musimy użyć funkcji help(), podobnie jak w przypadku funkcji wbudowanych.

In [8]:
bool(10)
bool(0.0)
int(20.5)
float(True) # konwersja do typu bardziej ogólnego
float(10) # konwersja do typu bardziej ogólnego
Out[8]:
True
Out[8]:
False
Out[8]:
20
Out[8]:
1.0
Out[8]:
10.0

łancuchy tekstowe

Łańcuchy znaków służą do przechowywania napisów. W Pythonie ten typ wartości nazywany jest str od angielskiego słowa string. Łańcuchy tekstowe tworzy się poprzez umieszczenie danego tekstu w pojedyńczym ( ' ) lub podwójnym ( “ ) cudzysłowiu (nie można mieszać typu cudzysłowiów, jeśli łańcuch zaczyna się od pojedyńczego cudzysłowia, musi także kończyć się pojedyńczym cudzysłowiem). Łańcuch tekstowy może zawierać litery, liczby i znaki specjalne.

'to jest łańcuch tekstowy'

Note: Znaki specjalne w łańcuchach tekstowych

W przypadku gdy chcemy wewnątrz łańcucha tekstowego użyć element, który może nie zostać zinterpretowany prawidłowo, musimy go poprzedzić znakiem ucieczki \ (ang. backslash) Przykłady znaków specjalnych:

  • \' - pojedynczy cudzysłów
  • \” - podwójny cudzysłów
  • \n – znak końca linii, oznacza przejście do nowej linii
  • \t – tabulator
  • \ - backshlash

Co istotne, łańcucha tekstowego nie możemy wyświetlić poprawnie bez użycia funkcji print().

In [9]:
x = "tekst z cudzysłowiem \"wewnątrz\""
print(x)
x = 'tekst z  \t tabluatorem'
print(x)
x = 'tekst z  \n podziałem wiersza'
print(x)
tekst z cudzysłowiem "wewnątrz"
tekst z  	 tabluatorem
tekst z  
 podziałem wiersza

W przypadku operacji na łańcuchach tekstowych można używać operatora + (łączenie) oraz * (powielanie). Operator * stosowany jest zawsze w połączeniu z liczbą. W wyniku operacji "mnożenia" łańcuch tekstowy powtarzany jest określoną (przez liczbę) ilość razy. Pozostałe operatory matematyczne będą skutkowały błędem.

In [10]:
print('a' + 'b') 
print(5 * 'b')
ab
bbbbb

Łączenie tekstu i liczb w prostych operacjach

W przeciwieństwie do operacji na różych typach liczbowych, gdzie zachodziła konwersja niejawna, łącznie ze sobą tekstu i liczb jest ograniczone oraz wymaga konwersji jawnej poprzez zastosowanie:

  • jednej z wymienionej powyżej funkcji do konwersji tekstu na liczbę
  • funkcji str() do konwersji liczby na tekst.

O ile konwersja liczby na tekst zawsze zakończy się sukcesem to w przypadku łańcucha tekstowego musi on być jednoznacznie liczbą zgodną z typem do którego dokonujemy konwersji. Najbezpiecznejszym rozwiązaniem jest zawsze konwersja najpierw na typ float a następnie na int. Łańcuchy tekstowe, które można zinterpretować jako True i False można bezpośrednio konwertować na typ logiczny.

In [11]:
int('10')
# int(10.1) # to nie zadziała
int(float(10.1))
# float('a341.1') # nie zadziała nie jest to jednoznacznie liczba
bool("true")
bool("TRUE")
bool("True")
Out[11]:
10
Out[11]:
10
Out[11]:
True
Out[11]:
True
Out[11]:
True

Jeżeli chcemy połączyć ze sobą liczby z łańcuchem tekstowym w nowy łańcuch tekstowy to liczbę trzeba konwertować jawnie do formatu tekstowego. Należy być jednak ostrożnym z konwersją liczb zmiennoprzcinkowych o nieznanej wartości:

In [12]:
print(str(5)+' pięć')
print(str(1/1010181910.00019)+ ' Ale liczba!')
5 pięć
9.89920716358712e-10 Ale liczba!

Więcej informacji na temat pracy z tekstem, w tym na temat jego formatowania znajdzie się w osobnym module.

Note: Wartości specjalne i stałe

Podstawowa wersja języka nie definiuje wartości specjalnych takich jak NaN, NA, inf czy łańcuch pusty. Można je jednak zdefiniować samodzielnie, jeżeli istnieje taka potrzeba. W praktyce korzysta się jednak z definicji tych wartości tworzonych w innych modułach jak math lub numpy. Więcej na ten temat w dalszej częsci kursu

In [13]:
NaN = float('NaN')
inf = float('inf')
empty = ''