Algorytmy danych geoprzestrzennych
Wprowadzenie do Pythona

Krzysztof Dyba

Python to interpretowany język programowania wysokiego poziomu, powszechnie stosowany w różnych zastosowaniach takich jak tworzenie stron internetowych, analiza danych i uczenie maszynowe, pisanie skryptów i automatyzacja procesów czy zarządzanie systemami (DevOps). Jest także używany w systemach informacji geograficznej do przetwarzania i analizowania danych przestrzennych. Jest aktualnie najpopularniejszym językiem programowania.

Cechy języka Python:

Przegląd funkcjonalności

W tej sekcji znajdziesz błyskawiczny przegląd funkcjonalności Pythona. Pełna wersja tutorialu w języku angielskim dostępna jest tutaj.

Zmienne

Do przypisania wartości do zmiennej stosuje się znak równości =.

x = 5          # liczba
y = "parasol"  # tekst

Utworzone zmienne można wyświetlić używając funkcji print().

print(x)
print(y)
5
parasol

Typy danych

Domyślnie wspierane są następujące typy danych:

  • liczba całkowita int (np. -10, 0, 10),
  • liczba zmiennoprzecinkowa float (np. 0.01, 21.37),
  • łańcuchy tekstu str (np. “Ala ma kota.”, ‘rower’),
  • wartości logiczne bool (True, False).

Do sprawdzenia typu danych służy funkcja type().

type(10)
int
type(0.01)
float
type("Ala ma kota.")
str
type(False)
bool

Możemy również dokonać konwersji między typami:

  • z liczby zmiennoprzecinkowej na całkowitą (część dziesiętna zostaje usunięta!),
  • z liczby całkowitej na zmiennoprzecinkową,
  • z liczby na tekst i na odwrót.
# konwersja liczby zmiennoprzecinkowej na całkowitą
print(int(3.14))
print(int(3.99))
3
3
# konwersja tekstu na liczbę
str(10)
'10'

Struktury danych

Do podstawowych struktur danych należą:

  • lista,
  • słownik.

Lista

Lista jest uporządkowanym, modyfikowalnym i dynamicznym zbiorem elementów, które mogą być dowolnego typu danych. Definiuje się ją poprzez umieszczenie elementów między nawiasami kwadratowymi [], które oddzielone są przecinkami. Listy można również zagnieżdżać.

# stworzenie listy
ls = [35, "rower", 53.61, "plecak", True]
print(ls)
[35, 'rower', 53.61, 'plecak', True]

Funkcja len() zwraca liczbę elementów w liście.

len(ls)
5

Dostęp do poszczególnych elementów listy możemy uzyskać za pomocą ich indeksu.

# dostęp do elementów listy
print(ls[0]) # pierwszy element
print(ls[1]) # drugi element

print(ls[-1]) # pierwszy element od końca
print(ls[-2]) # drugi element od końca
35
rower
True
plecak
# zakresy indeksów
# ls[początek:koniec]
print(ls[2:4]) # od trzeciego do czwartego obiektu
print(ls[:3]) # od początku do trzeciego obiektu
print(ls[3:]) # od czwartego obiektu do końca
[53.61, 'plecak']
[35, 'rower', 53.61]
['plecak', True]

Używając indeksów można zastąpić poszczególne elementy listy.

ls[4] = False
print(ls)
[35, 'rower', 53.61, 'plecak', False]

Możemy również modyfikować zawartość listy za pomocą różnych metod:

  • append() – dodaje element na końcu listy,
  • insert(indeks, element) – dodaje element w określonym miejscu,
  • remove() – usuwa element według wartości,
  • reverse() – odwraca kolejność elementów listy.
ls.append(999)
print(ls)
[35, 'rower', 53.61, 'plecak', False, 999]
ls.insert(6, "nowy")
print(ls)
[35, 'rower', 53.61, 'plecak', False, 999, 'nowy']
ls.remove("rower")
print(ls)
[35, 53.61, 'plecak', False, 999, 'nowy']
ls.reverse()
print(ls)
['nowy', 999, False, 'plecak', 53.61, 35]

Nie są to jednak wszystkie dostępne metody. Aby odkryć pozostałe, wykonaj Zadanie 4.

Słownik

Słownik jest strukturą danych używaną do przechowywania zbiorów danych w formacie pary klucz-wartość. W przeciwieństwie list, które są indeksowane liczbami całkowitymi, słowniki są indeksowane za pomocą unikalnych, niemodyfikowalnych kluczy. Każdy klucz jest unikatowy w słowniku i pełni funkcję identyfikatora umożliwiającego dostęp do powiązanej z nim wartości.

Słowniki są definiowane za pomocą nawiasów klamrowych {}, pary klucz-wartość są określane za pomocą dwukropka :, a kolejne pary są rozdzielone przecinkami , w następujący sposób:

