Adam Inglot
Adiunkt w Katedrze Geodezji
Wydział Inżynierii Lądowej i Środowiska, Politechnika Gdańska
adam.inglot@pg.edu.pl  
2022-10-11, aktualizacja 2022-10-17
© ainglot.pl, 2022. Udostępnianie i wykorzystanie zgodnie z licencją Creative Commons Attribution 4.0 International license (CC BY 4.0).W drugiej części wprowadzenia do Pythona zapoznamy się z definiowaniem własnej funkcji, trzema modułami z podstawowych bibliotek Pythona: os, datetime i random. Przyglądniemy się też podstawowemu sposobowi obsługiwania plików, na przykładzie i zastosowaniu do pliku tekstowego.
defBudując własną funkcję w języku Python możemy utworzyć jedną z czterech rodzajów funkcji: globalną, lokalną, lambda lub metodę. My na potrzeby kursu ograniczymy się do używania, tworzenia funkcji globalnych. Ogólna składnia funkcji def:
1def nazwa_funkcji(pierwszyParametr...):2pakiet
Parametry które możemy podać są opcjonalne, możemy je podać jako sekwencję identyfikatorów oddzielonych przecinkami lub jako sekwencja par identyfikator=wartość. Podczas użycia funkcji należy wprowadzić dokładnie tyle parametrów ile jest wymaganych (podanych w nawiasie okrągłym), w przeciwnym razie zwrócony zostanie błąd w wyniku działania funkcji. Sprawdźmy na przykładzie jak zastosować funkcję def:
1def suma_trzech_parametrow(pierwszyParametr, drugiParametr, trzeciParametr):2sumaParametrow = pierwszyParametr + drugiParametr + trzeciParametr3return sumaParametrow45print(suma_trzech_parametrow(1, 2, 3)
Wynik działania skryptu:
Run:6 Process finished
W powyższym przykładzie zostały zastosowane argumenty pozycyjne, czyli wykonując funkcję podajemy na konkretnej pozycji wartość jaką ma przyjmować dany parametr. Możemy argument pozycyjny zamienić na argument z wartością domyślną, wtedy nie musimy podawać argumenty a funkcja zostanie wykonana z wprowadzoną wartością domyślną.
1def suma_trzech_parametrow(pierwszyParametr, drugiParametr, trzeciParametr=3):2sumaParametrow = pierwszyParametr + drugiParametr + trzeciParametr3return sumaParametrow45print(suma_trzech_parametrow(1, 2)
Wynik działania skryptu z wartością domyślną:
Run:6 Process finished
Przy zastosowaniu wartości domyślnej możemy pozostawić tę wartość jak w kodzie powyżej lub wprowadzić na ostatnią pozycję wartość dla której chcemy przeprowadzić działanie:
1def suma_trzech_parametrow(pierwszyParametr, drugiParametr, trzeciParametr=3):2sumaParametrow = pierwszyParametr + drugiParametr + trzeciParametr3return sumaParametrow45print(suma_trzech_parametrow(1, 2, 10)
Wynik działania skryptu gdzie wartość domyślna została zastąpiona:
Run:13 Process finished
Podczas projektowania własnej funkcji z wartością domyślną, należy pamiętać że w pierwszej kolejności należy wprowadzić argumenty pozycyjne a po nich, argumenty z wartością domyślną.
osDo czego może nam się przydać moduł os? Najprościej można odpowiedzieć że na potrzeby dostępu do plików i folderów. Dzięki metodom z tego modułu możemy np. wylistować pliki i foldery z podanej lokalizacji, usunąć lub skopiować plik, wyodrębnić nazwę pliku czy rozszerzenia.
Dla podanych metod sposób importu biblioteki os wygląda w taki sposób: import os.
| składnia | opis | 
|---|---|
| os.listdir(path) | zwraca w formie listy zawartość podanego folderu | 
| os.remove(file) | usuwa plik z podanej lokalizacji | 
| os.rename(oldFile, newFile) | zmienia nazwę pliku, podajemy dwa argumenty, pierwszy to istniejący plik z ścieżką, drugi nowa nazwa pliku z miejscem docelowym | 
| os.replace(oldFile, newFile) | zmienia miejsce i nazwę pliku | 
| os.path.abspath(path) | metoda ta podaje pełną ścieżkę do pliku | 
| os.path.dirname(file) | wydziela samą ścieżkę | 
| os.path.exists(file) | zwraca wartość True w przypadku gdy plik istnieje | 
| os.path.getatime(file) | zwraca datę i czas w formie liczby typu float założenia pliku | 
| os.path.getmtime(file) | zwraca datę i czas w formie liczby typu float modyfikacji pliku | 
| os.path.getsize(file) | zwraca rozmiar pliku mierzony w bajtach | 
| os.path.join(path, name.r) | łączy ścieżki lub ścieżkę i nazwę pliku | 
| os.path.split(path) | dzieli ścieżkę na dwie części i zapisuje do krotki, dzieli ścieżkę na ostatni składnik i resztę, jeżeli mamy ścieżkę do pliku to podzieli nam na ścieżkę i nazwę pliku z rozszerzeniem | 
| os.path.splitext(name.r) | rozdziela nazwę pliku z rozszerzeniem w postaci krotki gdzie mamy wydzieloną nazwę i rozszerzenie | 
Dokumentacja modułu os jest dostępna na stronach internetowych python.org moduł os.
osNa potrzeby przykładu posłużymy się folderem który zawiera kilka plików:

Wyświetlmy jakie pliki zawiera podany folder:

Można użyć pętli for do bardziej czytelnej formy prezentacji listy plików:

Sprawdźmy parametry plików takie jak, czas założenia pliku i rozmiar:

Format czasu podany w tej formie, jest niejasny dla człowieka, nie jesteśmy w stanie określić roku, dnia czy godziny. W kolejnym module poznamy metody dzięki którym będziemy w stanie zamienić liczbę na datę i czas.
datetimeDla podanych metod sposób importu biblioteki datetime wygląda w taki sposób: import datetime as dt.
| składnia | opis | 
|---|---|
| dt.datetime.now() | wywołanie aktualnej daty i czasu z dokładnością do 6 miejsc po przecinku dal sekund, w lokalnej strefie czasowej | 
| dt.timedelta.total_seconds() | |
| dt.datetime.utcnow() | wywołanie aktualnej daty i czasu z dokładnością do 6 miejsc po przecinku dal sekund, dla strefy 0 UTC | 
| dt.datetime(y, m, d, H=0, M=0, S=0, MS=0, tzinfo=None, *, fold=0) | konwertuje podane wartości na obiekt datetime, wymaga minimum trzech argumentów, y=rok, m=miesiąc, d=dzień | 
| t.isoformat() | konwertuje obiekt datetime na typ string w formacie iso, np. '2022-10-15T14:31:53' | 
| dt.datetime.fromisoformat(datetime_iso_string) | konwertuje date i czas zapisany w formacie iso na obiekt datetime, np. '2022-10-15T14:31:53' | 
| t.strftime(format) | konwertuje obiekt datetime do string używając kombinacji parametrów z tabeli poniżej | 
| dt.datetime.fromtimestamp(datetime_float) | konwertuje liczbę zmiennoprzecinkową na obiekt datetime | 
Kolejna tabela przedstawia oznaczenia formatu konwersji daty i czasu z obiektu datetime do string. Dzięki tym parametrom jesteśmy w stanie skomponować formę zapisu daty i czasu do ciąg znaków w dowolnej kombinacji.
| oznaczenie | znaczenie | przykład, wynik | 
|---|---|---|
| `%y` | zwraca dwucyfrową liczbę reprezentującą rok w obrębie jednego wieku | 01, 02, ..., 99 | 
| `%Y` | zwraca czterocyfrową liczbę reprezentującą rok | 0001, 0002, ..., 2022, 2023, ..., 9998, 9999 | 
| `%m` | zwraca dwucyfrową liczbę reprezentującą miesiąc | 01, 02, ..., 12 | 
| `%b` | zwraca trzy literowy ciąg znaków reprezentującą miesiąc | Jan, Feb, ..., Dec (en_US); | 
| `%B` | zwraca pełną nazwę miesiąca | January, February, ..., December (en_US); | 
| `%d` | zwraca dwucyfrową liczbę reprezentującą dzień w obrębie miesiąca | 01, 02, ..., 31 | 
| `%H` | zwraca dwucyfrową liczbę reprezentującą godzinę do 24h | 01, 02, ..., 24 | 
| `%I` | zwraca dwucyfrową liczbę reprezentującą godzinę do 12h | 01, 02, ..., 12 | 
| `%p` | oznaczenie pory dnia, przed południem czy popołudniu | AM, PM (en_US); | 
| `%M` | zwraca dwucyfrową liczbę reprezentującą minuty | 00, 01, 02, ..., 59 | 
| `%S` | zwraca dwucyfrową liczbę reprezentującą sekundy | 00, 01, 02, ..., 59 | 
| `%f` | zwraca sześciocyfrową liczbę reprezentującą mikrosekundy | 00, 01, 02, ..., 59 | 
| `%j` | zwraca trzycyfrową liczbę reprezentującą dzień liczony od początku roku | 001, 002, 003, ..., 366 | 
Obie tabele zostały przygotowane na podstawie dokumentacji przedstawionej na stronie python.org moduł datetime.
datetimeZacznijmy od niedokończonego zadania z modułu os, odczytaliśmy informację o założeniu pliku ale w formie liczby, która jest trudna przez człowieka do interpretacji. Zamieńmy te liczby na czas w konwencjonalnej formie. Użyjemy do tego na początek metody fromtimestamp.

Uwzględniając lokalny czas, za pomocą metody dt.timezone.utc

random| składnia | opis | 
|---|---|
| random.randint(a, b) | zwraca liczbę całkowitą n z zakresu a ≤ n ≤ b, podobną metodą jest random.randrange() | 
| random.choice(sekwencja) | zwraca jeden element z wskazanej sekwencji, sekwencją może być lista, krotka czy też ciąg znaków | 
| random.random() | zwraca liczbę zmiennoprzecinkową z zakresu [0.0, 1.0) | 
| random.uniform(a, b) | zwraca liczbę zmiennoprzecinkową n z zakresu a ≤ n ≤ b | 
| random.sample(listValues, counts=countValue, k=countSample) | zwraca listę wartości wybranych z listValues, parametr countValue odpowiada liczebnością liście listValues i służy do zwielokrotnienia występowania danej wartości na tych samych pozycjach, parametrcountSample to liczba naturalna określająca ile ma się znajdować wartości w liście wynikowej, przy czym countSample ≤ len(listValues) lub kombinacji list listValues i countValue | 
randomModuł generujący liczby pseudolosowe głównie może nam się przydać do wprowadzenia danych testowych, sztucznie wygenerowanych współrzędnych lub z puli danych przygotować część losowo wybranych obiektów.
Przyglądnijmy się jak wygenerować listę 30 liczb całkowitych w przedziale (100, 200) - nie uwzględniając liczb 100 i 200:
1import random2listaDanych = []3for i in range(30):4listaDanych.append(random.randint(101, 199))
Sprawdź wynik działania skryptu w Python.

Teraz sprawdźmy czy w naszej liście są takie liczby które występują więcej niż 1 raz, skorzystajmy z metody count którą możemy zliczyć wystąpienia w liście:

W takim razie zastosujmy metodę sample do wygenerowania liczb unikalnych w obrębie zakresu danych, możemy to wykonać podając zakres wartości z jakiego ma metoda pobierać wartości:

Po sprawdzeniu czy występują jakieś powielone liczby z podanego zakresu, program nie wykazuje nam żadnych powieleń.
Zapis i odczyt pliku tekstowego jest stosunkowo prostą operacją, komplikuje się w momencie pozyskiwania informacji z ciągu znaków. Inaczej mówiąc, gdy projektujemy sposób zapisu danych do liku tekstowego, musimy tak przygotować, zaprogramować zapis danych aby w łatwy sposób te dane ponownie wprowadzić do pierwotnej formy. Co może stanowić problem. Rozważmy zapis współrzędnych do pliku tekstowego, wiemy że część całkowita od części dziesiętnej jest separowana kropką ., jeżeli jako separator wybierzemy kropkę a nie przecinek czy średnik, to przy odczytywaniu danych będziemy mieli więcej pracy.
Odczytywanie pliku tekstowego jest obsługiwane przez metodę open, natomiast czytanie linii po linii w pliku tekstowym wykonuje się za pomocą pętli for z metodą file.readlines(). Zapisywanie danych do pliku tekstowego również odbywa się z wykorzystaniem metodę open a poszczególne elementy wprowadzamy za pomocą metody file.write(<i>tekst</i>). Zobaczmy ogólną składnie z dodatkowymi elementami:
Odczytywanie informacji zawartych z pliku txt:
1inFile = open('NameFile.txt', "r", encoding="utf8")2for line in inFile.readlines():3line.split("")4...5inFile.colse()
Zapisywanie danych do pliku txt:
1outFile = open('NameFile.txt', "w", encoding="utf8")2outFile.write(tekst)3outFile.colse()
Pobierzmy dane badawcze udostępnione na portalu Most Danych, dane te udostępnione są w formie pliku txt zawierającym współrzędne przestrzenne (x, y, z) w lokalnym systemie współrzędnych. Odczytajmy te dane za pomocą powyższych składni, obliczmy ile jest punktów w pliku.
1inFile = open(r"D:\GIS\Dane\silo.txt", "r", encoding="utf8")2sumLine = 03for xyz in inFile.readlines():4sumLine += 15print(sumLine)
Wynik działania skryptu:
Run:447693 Process finished
Zmodyfikujmy plik w taki sposób żeby w pierwszej linijce podana była informacja o nazwie kolumn: x y z
1inFile = open(r"D:\GIS\Dane\silo.txt", "r", encoding="utf8")2outFile = open(r"D:\GIS\Dane\new_silo.txt", "w", encoding="utf8")34newText = 'x y z \n'5for xyz in inFile.readlines():6newText += xyz78outFile.write(newText)

[1] Mark Summerfield, Python 3 - kompletne wprowadzenie do programowania. Helion, wydanie 2, ISBN: 978-83-246-2642-7, 2010.
[2] Dokumentacja Python. https://docs.python.org/3/, (data dostępu 10.10.2022).