slownik = {klucz_1: wartosc_1, klucz_2: wartosc_2, ...}

# stworzenie słownika
osoby = {
    "imie": "Ania",
    "wiek": 21,
    "miasto": "Poznań"
}

Dostęp do wartości powiązanej z kluczem możemy uzyskać za pomocą nawiasów kwadratowych [] i klucza:

print(osoby["imie"])
Ania

Dostępne są również metody keys() oraz values(), które zwracają wszystkie klucze oraz wartości.

print(osoby.keys())
print(osoby.values())
dict_keys(['imie', 'wiek', 'miasto'])
dict_values(['Ania', 21, 'Poznań'])

Słowniki są modyfikowalne, co oznacza, że można dodawać, modyfikować lub usuwać pary klucz-wartość po utworzeniu słownika.

# dodanie nowej pary klucz-wartość
osoby["wzrost"] = 165

# modyfikacja wartości
osoby["wiek"] = 41

# usunięcie pary klucz-wartość
del osoby["miasto"]

print(osoby)
{'imie': 'Ania', 'wiek': 41, 'wzrost': 165}

Operatory

Python obsługuje różne operatory do wykonywania operacji arytmetycznych, porównawczych, logicznych, przypisania i innych.

Arytmetyczne:

  • Dodawanie +,
  • Odejmowanie -,
  • Mnożenie *,
  • Dzielenie /,
  • Modulo % (reszta z dzielenia),
  • Potęgowanie **.
a = 10
b = 3

print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a % b)
print(a ** b)
13
7
30
3.3333333333333335
1
1000

Porównawcze

  • Operator równości ==,
  • Operator negacji równości !=,
  • Operatory nierówności >, >=, <, <=.
a = 10
b = 3

print(a == b)
print(a != b)
print(a < b)
print(a > b)
False
True
False
True

Logiczne

  • Koniunkcja and (True, jeśli obie wartości są prawdziwe),
  • Alternatywa or (True, jeśli przynajmniej jedna wartość jest prawdziwa),
  • Negacja not (odwraca wartość logiczną).
a = 10
print(a > 0 and a < 100)
True
print(True and False)
print(True or False)
False
True

Instrukcje warunkowe

Instrukcje warunkowe są podstawowymi mechanizmami przepływu pracy, które pozwalają na wykonywanie różnych bloków kodu w zależności od tego czy określony warunek jest prawdziwy czy fałszywy. W Pythonie do formułowania instrukcji warunkowych używa się wyrażeń if, elif oraz else. Warunki są sprawdzane (i wykonywane) w takiej kolejności w jakiej zostały zapisane.

x = 10

# sprawdza jeden warunek
if x > 0:
    print("Liczba jest większa od 0.")
else:
    print("Liczba jest mniejsza od 0 lub równa 0.")
Liczba jest większa od 0.
x = 0

# sprawdza dwa warunki
if x > 0:
    print("Liczba jest większa od 0.")
elif x < 0:
    print("Liczba jest mniejsza od 0.")
else:
    print("Liczba to 0.")
Liczba to 0.

Pętle

Pętle to instrukcje przepływu pracy używane do wielokrotnego wykonywania bloku kodu. Są one niezbędne do automatyzacji powtarzających się zadań. W Pythonie istnieją dwa typy pętli: for oraz while.

Pętla for

Służy do iteracji po sekwencji, np. lista, łańcuch znaków, zakres (lub dowolnym iterowalnym obiekcie) i wykonuje zdefiniowaną akcję dla każdego elementu.

ls = ["a", "b", "c"]

# iteracja po elementach listy
for i in ls:
    print(i)
a
b
c
# iteracja po zakresie liczb
for i in range(3):
    print(i)
0
1
2

Zauważ, że numeracja rozpoczyna się od 0.

Pętla while

Służy do wielokrotnej iteracji, dopóki określony warunek jest prawdziwy. Oznacza to, że pętla zakończy się wtedy, kiedy warunek nie zostanie spełniony. Używając tego rodzaju pętli, należy upewnić się, że jest ona skończona!

licznik = 0
while licznik < 5:
    print(licznik)
    licznik += 1
0
1
2
3
4

Wykonywanie pętli można kontrolować za pomocą wyrażeń:

  • break – natychmiastowe wyjście z pętli,
  • continue – pominięcie bieżącej iteracji i przejście do następnej,
  • pass – brak akcji (nic się nie dzieje).

Funkcje

Funkcja to blok kodu wielokrotnego użytku, który wykonuje określone zadanie. Umożliwiają organizowanie kodu w mniejsze moduły, dzięki czemu kod programu jest czytelniejszy i łatwiejszy do zrozumienia. Funkcje mogą przyjmować dane wejściowe, przetwarzać je i zwracać dane wyjściowe. Funkcje definiuje się za pomocą słowa kluczowego def, po którym następuje nazwa funkcji i nawiasy () z argumentami.

def pole_prostokata(a, b):
    """Opcjonalna dokumentacja opisująca funkcję"""
    P = a * b
    return P

Aby wykonać funkcję, należy ją wywołać, używając jej nazwy wraz z nawiasami. Jeśli funkcja przyjmuje argumenty, to należy je określić w nawiasie.

pole_prostokata(10, 5)
50

Obsługa wyjątków

Obsługa wyjątków jest mechanizmem umożliwiającym zarządzanie i reagowanie na błędy lub nieoczekiwane zdarzenia, które mogą wystąpić podczas wykonywania kodu. Przyczyny błędów w programie mogą być zróżnicowane, np. nieprawidłowy format danych wejściowych, brak pliku w określonej lokalizacji, dzielenie przez zero, itd.

Podstawowym narzędziem Pythona do obsługi wyjątków jest blok try-except:

  • try – obejmuje blok kodu, który potencjalnie może spowodować wyjątek,
  • except – określa typów wyjątków, które powinny zostać wychwycone.

Wśród podstawowych klas wyjątków możemy znaleźć:

  • TypeError (operacja wykonywana jest na niezgodnym typie danych),
  • ZeroDivisionError (próba dzielenia przez 0),
  • FileNotFoundError (żądany jest plik, który nie istnieje),
  • SyntaxError (nieprawidłowa składnia języka Python).

Wszystkie klasy są opisane tutaj.

def dzielenie(n):
    try:
        wynik = 10 / n
    except TypeError:
        print("Nieprawidłowy typ danych!")
    except ZeroDivisionError:
        print("Nie można dzielić przez 0!")
    else:
        print(wynik)

W powyższym przykładzie najpierw wykonywany jest kod w bloku try. Następnie, jeżeli w bloku try wystąpi wyjątek określony w klauzulach except, to zostanie wykonany odpowiedni blok except, np. wyświetlenie komunikatu o błędzie, zastosowanie alternatywnego podejścia. Jeżeli nie wystąpił żaden wyjątek, to zostanie wykonany blok else.

Przetestuj samodzielnie, co stanie się w poniższych wariantach:

dzielenie("a")
dzielenie(0)
dzielenie(5)
Nieprawidłowy typ danych!
Nie można dzielić przez 0!
2.0

Używając instrukcji raise możemy wywołać wyjątek, jeśli wystąpi określony warunek, co spowoduje przerwanie działania programu i stworzenie wyjątku.

def wyswietl_wiek(wiek):
    if not isinstance(wiek, (int, float)):
        raise TypeError("Wiek musi być liczbą!")
    if wiek < 0:
        raise ValueError("Wiek musi być dodatni!")
    if wiek > 150:
        raise ValueError("Wiek jest zbyt duży!")
    print(wiek)

Importowanie bibliotek

Importowanie bibliotek umożliwia dostęp i używanie dodatkowych klas i metod, które nie są wbudowane język Python, dzięki czemu możliwe jest rozszerzenie funkcjonalności języka i wykorzystanie gotowych funkcji do różnych zadań.

W Pythonie możemy załadować wbudowane biblioteki (np. math, time, os) lub zainstalować zewnętrzne (np. numpy, pandas, matplotlib) używając polecenia import. Aby wywołać zaimportowane funkcje, należy wykorzystać nazwę biblioteki jako prefiks z kropką, a następnie podać nazwę funkcji, w ten sposób: biblioteka.funkcja(). Zaimportowanej bibliotece można również nadać alias, dzięki czemu nazwa zostanie skrócona, np. import numpy as np.

import math
print(math.sqrt(16))

import random
# wylosuj 5 liczb z zakresu od 1 do 100
random_numbers = random.sample(range(1, 101), 5)
print(random_numbers)
4.0
[41, 57, 37, 52, 11]

Zadania

  1. Napisz pętlę, która zsumuje wartości od 1 do 10.
  2. Napisz funkcję, która zamienia kilogramy (kg) na funty (lb) oraz na odwrót.
  3. Napisz funkcję, która sprawdzi czy dany rok jest przestępny. Rok jest przestępny, gdy jest podzielny przez 4 i nie jest podzielny przez 100 lub jest podzielny przez 400. Przykładowo lata 2000 i 2004 były przestępne, natomiast lata 1990, 2010 czy 2021 nie były.
  4. Używając listy składanej (list comprehension) oraz instrukcji warunkowej, sprawdź jakie są pozostałe metody dostępne dla list. Do tego zadania będą pomocne dwie metody – dir() oraz startswith().