Python Workshop

Transkrypt

Python Workshop
Python Workshop
Release 3f9e170, 2017-02-21
Matt Harasymczuk
2017-02-21
Wst˛ep
1
Author
2
Wst˛ep
2.1 O j˛ezyku Python . . . . . . . . . . . . . . . . .
2.1.1
Co to jest Python . . . . . . . . . . . .
2.1.2
Historia Pythona . . . . . . . . . . . .
2.1.3
Read–Eval–Print Loop . . . . . . . . .
2.1.4
Rozszerzenia plików Pythona . . . . . .
2.2 Instalacja . . . . . . . . . . . . . . . . . . . . .
2.2.1
Którego wersj˛e wybrać? . . . . . . . .
2.2.2
Który interpreter? . . . . . . . . . . . .
2.2.3
Instalacja . . . . . . . . . . . . . . . .
2.2.4
PYTHON_PATH . . . . . . . . . . . .
2.3 Podstawy składni j˛ezyka . . . . . . . . . . . . .
2.3.1
Ehlo World! . . . . . . . . . . . . . . .
2.3.2
Deklaracje na poczatku
˛ pliku . . . . . .
2.3.3
Wci˛ecia zamiast nawiasów klamrowych
2.3.4
Końce linii . . . . . . . . . . . . . . .
2.3.5
Duck typing . . . . . . . . . . . . . . .
2.3.6
Komentarze . . . . . . . . . . . . . . .
2.4 Virtualenv . . . . . . . . . . . . . . . . . . . .
2.4.1
Tworzenie wirtualnego środowiska . . .
2.4.2
Aktywacja i korzystanie ze środowiska .
2.4.3
Pakiety i zależności . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
3
3
4
4
5
5
5
6
7
7
7
7
8
8
8
9
10
10
11
11
Podstawy
3.1 Stałe, zmienne i typy danych . . . . . . . .
3.1.1
Stałe i zmienne . . . . . . . . . .
3.1.2
Numeryczne typy danych . . . . .
3.1.3
Tekstowe typy danych . . . . . .
3.1.4
Logiczne typy danych . . . . . . .
3.1.5
Złożone typy danych . . . . . . .
3.1.6
Rozszerzone typy danych . . . . .
3.1.7
Jak inicjować poszczególne typy?
3.2 Instrukcje warunkowe . . . . . . . . . . .
3.2.1 if ... elif ... else . . . . . . .
3.2.2 not, in, is . . . . . . . . . . .
3.2.3 switch statement? . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
13
14
15
15
15
15
16
16
16
16
3
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
i
3.3
3.4
3.5
3.6
3.7
3.8
3.9
3.10
3.11
3.12
3.13
3.14
ii
P˛etle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.1
Wybitnie użyteczne p˛etla for . . . . . . . . . . . . . .
3.3.2 while . . . . . . . . . . . . . . . . . . . . . . . . . .
Funkcje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.1
Definiowanie funkcji . . . . . . . . . . . . . . . . . . .
3.4.2
Konwencja nazewnicza funkcji . . . . . . . . . . . . . .
3.4.3
Argumenty do funkcji . . . . . . . . . . . . . . . . . . .
3.4.4
Zwracanie wartości . . . . . . . . . . . . . . . . . . . .
3.4.5
Operator * i ** . . . . . . . . . . . . . . . . . . . . . .
Funkcje wbudowane i słowa kluczowe . . . . . . . . . . . . . . .
3.5.1
Słowa kluczowe . . . . . . . . . . . . . . . . . . . . . .
3.5.2
Wszystkie funkcje wbudowane . . . . . . . . . . . . . .
3.5.3
Funkcje wbudowane . . . . . . . . . . . . . . . . . . .
Operatory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.6.1
Lista operatorów . . . . . . . . . . . . . . . . . . . . .
3.6.2
Operacje na typach numerycznych . . . . . . . . . . . .
3.6.3
Kolejność operatorów . . . . . . . . . . . . . . . . . . .
Pliki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.7.1
Konstrukcja with . . . . . . . . . . . . . . . . . . . .
3.7.2
Czytanie . . . . . . . . . . . . . . . . . . . . . . . . . .
3.7.3
Zapis . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.7.4
Tryby odczytu i zapisu . . . . . . . . . . . . . . . . . .
3.7.5
Obsługa wyjatków
˛
. . . . . . . . . . . . . . . . . . . .
Doctesty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Print formatting . . . . . . . . . . . . . . . . . . . . . . . . . .
3.9.1
Stary styl - %s . . . . . . . . . . . . . . . . . . . . . . .
3.9.2
Nowy styl - .format() . . . . . . . . . . . . . . . . .
3.9.3
f-strings - Python >= 3.6 . . . . . . . . . . . . . . . . .
3.9.4
Wi˛ecej informacji . . . . . . . . . . . . . . . . . . . . .
Logowanie zdarzeń . . . . . . . . . . . . . . . . . . . . . . . . .
3.10.1 Poziomy logowania . . . . . . . . . . . . . . . . . . . .
3.10.2 Korzystanie z logging . . . . . . . . . . . . . . . . .
3.10.3 Konfiguracja logowania . . . . . . . . . . . . . . . . . .
3.10.4 Konfiguracja formatowania logów . . . . . . . . . . . .
Programowanie obiektowe . . . . . . . . . . . . . . . . . . . . .
3.11.1 Paradygmat Obiektowy . . . . . . . . . . . . . . . . . .
3.11.2 Składnia . . . . . . . . . . . . . . . . . . . . . . . . . .
3.11.3 Przecia˛żanie operatorów . . . . . . . . . . . . . . . . .
3.11.4 Dobre praktyki . . . . . . . . . . . . . . . . . . . . . .
Serializacja . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.12.1 pickle . . . . . . . . . . . . . . . . . . . . . . . . . .
3.12.2 json . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.12.3 csv . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.12.4 xml . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.12.5 xslt . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wyjatki
˛ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.13.1 Po co sa˛ wyjatki?
˛
. . . . . . . . . . . . . . . . . . . . .
3.13.2 Najpopularniejsze wyjatki
˛
. . . . . . . . . . . . . . . .
3.13.3 Przechwytywanie wyjatków
˛
. . . . . . . . . . . . . . .
3.13.4 Hierarchia wyjatków
˛
. . . . . . . . . . . . . . . . . . .
Dobre praktyki . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.14.1 PEP20 - Zen of Python . . . . . . . . . . . . . . . . . .
3.14.2 PEP8 . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.14.3 Korzystanie z help(), dir() i object.__dict__
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
16
16
16
16
16
16
16
17
18
19
19
20
20
20
20
21
21
21
21
21
22
22
22
22
23
23
23
23
23
23
23
24
24
25
25
25
27
27
28
28
28
28
28
29
30
31
31
31
31
31
33
33
34
39
3.14.4 Kilka przykaładów z praktyki . . . .
3.14.5 Magic number i Magic string . . . . .
3.14.6 Passowords . . . . . . . . . . . . . .
3.14.7 Wczytywanie konfiguracji programów
3.14.8 Wersjonowanie API . . . . . . . . . .
3.15 Zadania . . . . . . . . . . . . . . . . . . . . .
3.15.1 Powielanie napisów . . . . . . . . . .
3.15.2 Parzystość . . . . . . . . . . . . . . .
3.15.3 Liczby całkowite . . . . . . . . . . .
3.15.4 Dzienniczek ucznia . . . . . . . . . .
3.15.5 Przeliczenia trygonometryczne . . . .
3.15.6 Wyrazy . . . . . . . . . . . . . . . .
3.15.7 Lotto . . . . . . . . . . . . . . . . .
3.15.8 Przeliczanie temperatury . . . . . . .
3.15.9 Pole trójkata
˛ . . . . . . . . . . . . . .
3.15.10 Wyliczanie średniej dla parametrów .
3.15.11 Konwersja liczby na zapis słowny . .
3.15.12 Rzymskie . . . . . . . . . . . . . . .
3.15.13 map(), filter() i lambda . . .
3.15.14 Zawartość pliku . . . . . . . . . . . .
3.15.15 Ksia˛żka adresowa . . . . . . . . . . .
3.15.16 Zbalansowanie nawiasów . . . . . . .
4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
39
39
39
39
39
39
39
40
40
40
41
41
41
41
42
42
42
43
43
43
43
44
Średniozaawansowany
4.1 Biblioteka standardowa . . . . . . . . . . . . .
4.1.1 datetime . . . . . . . . . . . . . . .
4.1.2 time . . . . . . . . . . . . . . . . . .
4.1.3 os . . . . . . . . . . . . . . . . . . . .
4.1.4 sys . . . . . . . . . . . . . . . . . . .
4.1.5 warnings . . . . . . . . . . . . . . .
4.1.6 pprint . . . . . . . . . . . . . . . . .
4.1.7 csv . . . . . . . . . . . . . . . . . . .
4.1.8 memoize . . . . . . . . . . . . . . . .
4.1.9 json . . . . . . . . . . . . . . . . . .
4.1.10 sqlite . . . . . . . . . . . . . . . . .
4.1.11 re . . . . . . . . . . . . . . . . . . . .
4.1.12 httplib . . . . . . . . . . . . . . . .
4.1.13 urllib . . . . . . . . . . . . . . . . .
4.1.14 socket . . . . . . . . . . . . . . . . .
4.1.15 tempfile . . . . . . . . . . . . . . .
4.1.16 io . . . . . . . . . . . . . . . . . . . .
4.1.17 functools . . . . . . . . . . . . . .
4.1.18 itertools . . . . . . . . . . . . . .
4.1.19 math . . . . . . . . . . . . . . . . . .
4.1.20 statistics . . . . . . . . . . . . .
4.1.21 random . . . . . . . . . . . . . . . . .
4.1.22 subprocess . . . . . . . . . . . . .
4.1.23 doctest . . . . . . . . . . . . . . . .
4.1.24 Collections . . . . . . . . . . . . . . .
4.2 Biblioteki zewn˛etrzne . . . . . . . . . . . . . .
4.2.1
Do zastosowań naukowych . . . . . . .
4.2.2
Wspierajacych
˛
programowanie sieciowe
4.2.3
Google App Engine . . . . . . . . . . .
4.2.4
Bazy danych . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
47
47
47
47
47
47
47
48
48
48
48
48
48
49
49
49
49
49
49
49
49
49
49
49
50
50
50
50
50
52
52
iii
4.2.5
Inne . . . . . . . . . . . . . . . . . . . . . . . .
Parametry linii poleceń . . . . . . . . . . . . . . . . . . .
4.3.1 argparse . . . . . . . . . . . . . . . . . . . .
4.3.2
Uruchamianie poleceń . . . . . . . . . . . . . .
4.3.3
Timeout dla wykonywania poleceń . . . . . . . .
4.3.4
Parsowanie i sanityzacja argumentów . . . . . .
4.4 Modularyzacja, wersjonowanie i dystrybucja . . . . . . .
4.4.1
Modularyzacja . . . . . . . . . . . . . . . . . .
4.4.2
Tworzenie paczek . . . . . . . . . . . . . . . . .
4.4.3
Instalacja i korzystanie z zewn˛etrznych bibliotek
4.4.4
Przyszłość paczkowania i dystrybucji . . . . . .
4.5 Wyrażenia regularne . . . . . . . . . . . . . . . . . . . .
4.5.1
Konstruowanie wyrażeń . . . . . . . . . . . . .
4.5.2
Wyciaganie
˛
parametrów (zmiennych) . . . . . .
4.5.3
Najcz˛eściej wykorzystywane funkcje . . . . . . .
4.5.4
Greedy search . . . . . . . . . . . . . . . . . . .
4.6 Testy . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.6.1
Doctest . . . . . . . . . . . . . . . . . . . . . .
4.6.2
Unit Test . . . . . . . . . . . . . . . . . . . . .
4.6.3 selenium . . . . . . . . . . . . . . . . . . . .
4.6.4
Mock . . . . . . . . . . . . . . . . . . . . . . .
4.6.5
Stub . . . . . . . . . . . . . . . . . . . . . . . .
4.7 Tworzenie dokumentacji . . . . . . . . . . . . . . . . . .
4.7.1
Format reStructuredText . . . . . . . . . . . . .
4.7.2
reStructuredText vs. Markdown . . . . . . . . .
4.7.3
Sphinx . . . . . . . . . . . . . . . . . . . . . . .
4.8 Django . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.8.1
Co to jest Django? . . . . . . . . . . . . . . . .
4.8.2
Architektura aplikacji Django . . . . . . . . . .
4.8.3
Modele . . . . . . . . . . . . . . . . . . . . . .
4.8.4
Widoki . . . . . . . . . . . . . . . . . . . . . .
4.8.5
Panel admina . . . . . . . . . . . . . . . . . . .
4.8.6
Dokumentacja . . . . . . . . . . . . . . . . . . .
4.8.7
Widoki generyczne . . . . . . . . . . . . . . . .
4.8.8
Localization . . . . . . . . . . . . . . . . . . . .
4.8.9
Sygnały . . . . . . . . . . . . . . . . . . . . . .
4.8.10 Migracje schematów bazy danych . . . . . . . .
4.8.11 Management Commands . . . . . . . . . . . . .
4.8.12 ORM . . . . . . . . . . . . . . . . . . . . . . .
4.8.13 Skrypty z Django . . . . . . . . . . . . . . . . .
4.9 Projektowanie GUI . . . . . . . . . . . . . . . . . . . . .
4.9.1
Biblioteka Tkinter . . . . . . . . . . . . . . . . .
4.10 Introspekcja . . . . . . . . . . . . . . . . . . . . . . . .
4.10.1 Pola obiektu . . . . . . . . . . . . . . . . . . . .
4.10.2 Metody obiektu . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
52
54
54
55
55
55
56
56
56
57
57
58
58
58
58
58
58
58
59
60
60
60
60
60
61
61
62
62
62
62
62
62
62
62
62
62
62
62
62
62
62
62
65
65
65
Zaawansowany
5.1 Generatory i list comprehension .
5.1.1
List comprehension . . .
5.1.2
Generator expressions . .
5.1.3
Operator yield . . . .
5.2 Iteratory . . . . . . . . . . . . .
5.2.1
Czym jest iterator? . . .
5.2.2
Iterowanie po obiektach .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
67
67
67
67
67
68
68
68
4.3
5
iv
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
68
69
69
69
69
69
69
69
69
69
72
73
73
73
74
75
75
75
75
75
75
75
75
76
76
76
76
76
76
76
76
76
77
79
79
80
80
81
Załaczniki
˛
6.1 Przydatne odnośniki . . . . . . . . . . . . . . . . .
6.1.1
Doumentacja . . . . . . . . . . . . . . . .
6.1.2
Video . . . . . . . . . . . . . . . . . . . .
6.1.3 Środowisko developerskie . . . . . . . . .
6.1.4
Ponadto . . . . . . . . . . . . . . . . . . .
6.1.5
Humor IT . . . . . . . . . . . . . . . . . .
6.1.6
Inne . . . . . . . . . . . . . . . . . . . . .
6.2 Python 2 vs. 3 . . . . . . . . . . . . . . . . . . . .
6.2.1 six . . . . . . . . . . . . . . . . . . . . .
6.2.2
Lista kompatybilności Python 2 i Python 3 .
6.2.3
Unicode i kodowanie znaków . . . . . . . .
6.2.4
Biblioteki standardowe w 2 i 3 . . . . . . .
6.2.5
Python 3.5 i deklaracja typów . . . . . . .
6.3 Wybór IDE . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
83
83
83
83
83
83
83
84
85
85
85
85
85
86
86
5.3
5.4
5.5
5.6
5.7
5.8
5.9
6
5.2.3
Własny iterator . . . . . . . . . . .
System Operacyjny . . . . . . . . . . . . . .
5.3.1 eval . . . . . . . . . . . . . . . .
5.3.2 sys.platform . . . . . . . . . .
5.3.3 sys.exit() . . . . . . . . . . .
5.3.4 subprocess . . . . . . . . . . .
Kolejki, watki
˛ i procesy . . . . . . . . . . .
5.4.1
Kolejki . . . . . . . . . . . . . . .
5.4.2
Watki
˛ a procesy . . . . . . . . . . .
5.4.3
Watki
˛
. . . . . . . . . . . . . . . .
5.4.4
Procesy . . . . . . . . . . . . . . .
Programowanie funkcyjne . . . . . . . . . .
5.5.1
lambda . . . . . . . . . . . . . . .
5.5.2
closure . . . . . . . . . . . . . . . .
5.5.3
decorator . . . . . . . . . . . . . .
5.5.4
złożenia funkcji . . . . . . . . . . .
5.5.5 map() . . . . . . . . . . . . . . .
5.5.6 zip() . . . . . . . . . . . . . . .
5.5.7 filter() . . . . . . . . . . . . .
5.5.8 all() . . . . . . . . . . . . . . .
5.5.9 any() . . . . . . . . . . . . . . .
Programowanie sieciowe . . . . . . . . . . .
5.6.1
Socket . . . . . . . . . . . . . . . .
5.6.2
Prosty serwer HTTP . . . . . . . .
5.6.3 httplib . . . . . . . . . . . . . .
5.6.4 urllib . . . . . . . . . . . . . . .
5.6.5 smtp . . . . . . . . . . . . . . . .
5.6.6 HTML Scrapping . . . . . . . .
Wzorce projektowe . . . . . . . . . . . . . .
5.7.1
Wzorce kreacyjne . . . . . . . . . .
C Extensions . . . . . . . . . . . . . . . . .
5.8.1
C Types . . . . . . . . . . . . . . .
5.8.2
C Modules . . . . . . . . . . . . .
Zadania . . . . . . . . . . . . . . . . . . . .
5.9.1
REST API . . . . . . . . . . . . . .
5.9.2
Generatory vs. Przetwarzanie Listy
5.9.3
Wielowatkowość
˛
. . . . . . . . . .
5.9.4
Mini Botnet . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
v
.
.
.
.
.
.
.
.
.
.
.
.
86
87
87
89
90
90
90
90
90
90
90
91
Receptury
7.1 LDAP Expiring Passwords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
93
93
6.4
6.5
6.6
7
vi
6.3.1
Czym jest IDE? . . . . .
Ekosystem Narz˛ediowy . . . . .
6.4.1
Code Quality . . . . . .
6.4.2
Automation and Releases
6.4.3
Testy Mutacyjne . . . .
6.4.4
Transifex . . . . . . . .
Ksia˛żki . . . . . . . . . . . . . .
6.5.1
Design patterns . . . . .
6.5.2
Refactoring . . . . . . .
6.5.3
Quality . . . . . . . . .
6.5.4
Python . . . . . . . . . .
Python WAT?! . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CHAPTER 1
Author
name Matt Harasymczuk
email [email protected]
www http://www.astrotech.io
facebook https://facebook.com/matt.harasymczuk
linkedin https://linkedin.com/in/mattharasymczuk
1
Python Workshop, Release 3f9e170, 2017-02-21
2
Chapter 1. Author
CHAPTER 2
Wstep
˛
O jezyku
˛
Python
Co to jest Python
Python - j˛ezyk programowania wysokiego poziomu ogólnego przeznaczenia, o rozbudowanym pakiecie
bibliotek standardowych, którego idea˛ przewodnia˛ jest czytelność i klarowność kodu źródłowego. Jego
składnia cechuje si˛e przejrzystościa˛ i zwi˛ezłościa.˛
Python wspiera różne paradygmaty programowania: obiektowy, imperatywny oraz w mniejszym stopniu
funkcyjny. Posiada w pełni dynamiczny system typów i automatyczne zarzadzanie
˛
pami˛ecia,˛ b˛edac
˛ w
tym podobnym do j˛ezyków Perl, Ruby, Scheme czy Tcl. Podobnie jak inne j˛ezyki dynamiczne jest cz˛esto
używany jako j˛ezyk skryptowy. Interpretery Pythona sa˛ dost˛epne na wiele systemów operacyjnych.
Python rozwijany jest jako projekt Open Source zarzadzany
˛
przez Python Software Foundation, która jest
organizacja˛ non-profit.
Fragment pochodzi z serwisu Wikipedia.
Historia Pythona
Pythona stworzył we wczesnych latach 90. Guido van Rossum - jako nast˛epc˛e j˛ezyka ABC, stworzonego
w Centrum voor Wiskunde en Informatica (CWI – Centrum Matematyki i Informatyki w Amsterdamie).
Van Rossum jest głównym twórca˛ Pythona, choć spory wkład w jego rozwój pochodzi od innych osób.
Z racji kluczowej roli, jaka˛ van Rossum pełni przy podejmowaniu ważnych decyzji projektowych, cz˛esto
określa si˛e go przydomkiem “Benevolent Dictator for Life” (BDFL).
Nazwa j˛ezyka nie pochodzi od zwierz˛ecia, jak można przypuszczać. Python pochodzi od serialu komediowego emitowanego w latach siedemdziesiatych
˛
przez BBC. Ten serial nosi nazw˛e “Monty Python’s
Flying Circus” (Latajacy
˛ Cyrk Monty Pythona). Projektant potrzebował nazwy, która była krótka,
unikalna i nieco tajemnicza. Na dodatek był fanem serialu, wi˛ec uważał, że taka nazwa dla j˛ezyka była
świetna.
Wersja 1.2 była ostatnia˛ wydana˛ przez CWI. Od 1995 roku Van Rossum kontynuował prac˛e nad Pythonem
w Corporation for National Research Initiatives (CNRI) w Reston w Wirginii, gdzie wydał kilka wersji
Pythona, do 1.6 włacznie.
˛
W 2000 roku van Rossum i zespół pracujacy
˛ nad rozwojem jadra
˛
Pythona
przenieśli si˛e do BeOpen.com by założyć zespół BeOpen PythonLabs. Pierwsza˛ i jedyna˛ wersja˛ wydana˛
przez BeOpen.com był Python 2.0.
Po wydaniu wersji 1.6 i opuszczeniu CNRI przez van Rossuma, który zajał
˛ si˛e programowaniem komercyjnym, uznano za wysoce pożadane,
˛
by Pythona można było używać z oprogramowaniem dost˛epnym
3
Python Workshop, Release 3f9e170, 2017-02-21
na licencji GPL. CNRI i Free Software Foundation (FSF) podj˛eły wspólny wysiłek w celu odpowiedniej modyfikacji licencji Pythona. Wersja 1.6.1 była zasadniczo identyczna z wersja˛ 1.6, z wyjatkiem
˛
kilku drobnych poprawek oraz licencji, dzi˛eki której późniejsze wersje mogły być zgodne z licencja˛ GPL.
Python 2.1 pochodzi zarówno od wersji 1.6.1, jak i 2.0.
Po wydaniu Pythona 2.0 przez BeOpen.com Guido van Rossum i inni programiści z PythonLabs przeszli
do Digital Creations. Cała własność intelektualna dodana od tego momentu, poczawszy
˛
od Pythona
2.1 (wraz z wersjami alpha i beta), jest własnościa˛ Python Software Foundation (PSF), niedochodowej
organizacji wzorowanej na Apache Software Foundation.
Fragment pochodzi z serwisu Wikipedia.
Read–Eval–Print Loop
Python spopularyzował wykorzystanie tzw. interpretera REPL (read–eval–print loop). REPL to interaktywny interpreter poleceń wykonujacy
˛ wyrażenia z j˛ezyka (zwykle linie), których wyniki sa˛ wyświetlane użytkownikowi natychmiast po ich wykonaniu. W uproszczeniu można powiedzieć, że REPL jest to linia poleceń programu python.
Znakiem zach˛ety do wprowadzania tekstu takiego programu sa˛ trzy znaki wi˛ekszości >>>. Polecenia wpisane po tych
znaczkach sa˛ interpretowane i natychmiast wykonywane. Ich wynik przedstawiany jest w nast˛epnej linijce. Jeżeli
wykorzystamy konstrukcj˛e, która wymaga wi˛ecej niż jednej linii, każda kolejna linijka b˛edzie poprzedzona trzema
kropkami .... Przykłady takiej interakcji zobaczymy przy omawianiu “Hello World”.
Rozwiazanie
˛
REPL idealnie pasuje do szybkiego testowania składni oraz funkcjonalności programów i bibliotek.
Dzi˛eki REPL jesteśmy w stanie przeprowadzić interaktywna˛ sesj˛e z linia˛ poleceń a po przetestowaniu rozwiazania
˛
wkleić działajace
˛ linie do naszego skryptu. Taki styl znaczaco
˛ przyspiesza development i debugging.
Uproszczona˛ implementacj˛e takiego rozwiazania
˛
można przedstawić w nast˛epujacy
˛ sposób:
while True:
command = raw_input('>>> ')
output = eval(command)
print(output)
W dalszej cz˛eści omówimy poszczególne elementy, które sa˛ tu wymienione.
Rozszerzenia plików Pythona
Pliki źródłowe j˛ezyka Python zarówno w wersji 2 jak i 3 maja˛ rozszerzenie .py. Podczas wytwarzania oprogramowania spotkasz si˛e jeszcze z kilkoma innymi rozszerzeniami. Moga˛ to być:
• .pyc - plik zawiera tzw. bytecode czyli efekt kompilacji kodu źródłowego. Python tworzy te pliki podczas
kompilacji jeżeli nic nie zmienimy w naszym kodzie źródłowym, wykorzystuje je bez potrzeby analizowania i kompilowania kodu ponownie. Od wersji 3.2 pliki .pyc znajduja˛ si˛e w specjalnym katalogu o nazwie
__pycache__.
• .pyd - Windowsowy plik ze skompilowanym kodem Pythona w formie biblioteki DLL.
• .pyo - pliki zawieraja˛ obiekty wykorzystywane podczas kompilacji skryptów przy wykorzystaniu flagi -O. Sa˛
to obiekty zoptymalizowane. Od wersji 3.5 Pythona te pliki nie sa˛ już tworzone.
• .pyw - Windowsowy plik z kodem źródłowym. Takie pliki odpalane sa˛ za pomoca˛ polecenia pythonw.exe
• .pyx - Źródło cPythona, które b˛edzie przekonwertowane do C/C++
• .pyz - Python 3.5 wprowadził możliwość tworzenia Python ZIP Archive. Takie spakowane archiwum zawiera
wszystkie pliki niezb˛edne do uruchomienia programu. Rozszerzenie dla obiektów tego typu jest .pyz. Do
pakowania służy biblioteka zipapp.
4
Chapter 2. Wstep
˛
Python Workshop, Release 3f9e170, 2017-02-21
Instalacja
Którego wersje˛ wybrać?
Python kilka lat temu przeszedł drastyczna˛ transformacj˛e. Projekt Python 3 miał całkowicie zmienić sposób w jaki
kompilator traktuje kod źródłowy. Dotychczas wszystkie ciagi
˛ znaków traktowane były jako ciagi
˛ ASCII. Od teraz
miało to ulec zmianie a konto popularnego na całym świecie kodowania UTF-8. Wcześniej, aby skorzystać z takiego
zachowania należało przed stringiem umieścić literk˛e “u”, np. u’Hello World!’ aby kompilator zrozumiał
kodowanie. Niestety nie było to domyślne kodowanie i z tego powodu konieczne było ciagłe
˛ żonglowanie funkcjami
.encode() i .decode().
Ponadto w nowym j˛ezyku Python 3 (czasami zwanym Python 3k [3k = 3000] aby pokazać, że drastycznie si˛e różni
od wersji 2) scalono niektóre moduły biblioteki standardowej oraz zmieniono zachowanie niektórych funkcji w tym
bardzo cz˛esto wykorzystywanej print(), która wcześniej była słowem kluczowym w j˛ezyku.
Jeżeli rozpoczynasz nauk˛e programowania wybierz nowego Pythona 3. Jeżeli tworzysz nowy projekt wybierz podobnie. Na chwil˛e obecna˛ jedynym uzasadnieniem wyboru starszej wersji jest niekompatybilność niektórych bibliotek i
projektów zewn˛etrznych. Na szcz˛eście z miesiaca
˛ na miesiac
˛ lista projektów “Python 3 compliant” wzrasta i wybór
pozostaje coraz bardziej oczywisty.
Ostatnia˛ wersja˛ gał˛ezi 2 jest 2.7. Wersja ta zawiera elementy i składni˛e ułatwiajace
˛ konwersj˛e programów do nowego
środowiska i pozwala na pisanie aplikacji i skryptów, które powinny uruchomić si˛e zarówno przy wykorzystaniu
interpretera python2 jak i python3. Wersja 2.7 jest ostatnia˛ z rodziny 2 i b˛eda˛ do niej wypuszczane jedynie
poprawki bezpieczeństwa.
Który interpreter?
Sam Python jest tak naprawd˛e tylko specyfikacja˛ składni oraz wygladu
˛ biblioteki standardowej. Python ma obecnie
kilka interpreterów z których najbardziej popularny jest cPython, który jest wydawany razem z nowa˛ wersja˛ specyfikacji j˛ezyka.
cPython
Domyślna˛ wersja˛ Pythona jest cPython. Jest to tzw. implementacja wzorcowa i to jej kompilator jest wydawany wraz
ze specyfikacja˛ nowych funkcjonalności przy każdym wydaniu Python. Sam kompilator jest rozwijany w j˛ezyku C.
cPython jest najbardziej popularna˛ dystrybucja˛ z wszystkich wydań. W poniższych materiałach to właśnie z tej wersji
b˛edziemy korzystać.
PyPy
Bardzo ciekawy projekt napisania interpretera Pythona w... Pythonie. Kompilator dokonuje bardzo wielu
niskopoziomowych optymalizacji dlatego ta wersja j˛ezyka jest wyjatkowo
˛
szybka. Niestety nie wszystkie biblioteki
zewn˛etrzne sa˛ z nia˛ kompatybilne. Nie mniej projekt jest wcia˛ż aktywnie rozwijany przez bardzo pomysłowych
programistów i stanowi solidna˛ alternatyw˛e dla cPythona. Niektóre programy przy wykorzystaniu PyPy potrafia˛
przyspieszyć kilkuset do kilkutysiac
˛ krotnie.
IronPython
Próba implementacji j˛ezyka Python wykorzystujac
˛ platform˛e .NET firmy Microsoft. Dzi˛eki temu j˛ezyk bardzo dobrze
integruje si˛e z całym środowiskiem.
2.2. Instalacja
5
Python Workshop, Release 3f9e170, 2017-02-21
Jython
Próba implementacji j˛ezyka Python wykorzystujac
˛ platform˛e wirtualnej maszyny JAVA (JVM). Projekt bardzo obiecujacy
˛ lecz niestety ostatnio słabo rozwijany. JVM stanowi bardzo dobra˛ platform˛e dobrze “wygrzana”
˛ oraz poznana˛
pod wzgl˛edem wydajnościowym jak i środowiska developerskiego.
Inne
W internecie jest dost˛epnych jeszcze wi˛ecej implementacji j˛ezyka. Niektóre projekty sa˛ jeszcze rozwijane, niektóre
(Stackless Python) weszły w skład lub transformowały si˛e w wyżej wymienionych lub zostały zarzucone (Unleaden
Swallow).
Instalacja
Windows
Aby zainstalować Python na środowisku Windows należy pobrać instalator z python.org a nast˛epnie przejść przez
wszystkie kroki kreatora. Po instalacji należy wylogować si˛e i zalogować ponownie aby odświeżyć zmienna˛ PATH.
Po tym procesie w Windowsowej liście poleceń (cmd) b˛edzie dost˛epny program python. Ponadto wraz z instalacja˛ Pythona na Twoim komputerze zainstaluje si˛e edytor Idle, który w poczatkowej
˛
fazie nauki tworzenia oprogramowania powinien nam w zupełności wystarczyć.
OS X
Jeżeli posiadasz OS X to Python powinien być domyślnie zainstalowany na Twoim komputerze. Apple w najnowszych
systemach operacyjnych standardowo dostarcza Pythona w wersji 2.7 i 2.6. Domyślnie po wpisaniu polecenia
python uruchamiany jest 2.7. Aby zainstalować Pythona w wersji 3 możemy skorzystać z managera pakietów
brew albo z tzw. macports. Osobiście polecam to pierwsze podejście. Brew dost˛epny jest za darmo i można pobrać
go z internetu uruchamiajac
˛ polecenie ze strony Brew. Najpierw jednak konieczne b˛edzie zainstalowanie najnowszej
wersji Xcode z AppStore. Brew powinien zrobić to za Ciebie.
Sama instalacja brew sprowadza do uruchomienia polecenia wygladaj
˛ acego
˛
jak nast˛epujace:
˛
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Nast˛epnie po instalacji:
brew install python3
I już możemy cieszyć si˛e najnowszym Pythonem.
Linux
Niemalże wszystkie dystrybucje Linuxa posiadaja˛ zainstalowana˛ wersj˛e Pythona w wersji 2. Aby zainstalować trójk˛e
użyj swojego managera pakietów apt-get, yum czy emerge czy rpm w zależności od dystrybucji.
6
Chapter 2. Wstep
˛
Python Workshop, Release 3f9e170, 2017-02-21
PYTHON_PATH
Podstawy składni jezyka
˛
Ehlo World!
W lekcjach programowania utarło si˛e, że zawsze zaczynamy od już przysłowiowego “Hello World”. Skrypty czy
programy tego typu nie maja˛ na celu pokazania jak minimalna˛ ilościa˛ znaków da si˛e wyświetlić coś na ekranie, a
sposób interakcji i przepływu programista-komputer.
W Pythonie mamy możliwość wykorzystania interpretera REPL, przykład poniżej oraz stworzenia skryptu, który
wykonamy z linii poleceń.
$ python3
Python 3.5.1 (default, Dec 7 2015, 21:59:10)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.1.76)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print('Hello World!')
Hello World!
Powyższy przykład ilustruje moment wpisania polecenia python, standardowy tekst informujacy
˛ o wersji i kompilacji j˛ezyka oraz znak zach˛ety >>> (ang. prompt). Polecenia wpisujemy po tym znaku a ich wynik wyświetla si˛e
poniżej (i nie zawiera wci˛ecia). Dalej w materiałach b˛edziemy posługiwali si˛e już samym znakiem zach˛ety.
Drugim sposobem jest stworzenie skryptu posiadajacego
˛
nast˛epujace
˛ linie. Ta metoda przydaje nam si˛e gdy nasze
programy zaczna˛ rosnać
˛ na wi˛ecej niż jedna˛ dwie linijki. Warto zwrócić uwag˛e na pierwsza˛ lini˛e, na tzw. shebang
#! i nast˛epujace
˛ po nim polecenie. To jest deklaracja programu, którego kod źródłowy znajduje si˛e poniżej. Linijka
ta jest opcjonalna, ale dla zachowania poprawności i warto w naszych skryptach coś takiego zadeklarować. Już po
pierwszej linii widzimy, że skrypt b˛edzie zinterpretowany jako kod źródłowy trzeciej wersji Pythona.
#!/usr/bin/env python3
print('Hello World!')
Wynik uruchomienia powyższego skryptu b˛edzie identyczny z efektem uzyskanym w REPL, tzn, na naszym ekranie
ukaże si˛e napis Hello World.
Dla wszystkich, którzy potrzebuja˛ wiedzieć jak wyglada
˛ najmniejszy kod, który wyświetli nam te słowa polecam
poniższy kod.
print('Hello World!')
Deklaracje na poczatku
˛
pliku
Deklaracja interpretera
Jest to specjalny rodzaj komentarza który opisaliśmy pokrótce powyżej. Ten typ komentarza wyst˛epuje tylko w pierwszej linii programu i definiuje interpreter kodu źródłowego dla kodu poniżej.
#!/usr/bin/env python3
2.3. Podstawy składni jezyka
˛
7
Python Workshop, Release 3f9e170, 2017-02-21
Deklaracja kodowania znaków w pliku
Jest to kolejny rodzaj specjalnego komentarza, który instruuje interpreter i jawnie wskazuje na sposób kodowania
znaków w pliku z kodem źródłowym. W skryptach Pythona w wersji drugiej był obowiazkowy,
˛
jeżeli w kodzie lub
komentarzach w pliku znajdowały si˛e znaki z poza zakresu ASCII, np. polskie znaki diakrytyczne a,˛ e˛ , ś, ć itp.
# -*- coding: utf-8 -*-
Informacja na temat modułu
Pierwszy wielolinijkowy komentarz w pliku jest traktowany jako opis modułu. Może si˛e w nim znajdować np. licencja
użytkowania programu, instrukcja jego obsługi itp. Bardzo ciekawym pomysłem jest również napisanie komentarza
opisujacego
˛
parametry programów wykorzystujacego
˛
standard *unix takiego opisu. Dzi˛eki temu poza samym jednoznacznym opisem działania programu zgodnym z ogólnie przyj˛eta˛ konwencja˛ dostajemy możliwość wykorzystania
modułu docopt do jego sparsowania i obsługi parametrów przekazywanych z linii poleceń.
Docopt bierze opis z komentarza i parsuje zmienne zgodnie z instrukcja˛ czyniac
˛ niektóre elementy obligatoryjnymi,
możliwymi do podania jedno- lub wielokrotnie itp. Samym opisem działania tego modułu zajmiemy si˛e w sekcji jemu
poświ˛econej.
Wciecia
˛
zamiast nawiasów klamrowych
Jest to chyba najbardziej ciekawa rzecz w samym j˛ezyku. Autorzy specyfikacji zdecydowali si˛e na zastapienie
˛
nawiasów klamrowych wci˛eciami, czyli tzw. białymi spacjami (ang. whitespace). Jest to dość nietypowe rozwiazanie,
˛
które okazało si˛e bardzo rewolucyjne i niesamowicie podniosło czytelność kodu źródłowego.
Sama idea spowodowała duża˛ polaryzacj˛e programistów. Jedni bardzo sobie chwala˛ to rozwiazanie,
˛
a inni
przyzwyczajeni do j˛ezyków przypominajacych
˛
składnia˛ C sa˛ jej zaciekłymi wrogami. Osobiście jestem wielkim
zwolennikiem takiego rozwiazania!
˛
>>> from __future__ import braces
File "<stdin>", line 1
SyntaxError: not a chance
Końce linii
Pierwsza˛ rzecza˛ (poza znaczacymi
˛
wci˛eciami), która może zaskoczyć programistów przyzwyczajonych do składni C
jest brak konieczności, a nawet zalecenie do niestawiania znaku średnika ; na końcu linii. Programy interpretowane
sa˛ linia po linii. Linia kończy si˛e tam, gdzie ostatni znak polecenia.
Python pozwala na stosowanie znaków końca linii zarówno znanych z systemów Windows (rn) jak i środowiska *nix
(n). W tych materiałach b˛edziemy posługiwali si˛e znakiem n symbolizujacym
˛
koniec linii.
Duck typing
W j˛ezykach programowania można doszukać si˛e wielu systemów typowania. System typowania informuje kompilator o obiekcie oraz o jego zachowaniach. Ponadto niesie za soba˛ informacj˛e na temat ilości pami˛eci, która˛ trzeba
dla takiego obiektu zarezerwować. Istnieje nawet cała gałaź
˛ zajmujaca
˛ si˛e systemami typów. Obecnie najcz˛eściej
wykorzystywane j˛ezyki programowania dziela˛ si˛e na statycznie - silnie typowane (JAVA, C, C++ i pochodne) oraz
dynamicznie - słabo typowane (Python, Ruby, PHP itp.). Oczywiście moga˛ znaleźć si˛e rozwiazania
˛
hybrydowe oraz z
tzw. inrefencja˛ typów itp.
8
Chapter 2. Wstep
˛
Python Workshop, Release 3f9e170, 2017-02-21
W naszym przypadku skupmy si˛e na samym mechanizmie dynamicznego typowania. Określenie to oznacza, że j˛ezyk
nie posiada typów zmiennych i obiektów, które jawnie trzeba deklarować. Inicjujac
˛ zmienna˛ nie musimy powiedzieć,
że jest to int. Co wi˛ecej po chwili do tej zmiennej możemy przypisać dowolny obiekt, np. łańcuch znaków i
kompilator nie powie nam złego słowa. Kompilator podczas działania oprogramowania niejawnie może zmienić typ
obiektu i dokonać na nim konwersji.
Wśród programistów popularne jest powiedzenie “jeżeli chodzi jak kaczka i kwacze jak kaczka, to musi być to
kaczka”. Od tego powiedzenia wzi˛eła si˛e nazwa Duck typing. Określenie to jest wykorzystywane w stosunku do
j˛ezyków, których typy obiektów rozpoznawane sa˛ po metodach, które można na nich wykonać. Nie zawsze takie
zgadywanie jest celne i jednoznacznie i precyzyjnie określa typ. Może si˛e okazać, że obiekt np. Samochód posiada
metody uruchom_silnik() i jedz_prosto() podobnie jak Motor. Jeden i drugi obiekt b˛edzie zachowywał
si˛e podobnie. J˛ezyki wykorzystujace
˛ ten mechanizm wykorzystuja˛ specjalne metody porównawcze, które jednoznacznie daja˛ informacj˛e kompilatorowi czy dwa obiekty sa˛ równe.
Sam mechanizm dynamicznego typowania jest dość kontrowersyjny, ze wzgl˛edu na możliwość bycia nieścisłym. W
praktyce okazuje si˛e, że rozwój oprogramowania wykorzystujacego
˛
ten sposób jest dużo szybszy. Za to zwolennicy
statycznego typowania, twierdza,˛ że projekty wykorzystujace
˛ duck typing sa˛ trudne w utrzymaniu po latach. Celem
tego dokumentu nie jest udowadnianie wyższości jednego rozwiazania
˛
nad drugim. Zach˛ecam jednak do zapoznania
si˛e z wykładem “The Unreasonable Effectiveness of Dynamic Typing for Practical Programs”, którego autorem jest
“Robert Smallshire”. Wykład zamieszczonym został w serwisie InfoQ (http://www.infoq.com/presentations/dynamicstatic-typing). Wykład w ciekawy sposób dotyka problematyki porównania tych dwóch metod systemu typów. Wykład
jest o tyle ciekawy, że bazuje na statystycznej analizie projektów umieszczonych na https://github.com a nie tylko
bazuje na domysłach i flamewar jakie programiści lubia˛ prowadzić.
Wszystko jest obiektem
W Pythonie wszystkie rzeczy sa˛ obiektem. Każdy element posiada swoje metody, które możemy na nim uruchomić.
W dalszej cz˛eści tych materiałów b˛edziemy korzystali z polecenia help() aby zobaczyć jakiego z jakiego typu
obiektem mamy okazj˛e pracować oraz co możemy z nim zrobić.
Komentarze
Komentarze sa˛ wykorzystywane by podpowiedzieć programiście, który b˛edzie czytał kod źródłowy w przyszłości co
dana funkcja, metoda lub po prostu kolejna linijka kodu robi. Jestem wielkim fanem pisania tak swoich programów,
aby komentarze w kodzie były zb˛edne. Dobrego dzielenia aplikacji na mniejsze cz˛eści, właściwego stosowania whitespace’ów, precyzyjnego i opisowego ich nazywania. Komentarze moga˛ być bardzo przydatne, ale w wi˛ekszości sytuacji
jeżeli potrzebujemy z nich skorzystać to znaczy, że logicznie źle rozplanowaliśmy układ naszego kodu. Ponadto komentarze maja˛ brzydka˛ właściwość szybkiego starzenia si˛e, tzn. kod ewoluuje, a komentarz opisuje zachowanie starej
funkcji. Może to powodować dezinformacj˛e.
Zakomentowany kod
Bardzo cz˛esto spotykam si˛e z problemem zakomntowanego kodu. O ile komentarze opisujace
˛ działanie poszczególnych elementów sa˛ użyteczne to zakomentowany kod jest nieakceptowalny. Cz˛esto stosujemy ta˛ technik˛e by chwilowo
wyłaczyć
˛
działanie jakiejś funkcjonalności. Jednakże niedopuszczalne jest commitowanie zmian zawierajacych
˛
zakomentowany kod. Kod taki bardzo cz˛esto jest już niedziałajacy
˛ i taki pozostanie na zawsze. Bardzo cz˛esto słysz˛e
argument, że może kiedyś b˛edziemy chcieli powrócić do tego kodu i bez sensu b˛edzie go wymyślać i pisać na nowo.
W dobie systemów kontroli wersji sytuacja ta nie b˛edzie stwarzała jakiegokolwiek problemu. Wystarczy przeglad˛
nać
˛ diffa (podglad
˛ różnicowy) pliku albo wykonać git blame i mamy dost˛ep do starego sposobu.
Nieuruchamiajacy
˛ si˛e i niewywoływany kod nie powinien znaleźć si˛e w repozytorium. Kropka!
2.3. Podstawy składni jezyka
˛
9
Python Workshop, Release 3f9e170, 2017-02-21
Komentowanie linii
W Pythonie mamy kilka sposobów komentowania. Najprostszym z nich jest komentowanie całej linii poprzez wykorzystanie znaku zwanego “pound” lub “hash” #. Ciag
˛ znaków znajdujacych
˛
si˛e za # zostanie zignorowany przez
kompilator.
>>> #na ekranie otrzymamy: Hello World!
... print('Hello World!')
Hello Wold!
Tu możemy zaobserwować zachowanie, o którym wspominaliśmy troch˛e wcześniej, tzn. kontynuacja jest oznaczana
przez znak zach˛ety trzech kropek ....
Komentarze inline
Kolejnym sposobem jest komentowanie inline tzn. w linijce. Tego typu komentarze stosuje si˛e aby wytłumaczyć
zachowanie poszczególnych linii kodu. Choć kompilator dopuszcza ich stosowanie, to w ramach dobrych praktyk
lepiej zastapić
˛ je komentarzami w linijce poprzedzajacej
˛ wywołanie.
>>> print('Hello Wold!') #na ekranie otrzymamy: Hello World!
Hello Wold!
Komentarze wieloliniowe
Komentarze wieloliniowe w Pythonie można robić na dwa sposoby poprzez wykorzystanie trzech znaków cudzysłowia:
• pojedynczego ’’’,
• podwójnego """.
W jednym i drugim przypadku cudzysłowie podwójne lub pojedyncze b˛edzie oznaczało poczatek
˛ jak i koniec komentarza. Rodzaj cudzysłowiów nie ma znaczenia, ale utarło si˛e aby stosować podwójne ". W materiałach b˛edziemy
korzystać właśnie z tej notacji.
"""
Tu jest treść komentarza, który obejmuje wiele linii
W ramach dobrych praktyk, powinniśmy takim komentarzem opisać każda˛ z funkcji,
aby narz˛
edzia takie jak np. ``help()`` wyświetlały ładne podpowiadanie działania.
"""
Sa˛ dwie szkoły tworzenia takich komentarzy. Jedna mówi, aby tekst pisać bezpośrednio po znaku cudzysłowia, a
druga od nowej linijki. Jest to kwestia estetyki i czytelności komentarza.
Virtualenv
Tworzenie wirtualnego środowiska
Wraz z wersja˛ Python 3.3 do j˛ezyka został dodany ten genialny moduł. Aplikacja ta odpowiada na problem zarzadzania
˛
zależnościami na Twojej maszynie. Dzi˛eki użyciu Virtualenv (po właczeniu
˛
jako standard zwany pyvenv. Mamy
możliwość do tworzenia tzw. wirtualnych środowisk Pythona. Środowisko to zawiera w sobie plik wykonywalny
j˛ezyka oraz wszystkie potrzebne biblioteki wewn˛etrzne i zewn˛etrzne. Takie środowiska możemy tworzyć per projekt
i nie musimy martwić si˛e, że Projekt A wymaga np. Django w wersji 1.8 a Projekt B w 1.9.
Tworzenie takiego środowiska jest bardzo łatwe i szybkie:
10
Chapter 2. Wstep
˛
Python Workshop, Release 3f9e170, 2017-02-21
pyvenv .virtualenv
lub na Windowsie:
python3 -m venv .virtualenv
Aktywacja i korzystanie ze środowiska
I po chwili w pojawi si˛e katalog .virtualenv ze środowiskiem. Nast˛epnie za każdym razem kiedy b˛edziesz chciał
pracować wykorzystujac
˛ to środowisko b˛edzie konieczna jego aktywacja:
source .virtualenv/bin/activate
lub na Windowsie:
.virtualenv\bin\activate.bat
Pakiety i zależności
Instalacja pakietów
Każda instalacja pakietów oraz bibliotek wykona si˛e w środowisku. Skrypt który uruchomisz wykorzysta właśnie te
wersje, które masz w nim zainstalowane.
Aby zainstalować jakieś nowe paczki należy użyć polecenia pip. Od wersji Python 3.4 pip jest zainstalowany
domyślnie.
pip install pep8
lub na Windows:
python -m pip install pep8
Lista zainstalowanych paczek
Aby zobaczyć zainstalowane paczki, użyj polecenia pip freeze. Przekierowujac
˛ wynik tego polecenia do pliku
requirements.txt stworzysz list˛e zależności wraz z wersjami, które sa˛ niezb˛edne dla uruchomienia Twojego
programu.
pip freeze > requirements.txt
lub na Windows:
python -m pip install pep8
Wi˛ecej na temat instalowania paczek, modularyzacji itp. znajdziesz w rozdziale tej ksia˛żki poświ˛econym temu tematowi.
2.4. Virtualenv
11
Python Workshop, Release 3f9e170, 2017-02-21
12
Chapter 2. Wstep
˛
CHAPTER 3
Podstawy
Stałe, zmienne i typy danych
Stałe i zmienne
Deklarowanie zmiennych
moja_zmienna = 10
moja_zmienna = 'przykladowy tekst'
Deklarowanie stałych
MOJA_STALA = 10 MOJA_STALA = ‘przykladowy tekst’
Różnica miedzy
˛
stałymi i zmiennymi
Zasieg
˛ widoczności
• globals()
• locals()
Numeryczne typy danych
int - Liczba całkowita
Jednym z najbardziej podstawowych typów danych jest int. int() jest funkcja˛ wbudowana,˛ która zamieni swój
argument na liczb˛e całkowita.˛
float - Liczba zmiennoprzecinkowa
float w Pythonie reprezentuje liczb˛e zmiennoprzecinkowa.˛ Ciekawa˛ własnościa˛ tego typu jest możliwość reprezentacji nieskończoności za pomoca˛ Infinity oraz minus nieskończoności -Infinity. Wi˛ecej szczegółów dost˛epnych jest w dokumentacji dla tego typu
Podobnie jak pozostałe typy float() jest funkcja,˛ która konwertuje swój argument na liczb˛e zmiennoprzecinkowa.˛
13
Python Workshop, Release 3f9e170, 2017-02-21
>>> float('+1.23')
1.23
>>> float('
-12345\n')
-12345.0
>>> float('1e-003')
0.001
>>> float('+1E6')
1000000.0
>>> float('-Infinity')
-inf
complex - liczba zespolona
complex reprezentuje typ liczby zespolonej posiadajacej
˛ cz˛eść rzeczywista˛ oraz urojona.˛ Należy zwrócić uwag˛e,
że argument powinien być ciagiem
˛
znaków niezawierajacym
˛
spacji. W przeciwnym przypadku otrzymamy
ValueError.
>>> complex('1+2j')
(1+2j)
>>> complex('1 + 2j')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: complex() arg is a malformed string
Tekstowe typy danych
str - Ciag
˛ znaków
Obiekt typu str przechowuje łańcuch znaków. str() jest także funkcja,˛ która zwraca ciag
˛ znaków z argumentu.
Niemutowalność
Ważna˛ cecha˛ ciagów
˛
znakowych jest tzw. niemutowalność. Gdy wykonujemy operacj˛e na stringu tworzona jest jego
nowa kopia.
Różnica miedzy
˛
‘a“
Python nie rozróżnia czy stosujemy pojedyncze znaki cudzysłowiu czy podwójne. Ważne jest aby wybrać jedna˛
konwencj˛e i si˛e jej konsekwentnie trzymać.
Interpreter Pythona domyślnie stosuje pojedyncze znaki cudzysłowia, z tego powodu w tym materiale b˛edziemy trzymać si˛e tej konwencji.
Operacje na stringach
• strip(), lstrip(), rstrip()
• join()
• startswith()
• title()
14
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
• replace()
• Wycinanie cz˛eści stringów
Konwersja stringów
• bin()
• hex()
• oct()
Logiczne typy danych
bool - Wartość logiczna
Obiekt typu bool może przyjać
˛ dwie wartości logiczne:
• True
• False
Zwróć uwag˛e na wielkość liter!
bool() to także funkcja wbudowana w j˛ezyk Python, która zwraca wartość logiczna˛ wyrażenia.
None - Wartość pusta
Złożone typy danych
tuple - Krotka
list - Lista
set - Zbiór
dict - Słownik
Dobieranie sie˛ do wartości elementów
[0] i .get(0)
Rozszerzone typy danych
Lista słowników
Listy wielowymiarowe
Drzewa
Jak inicjować poszczególne typy?
• dict() czy {}
3.1. Stałe, zmienne i typy danych
15
Python Workshop, Release 3f9e170, 2017-02-21
• list() czy []
• tuple() czy ()
• set() czy {}
Instrukcje warunkowe
if ... elif ... else
if not 0 <= k <= n:
raise ValueError("Sample larger than population")
not, in, is
switch statement?
P˛etle
Wybitnie użyteczne petla
˛
for
while
Funkcje
Definiowanie funkcji
def hello():
print('hello world')
Konwencja nazewnicza funkcji
• CamelCase? Nie?! Używanie _ w nazwach
• Funkcje o nazwie zaczynajacej
˛ si˛e od _ przez konwencj˛e sa˛ traktowane jako prywatne (w Pythonie nie ma
private/protected/public).
• Funkcje o nazwie zaczynajacej
˛ si˛e od __ i kończacych
˛
si˛e na __ przez konwencj˛e sa˛ traktowane jako systemowe.
• Nazwy opisowe funkcji
Argumenty do funkcji
>>> def dodaj(a, b):
...
return a + b
>>> dodaj(1, 2)
3
16
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
Argumenty nazwane
>>> def dodaj(a, b):
...
return a + b
>>> dodaj(a=1, b=2)
3
Argumenty z wartościa˛ domyślna˛
>>> def hello(tekst='hello world'):
...
print(tekst)
>>> hello(tekst='ehlo')
ehlo
>>> hello()
hello world
Zwracanie wartości
Zwracanie wartości prostych
def foo1():
return True
def foo2():
return None
def foo3():
return 'bar'
def foo4():
return [10, 20]
def foo5():
return foo1
def foo6():
pass
def foo7():
return 10, 20, 30, 5, 'a'
def foo8():
return {'imie': 'Matt', 'nazwisko': 'Harasymczuk'}
Zwracanie typów złożonych
def foo9():
return [
{'imie': 'Matt', 'nazwisko': 'Harasymczuk'},
{'imie': 'Matt', 'nazwisko': 'Harasymczuk'},
{'imie': 'Matt', 'nazwisko': 'Harasymczuk'}]
3.4. Funkcje
17
Python Workshop, Release 3f9e170, 2017-02-21
Rozpakowywanie wartości zwracanych
>>> napiece, natezenie, *args = foo7()
>>> napiecie, *_ = foo7()
>>> value, _ = function()
>>> value, *args = function()
Operator * i **
Argumenty *args, **kwargs
def foo(a, b, *args, **kwargs):
print(locals())
Przy wywołaniu funkcji
foo(1, 2, **{'napiecie':10, 'natezenie': 20, 'moc': 3})
foo(
1,
2,
napiecie=10,
natezenie=20,
moc=3)
def bar():
return range(0, 5)
jeden, dwa, *reszta = bar()
print(jeden, dwa, reszta)
def foobar(a, b, *args):
print(locals())
foobar(1, 2, 5, 7)
def foobar(a, b, **kwargs):
print(locals())
foobar(1, 2, 5, 7)
Przykładowe zastosowanie
18
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
class Osoba:
first_name = 'Matt'
last_name = 'Harasymczuk'
def __str__(self):
return '{first_name} {last_name}'.format(**self.__dict__)
Funkcje wbudowane i słowa kluczowe
Słowa kluczowe
pass
continue
break
return
sorted
range
isinstance()
__file__
__name__
if __name__ == '__main__':
print('hello world')
import logging
log = logging.getLogger(__name__)
3.5. Funkcje wbudowane i słowa kluczowe
19
Python Workshop, Release 3f9e170, 2017-02-21
Wszystkie funkcje wbudowane
abs()
all()
any()
ascii()
bin()
bool()
bytearray()
bytes()
callable()
chr()
classmethod()
compile()
complex()
delattr()
dict()
dir()
divmod()
enumerate()
eval()
exec()
filter()
float()
format()
frozenset()
getattr()
globals()
hasattr()
hash()
Built-in Functions
help()
hex()
id()
input()
int()
isinstance()
issubclass()
iter()
len()
list()
locals()
map()
max()
memoryview()
min()
next()
object()
oct()
open()
ord()
pow()
print()
property()
range()
repr()
reversed()
round()
set()
setattr()
slice()
sorted()
staticmethod()
str()
sum()
super()
tuple()
type()
vars()
zip()
__import__
Funkcje wbudowane
min()
max()
len()
input()
Operatory
Lista operatorów
Operacja
%
**
\\
<
+=
<=
>
>=
==
!=
is
is not
in
not in
20
Znaczenie
modulo (reszta)
pot˛ega pow()
dzielenie bez reszty
mniejsze niż
dodanie i przypisanie
mniejsze lub równe
wi˛eksze niż
wi˛eksze lub równe
równe
różne
obiekty sa˛ tożsame
obiekty nie sa˛ tożsame
obiekty sa˛ tożsame
obiekty nie sa˛ tożsame
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
Operacje na typach numerycznych
Operacja
x + y
x - y
x * y
x / y
x // y
x % y
-x
+x
abs(x)
int(x)
float(x)
complex(re, im)
divmod(x, y)
pow(x, y)
x ** y
Rezultat
suma x i y
różnica x i y
iloczyn x i y
iloraz x i y
podłoga z ilorazu x i y
reszta z dzielenia x / y
x negacja
x bez zmiany
wartość bezwzgl˛edna x
x przekonwertowane do int
x przekonwertowane do float
liczba zespolona: re - cz˛eść rzeczywista im - cz˛eść urojona
para (x // y, x % y)
x podniesione do pot˛egi y
x do pot˛egi y
Kolejność operatorów
• modulo
• // i **
• przypisania i porównania
• +=
• in i not in
Pliki
Konstrukcja with
• Context manager
Czytanie
with open(FILENAME) as file:
content = file.read()
with open(FILENAME) as file:
content = file.readlines()
with open(FILENAME) as file:
for line in file:
print(line)
3.7. Pliki
21
Python Workshop, Release 3f9e170, 2017-02-21
Zapis
with open(FILENAME, 'w') as file:
file.write('foobar')
with open(FILENAME, 'a') as file:
file.write('foobar')
Tryby odczytu i zapisu
Character
’r’
’w’
’x’
’a’
’b’
’t’
’+’
’U’
Meaning
open for reading (default)
open for writing, truncating the file first
open for exclusive creation, failing if the file already exists
open for writing, appending to the end of the file if it exists
binary mode
text mode (default)
open a disk file for updating (reading and writing)
universal newlines mode (deprecated)
Obsługa wyjatków
˛
FILENAME = input('Podaj nazw˛
e pliku: ')
try:
with open(FILENAME, 'w') as file:
content = file.read()
print(content)
except FileNotFoundError:
print('File does not exists')
except PermissionError:
print('Brak uprawnien')
Doctesty
Niezwykle użytecznym sposobem komentowania sa˛ tzw. doctesty. W wielolinijkowym komentarzu wpisujemy sesj˛e
z interpreterem a po uruchomieniu doctestów otrzymujemy informacj˛e czy nasza funkcja poprawnie si˛e wykonuje.
Jest to bardzo proste narz˛edzie, które poza samym pokazaniem jak działa funkcja, jakie parametry przyjmuje i co
zwraca daje możliwość weryfikacji poprawności działania kodu. W tych materiałach nieraz b˛edziemy korzystać z
tego rozwiazania.
˛
def sumowanie_liczb(a, b):
"""Funkcja sumuje dwie liczby podane jako argumenty:
>>> sumowanie_liczb(1, 2)
3
>>> sumowanie_liczb(-1, 1)
0
>>> sumowanie_liczb(0, 0)
22
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
0
"""
return a + b
Wykorzystujac
˛ taki zapis natychmiast widzimy co dzieje si˛e w danym rozwiazaniu.
˛
Doctesty bardzo przydaja˛
si˛e przede wszystkim do zastosowań wykorzystujacych
˛
wyrażenia regularne, których zrozumienie zapisu cz˛esto
wymaga chwili zastanowienia.
Print formatting
Stary styl - %s
• kolejnościowe
• nazwane
• typy: string, int, float
• operatory na stringu
Nowy styl - .format()
• string
• int
• float
• operatory na stringu
• jako parametry do print("string", **args)
f-strings - Python >= 3.6
• f’{variable}’
• f’{self.field}’
• f’{datetime:%Y-%m-%d %H:%M}’
Wiecej
˛
informacji
• https://pyformat.info - Formatowanie stringów w Python
Logowanie zdarzeń
Poziomy logowania
• Critical
• Error
• Warning
3.9. Print formatting
23
Python Workshop, Release 3f9e170, 2017-02-21
• Info
• Debug
Korzystanie z logging
logging.critical('Bład
˛ krytyczny, kończ˛
e.')
logging.error('Bład,
˛
ale kontynuuj˛
e.')
logging.warning('Uwaga b˛
ed˛
e coś robił')
logging.info('B˛
ed˛
e coś robił')
logging.debug('Robi˛
e to tak')
Konfiguracja logowania
import logging
logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(format='[%(asctime).19s] [%(levelname)s] %(message)s')
24
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
Konfiguracja formatowania logów
Format
args
Description
The tuple of arguments merged into msg to produce message, or a dict whose values are
used for the merge (when there is only one argument, and it is a dictionary). You shouldn’t
need to format this yourself.
%(asctime)s Human-readable time when the LogRecord was created. By default this is of the form
‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).
%(created)f Time when the LogRecord was created (as returned by time.time).
exc_info
Exception tuple (à la sys.exc_info) or, if no exception has occurred, None. You shouldn’t
need to format this yourself.
%(filename)s Filename portion of pathname.
%(funcName)s Name of function containing the logging call.
%(levelname)sText logging level for the message (’DEBUG’, ’INFO’, ’WARNING’, ’ERROR’,
’CRITICAL’).
%(levelno)s Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
%(lineno)d
Source line number where the logging call was issued (if available).
%(module)s
Module (name portion of filename).
%(msecs)d
Millisecond portion of the time when the LogRecord was created.
%(message)s The logged message, computed as msg % args. This is set when Formatter.format is
invoked.
msg
The format string passed in the original logging call. Merged with args to produce
message, or an arbitrary object (see arbitrary-object-messages). You shouldn’t need to
format this yourself.
%(name)s
Name of the logger used to log the call.
%(pathname)s Full pathname of the source file where the logging call was issued (if available).
%(process)d Process ID (if available).
%(processName)s
Process name (if available).
%(relativeCreated)d
Time in milliseconds when the LogRecord was created, relative to the time the logging module
was loaded.
stack_info
Stack frame information (where available) from the bottom of the stack in the current thread,
up to and including the stack frame of the logging call which resulted in the creation of this
record. You shouldn’t need to format this yourself.
%(thread)d
Thread ID (if available).
%(threadName)s
Thread name (if available).
Programowanie obiektowe
Paradygmat Obiektowy
Dziedziczenie
Wielodziedziczenie
Kompozycja
Dziedziczenie czy kompozycja?
class OtwieralneSzyby:
def otworz_szyby(self):
raise NotImplementedError
3.11. Programowanie obiektowe
25
Python Workshop, Release 3f9e170, 2017-02-21
class OtwieralnyDach:
def otorz_dach(self):
raise NotImplementedError
class UmieTrabic:
def zatrab(self):
print('\bbiip')
class Pojazd:
kola = None
class Samochod(Pojazd, UmieTrabic, OtwieralneSzyby):
kola = 4
def wlacz_swiatla(self, *args, **kwargs):
print('właczam
˛
światła')
class Cabrio(Samochod, OtwieralnyDach):
def wlacz_swiatla(self, *args, **kwargs):
print('Podnieś obudow˛
e lamp')
print('Puść muzyzk˛
e')
super(Cabrio, self).wlacz_swiatla(*args, **kwargs)
print('Zatrab')
˛
class Motor(Pojazd, UmieTrabic):
kola = 2
c = Cabrio()
c.wlacz_swiatla()
Polimorfizm
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
26
class Pojazd:
def zatrab(self):
raise NotImplementedError
class Motor(Pojazd):
def zatrab(self):
print('bip')
class Samochod(Pojazd):
def zatrab(self):
print('biiiip')
obj = Motor()
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
>>> obj.zatrab()
>>>
>>> obj = Samochod()
>>> obj.zatrab()
Klasy abstrakcyjne
Składnia
Klasy
Metody
self
Pola klasy
Konstruktor
super()
@property i @x.setter
class Cls:
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
@staticmethod
__str__() i __repr__()
Metaclass
Przeciażanie
˛
operatorów
__eq__()
__ne__()
3.11. Programowanie obiektowe
27
Python Workshop, Release 3f9e170, 2017-02-21
__lt__()
__le__()
__gt__()
__ge__()
Dobre praktyki
Ask don’t tell
Inicjalizacja parametrów
Private, public? konwencja _ i __
Co powinno być w klasie a co nie?
Klasa per plik?
Serializacja
pickle
>>> import pickle
>>> p = pickle.dumps(PYTHON)
>>> print('Z Python do Pickle:', p)
>>> pp = pickle.loads(p)
>>> print('Z Pickle do Python:', pp)
>>> osoba = pp[0]
>>> print('Obiekt po konwersji:', osoba.nazwisko)
json
>>> import json
>>> json.loads()
Problem z rzutowaniem daty na JSON:
>>> json.JSONEncoder.default = lambda self,obj: ('{:%Y-%m-%dT%H:%M:%S.%fZ}'.format(obj) if isinstance
>>> json.dumps()
csv
28
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
>>> import csv
>>> with open('filename.csv') as csvfile:
...
data = csv.DictReader(csvfile, delimiter=',', quotechar='"')
...
...
for row in data:
...
print(row['first_name'], row['last_name'])
>>> import csv
>>> data = [
...
{'first_name': 'Baked', 'last_name': 'Beans'},
...
{'first_name': 'Lovely', 'last_name': 'Spam'},
...
{'first_name': 'Wonderful', 'last_name': 'Spam'}
...]
>>> with open('filename.csv', 'w') as csvfile:
...
fieldnames = data[0].keys()
...
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter=',', quotechar='"', quoting=
...
writer.writeheader()
...
...
for row in data:
...
writer.writerow(row)
...
xml
<execute>
<command timeout="2">/bin/ls -la /etc/</command>
<command>/bin/ls -l /home/ /tmp/</command>
<command timeout="1">/bin/sleep 2</command>
<command timeout="2">/bin/echo 'juz wstalem'</command>
</execute>
import logging
import xml.etree.ElementTree
import subprocess
FILENAME = 'xml-execute-commands.xml'
LOG_FORMAT = '[%(levelname)-5s] %(filename)s:%(lineno)s - %(msg).110s'
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
log = logging.getLogger('code-execution')
root = xml.etree.ElementTree.parse(FILENAME).getroot()
def run(command, timeout=1):
log.info('Executing command: %s' % command)
with subprocess.Popen(command, stdout=subprocess.PIPE) as proc:
try:
output, errors = proc.communicate(timeout=timeout)
except subprocess.TimeoutExpired:
log.error('Timeout %s exceeded for command: %s' % (timeout, command))
return proc.kill()
3.12. Serializacja
29
Python Workshop, Release 3f9e170, 2017-02-21
if errors:
log.error(errors)
if output:
# red = '\033[00;31m'
# green = '\033[00;32m'
# blue = '\033[00;36m'
# white = '\033[00;39m'
message = output.decode()
log.debug('Output: {message}'.format(**locals()))
return message
for command in root.findall('./command'):
cmd = command.text.split()
timeout = float(command.get('timeout', 1))
run(cmd, timeout)
xslt
import io
from lxml import etree
XSLT = '''
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<foo><xsl:value-of select="/a/b/text()" /></foo>
</xsl:template>
</xsl:stylesheet>
'''
xslt_root = etree.XML(XSLT)
transform = etree.XSLT(xslt_root)
f = io.StringIO('<a><b>Text</b></a>')
doc = etree.parse(f)
result_tree = transform(doc)
print(result_tree)
30
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
Wyjatki
˛
Po co sa˛ wyjatki?
˛
Najpopularniejsze wyjatki
˛
Nazwa
wyjatku
˛
AttributeError
ImportError
IndexError
KeyError
KeyboardInterrupt
NameError
NotImplementedError
RuntimeError
SyntaxError
IndentationError
TypeError
Opis
Raised when an attribute reference (see Attribute references) or assignment fails. (When an object
does not support attribute references or attribute assignments at all, TypeError is raised.)
Raised when an import statement fails to find the module definition or when a from ... import fails
to find a name that is to be imported.
Raised when a sequence subscript is out of range. (Slice indices are silently truncated to fall in the
allowed range; if an index is not an integer, TypeError is raised.)
Raised when a mapping (dictionary) key is not found in the set of existing keys.
Raised when the user hits the interrupt key (normally Control-C or Delete). During execution, a
check for interrupts is made regularly. The exception inherits from BaseException so as to not be
accidentally caught by code that catches Exception and thus prevent the interpreter from exiting.
Raised when a local or global name is not found. This applies only to unqualified names. The
associated value is an error message that includes the name that could not be found.
This exception is derived from RuntimeError. In user defined base classes, abstract methods
should raise this exception when they require derived classes to override the method.
Raised when an error is detected that doesn’t fall in any of the other categories. The associated
value is a string indicating what precisely went wrong.
Raised when the parser encounters a syntax error. This may occur in an import statement, in a call
to the built-in functions exec() or eval(), or when reading the initial script or standard input (also
interactively).
Base class for syntax errors related to incorrect indentation. This is a subclass of SyntaxError.
Raised when an operation or function is applied to an object of inappropriate type. The associated
value is a string giving details about the type mismatch.
Przechwytywanie wyjatków
˛
• try
• except
• else
• finally
Hierarchia wyjatków
˛
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
3.13. Wyjatki
˛
31
Python Workshop, Release 3f9e170, 2017-02-21
|
|
|
+-+-+-+-+-+-|
|
+-+-|
+-|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+-+-|
|
+-|
|
+-+-+-|
|
|
|
+--
32
+-- FloatingPointError
+-- OverflowError
+-- ZeroDivisionError
AssertionError
AttributeError
BufferError
EOFError
ImportError
LookupError
+-- IndexError
+-- KeyError
MemoryError
NameError
+-- UnboundLocalError
OSError
+-- BlockingIOError
+-- ChildProcessError
+-- ConnectionError
|
+-- BrokenPipeError
|
+-- ConnectionAbortedError
|
+-- ConnectionRefusedError
|
+-- ConnectionResetError
+-- FileExistsError
+-- FileNotFoundError
+-- InterruptedError
+-- IsADirectoryError
+-- NotADirectoryError
+-- PermissionError
+-- ProcessLookupError
+-- TimeoutError
ReferenceError
RuntimeError
+-- NotImplementedError
+-- RecursionError
SyntaxError
+-- IndentationError
+-- TabError
SystemError
TypeError
ValueError
+-- UnicodeError
+-- UnicodeDecodeError
+-- UnicodeEncodeError
+-- UnicodeTranslateError
Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
Dobre praktyki
PEP20 - Zen of Python
import this
The Zen of Python
• Beautiful is better than ugly.
• Explicit is better than implicit.
• Simple is better than complex.
• Complex is better than complicated.
• Flat is better than nested.
• Sparse is better than dense.
• Readability counts.
• Special cases aren’t special enough to break the rules.
• Although practicality beats purity.
• Errors should never pass silently.
• Unless explicitly silenced.
• In the face of ambiguity, refuse the temptation to guess.
• There should be one– and preferably only one –obvious way to do it.
• Although that way may not be obvious at first unless you’re Dutch.
• Now is better than never.
• Although never is often better than right now.
• If the implementation is hard to explain, it’s a bad idea.
• If the implementation is easy to explain, it may be a good idea.
• Namespaces are one honking great idea – let’s do more of those!
Zen Pythona
• Pi˛ekne jest lepsze niż brzydkie.
• Wyrażone wprost jest lepsze niż domniemane.
• Proste jest lepsze niż złożone.
• Złożone jest lepsze niż skomplikowane.
• Płaskie jest lepsze niż wielopoziomowe.
• Rzadkie jest lepsze niż g˛este.
• Czytelność si˛e liczy.
• Sytuacje wyjatkowe
˛
nie sa˛ na tyle wyjatkowe,
˛
aby łamać reguły.
3.14. Dobre praktyki
33
Python Workshop, Release 3f9e170, 2017-02-21
• Choć praktyczność przeważa nad konsekwencja.˛
• Bł˛edy zawsze powinny być sygnalizowane.
• Chyba że zostana˛ celowo ukryte.
• W razie niejasności powstrzymaj pokus˛e zgadywania.
• Powinien być jeden – i najlepiej tylko jeden – oczywisty sposób na zrobienie danej rzeczy.
• Choć ten sposób może nie być oczywisty jeśli nie jest si˛e Holendrem.
• Teraz jest lepsze niż nigdy.
• Chociaż nigdy jest cz˛esto lepsze niż natychmiast.
• Jeśli rozwiazanie
˛
jest trudno wyjaśnić, to jest ono złym pomysłem.
• Jeśli rozwiazanie
˛
jest łatwo wyjaśnić, to może ono być dobrym pomysłem.
• Przestrzenie nazw to jeden z niesamowicie genialnych pomysłów – miejmy ich wi˛ecej!
PEP8
Wciecia
˛
Tak:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# More indentation included to distinguish this from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Hanging indents should add a level.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
Nie:
# Arguments on first line forbidden when not using vertical alignment.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Further indentation required as indentation is not distinguishable.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
Zamykanie nawiasów
34
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
Lub:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
Tabulacje i czy spacje?
Gł˛ebokość wci˛eć równa czterem spacjom.
Długość linii
To jest dość kontrowersyjna klauzula mówiaca
˛ o tym, że długość linii powinna być nie dłuższa niż 79 znaków. Przy
obecnych wielkich szerokokatnych
˛
monitorach jest to dość ucia˛żliwe. Jednakże należy przestrzegać konwencji.
Linie możemy łamać poprzez stawianie znaku ukośnika \ na końcu:
with open('/path/to/some/file/you/want/to/read') as file_1, \
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
class Rectangle(Blob):
def __init__(self, width, height,
color='black', emphasis=None, highlight=0):
if (width == 0 and height == 0 and
color == 'red' and emphasis == 'strong' or
highlight > 100):
raise ValueError("sorry, you lose")
if width == 0 and height == 0 and (color == 'red' or
emphasis is None):
raise ValueError("I don't think so -- values are %s, %s" %
(width, height))
Blob.__init__(self, width, height,
color, emphasis, highlight)
3.14. Dobre praktyki
35
Python Workshop, Release 3f9e170, 2017-02-21
Puste linie
Kodowanie plików
Przy Pythonie 3 kodownaie plików powinno być w UTF-8.
Importy
Importy powinny być poukładane alfabetycznie w grupach. Na górze importy z bibliotek standardowych Pythona.
Nast˛epnie linia przerwy i zewn˛etrzne zależności. Znów linia przerwy i zależności wewnatrz
˛ Twoich aplikacji.
Każdy z importów powinien być w osobnej linii.
Tak:
import os
import sys
Nie:
import sys, os
Ale można:
from subprocess import Popen, PIPE
Cudzysłowia
Python interpretuje cudzysłowia pojedyncze i podwójne tak samo. Ważne jest aby wybrać jeden sposób i konsekwentnie si˛e go trzymać w całej aplikacji.
Białe spacje w wyrażeniach
Tak:
spam(ham[1], {eggs: 2})
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
spam(1)
dct['key'] = lst[index]
x = 1
y = 2
long_variable = 3
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
36
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
def complex(real, imag=0.0):
return magic(r=real, i=imag)
def
def
def
def
munge(input: AnyStr):
munge(sep: AnyStr = None):
munge() -> AnyStr:
munge(input: AnyStr, sep: AnyStr = None, limit=1000):
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
Nie:
spam( ham[ 1 ], { eggs: 2 } )
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]
spam (1)
dct ['key'] = lst [index]
x
= 1
y
= 2
long_variable = 3
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
def munge(input: AnyStr=None):
def munge(input:AnyStr):
def munge(input: AnyStr)->PosInt:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()
try: something()
finally: cleanup()
do_one(); do_two(); do_three(long, argument,
list, like, this)
if foo == 'blah': one(); two(); three()
3.14. Dobre praktyki
37
Python Workshop, Release 3f9e170, 2017-02-21
Komentarze
Google style comments
Konwencje nazewnicze
• zmienne
• STALE
• NazwyKlas
• nazwy_metod() i nazwy_funkcji()
• nazwymodulow nazwy_modulow
• self
• cls
Używanie __ i _ w nazwach
Konstrukcje warunkowe
Yes:
if foo is not None:
No:
if not foo is None:
Zwracanie z funkcji
Tak:
def foo(x):
if x >= 0:
return math.sqrt(x)
else:
return None
def bar(x):
if x < 0:
return None
return math.sqrt(x)
Nie:
def foo(x):
if x >= 0:
return math.sqrt(x)
def bar(x):
if x < 0:
return
return math.sqrt(x)
38
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
Sprawdzanie warunków
Tak:
if not seq:
if seq:
if greeting:
Nie:
if len(seq)
if not len(seq)
if greeting == True:
if greeting is True:
Korzystanie z help(), dir() i object.__dict__
Kilka przykaładów z praktyki
html.append(’<tag>’)
Magic number i Magic string
Passowords
Wczytywanie konfiguracji programów
Wersjonowanie API
Zadania
Powielanie napisów
Nazwa skryptu bin/zadanie1-powielanie-napisow.py
Uruchamianie python bin/zadanie1-powielanie-napisow.py
Zadanie 1 Napisz program, który wczyta od użytkownika pewien napis, a nast˛epnie wyświetli 30 kopii
tego napisu, każda w osobnej linii.
Zadanie 2 Napisz trzy wersje tego programu:
• wykorzystujac
˛ range()
• wykorzystujac
˛ p˛etl˛e while
• wykorzystujac
˛ właściwości mnożenia stringów
Zadanie 3 Napisz doctest do takiej funkcji.
Podpowiedź
• print(’ciag znakow’ * 30)
3.15. Zadania
39
Python Workshop, Release 3f9e170, 2017-02-21
Parzystość
Nazwa skryptu bin/zadanie2-parzystosc.py
Uruchamianie python bin/zadanie2-parzystosc.py
Zadanie
• napisz program, który wczyta od użytkownika ciag
˛ znaków
• zweryfikuje czy wprowadzony ciag
˛ jest liczba˛ (int lub float)
• sprawdzi czy jest to liczba parzysta, czy nieparzysta
Podpowiedź
• Liczba parzysta, to taka, która po podzieleniu przez dwa nie ma reszty
• Użyj dzielenia modulo % lub divmod()
• Zwróć uwag˛e, że operator % działa modulo tylko na int oraz na float. Przy str ma zupełnie
inne znaczenie.
Liczby całkowite
Nazwa skryptu bin/zadanie3-calkowite.py
Uruchamianie python bin/zadanie3-calkowite.py
Zadanie Napisz program, który wczyta od użytkownika liczb˛e i wyświetli informacj˛e, czy jest to liczba
całkowita, czy niecałkowita.
Podpowiedź Liczba całkowita to taka, której cz˛eść dziesi˛etna nie wyst˛epuje (int) lub jest równa zero
float.
Dzienniczek ucznia
Nazwa skryptu bin/oceny.py
Uruchamianie python bin/oceny.py
Zadanie Napisz program, który wczytuje od użytkownika kolejne oceny i:
• sprawdza czy wprowadzona ocena jest na liście dopuszczalnych na wydziale ocen
• jeżeli ocena jest na liście dopuszczalnych na wydziale ocen, dodaje ja˛ do dzienniczka
• jeżeli wpisano cyfr˛e nie znjadujac
˛ a˛ si˛e na liście dopuszczalnych ocen, wyświetl informacj˛e i
zakończ wpisywanie
• wyświetla wyliczona˛ dla dzienniczka ocen średnia˛ arytmetyczna˛
• jeżeli wciśni˛eto sam Enter, oznacza to koniec wpisywania do dzienniczka
• wykorzystaj moduł statistics do wyliczania średniej
Warunek
• Zastosuj akademicka˛ skal˛e ocen [2, 3, 3.5, 4, 4.5, 5]
Podpowiedź
• dla ułatwienia wszystkie oceny moga˛ być typu float
• len() sum()
40
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
• in
• import statistics statistics.mean()
Przeliczenia trygonometryczne
Nazwa skryptu bin/trygonometria.py
Uruchamianie python bin/trygonometria.py
Zadanie Napisz program, który wczyta od użytkownika wielkość kata
˛ w stopniach i wyświetli wartość
czterech podstawowych funkcji trygonometrycznych (sin, cos, tg, ctg) o ile dla danego kata
˛ jest to
możliwe.
Wyrazy
Nazwa skryptu bin/podzial-wyrazow.py
Uruchamianie python bin/podzial-wyrazow.py
Zadanie Napisz program, który wczyta od użytkownika pewien tekst, a nast˛epnie podzieli go na zdania
(zakładamy, że jednoznacznie kropka rozdziela zdania) i dla każdego zdania wyświetli ile jest w
nim wyrazów (zakładamy, że spacja oddziela wyrazy w zdaniu).
Podpowiedź
• str.split()
• len()
Lotto
Nazwa skryptu bin/lotto.py
Uruchamianie python bin/lotto.py
Zadanie Napisz program, który wyświetli 6 losowych i nie powtarzajacych
˛
si˛e liczb z zakresu od 1 do
49.
Podpowiedź
• random.randrange()
• random.sample()
Pytania
• Czym sa liczby pseudolosowe?
• Czy da si˛e stworzyć program czysto losowy?
• Dlaczego?
Przeliczanie temperatury
Nazwa skryptu bin/temperatura.py
Uruchamianie python bin/temperatura.py
3.15. Zadania
41
Python Workshop, Release 3f9e170, 2017-02-21
Zadanie Woda zamarza przy 32 stopniach Fahrenheita, a wrze przy 212 stopniach Fahrenheita. Napisz
program, który wyświetli tabel˛e przeliczeń stopni Celsjusza na stopnie Fahrenheita w zakresie od
–20 do +40 stopni Celsjusza (co 5 stopni). Pami˛etaj o wyświetlaniu znaku plus/minus przy temperaturze. Oczywiście napisz testy do rozwiazania.
˛
Podpowiedź
• Fahrenheit to Celsius: (°F - 32) / 1.8 = °C
• Celsius to Fahrenheit: (°C * 1.8) + 32 = °F
Pole trójkata
˛
Nazwa skryptu bin/pole-trojkata.py
Uruchamianie python bin/pole-trojkata.py
Zadanie Napisz program, który obliczy pole trójkata,
˛ pod warunkiem że użytkownik poda wysokość i
długość podstawy tego trójkata.
˛ Uwzgl˛ednij, że wysokość i długość podstawy moga˛ być liczbami
niecałkowitymi. Wykorzystaj doctest do przetestowania funckji.
Wyliczanie średniej dla parametrów
Nazwa skryptu bin/srednia.py
Uruchamianie python bin/srednia.py
Zadanie 1 Zdefiniuj funkcj˛e avg(), która dla dowolnej liczby parametrów zwróci ich średnia˛ arytmetyczna˛ (lub 0 dla 0 parametrów).
Zadanie 2 Dowolna liczba parametrów podanych z linii poleceń.
Podpowiedź
• getopt
• argparse
• docopt
Uruchamianie python bin/srednia.py 5 10 100 32 -90 27.5
Konwersja liczby na zapis słowny
Nazwa skryptu bin/konwersja-liczby.py
Uruchamianie python bin/konwersja-liczby.py
Zadanie 1 Napisz program “numer.py‘‘”, który zamieni wprowadzony przez użytkownika ciag
˛ cyfr na
form˛e tekstowa:
˛
• znaki nie b˛edace
˛ cyframi maja˛ być ignorowane
• konwertujemy cyfry, nie liczby, a zatem: * 911 to “dziewi˛eć jeden jeden” * 1100 to “jeden
jeden zero zero”
Zadanie 2 Napisz program, który przekonwertuje liczb˛e na zapis słowny, np.:
42
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
>>> int_to_str(999)
'dziewiećset dziewi˛
ećdziesiat
˛ dziewi˛
eć'
>>> int_to_str(127.32)
'sto dwadzieścia siedem i trzydzieści dwa setne'
Zakres
• 6 cyfr przed przecinkiem
• 5 cyfr po przecinku
Zadanie 3 Napisz testy sprawdzajace
˛ przypadki brzegowe.
Rzymskie
Nazwa skryptu bin/rzymskie.py
Uruchamianie python bin/rzymskie.py
Zadanie 1 Napisz program, który przeliczy wprowadzona˛ liczb˛e rzymska˛ na jej postać dziesi˛etna.˛
Zadanie 2 Zrób druga˛ funkcj˛e, która dokona procesu odwrotnego.
map(), filter() i lambda
Nazwa skryptu bin/funkcyjne.py
Uruchamianie python bin/funkcyjne.py
Zadanie 1 Używajac
˛ generatora zbuduj list˛e zawierajac
˛ a˛ wszystkie liczby podzielne przez 3 z zakresu
od 1 do 33.
Zadanie 2
• Używajac
˛ funkcji filter() usuń z niej wszystkie liczby parzyste
• Używajac
˛ wyrażenia lambda i funkcji map() podnieś wszystkie elementy tak otrzymanej
listy do sześcianu
• Odpowiednio używajac
˛ funkcji sum() i len() oblicz średnia˛ arytmetyczna˛ z elementów tak
otrzymanej listy.
Zawartość pliku
Nazwa skryptu bin/zawartosc-pliku.py
Uruchamianie python bin/zawartosc-pliku.py
Zadanie 1 Napisz program, który wyświetli na ekranie zawartość pliku o nazwie podanej przez
użytkownika.
Zadanie 2 Dopisz obsług˛e wyjatków
˛
dla braku uprawnień oraz tego że plik nie istnieje.
Ksiażka
˛
adresowa
Nazwa skryptu bin/ksiazka-adresowa.py
Uruchamianie python bin/ksiazka-adresowa.py
3.15. Zadania
43
Python Workshop, Release 3f9e170, 2017-02-21
Zadanie Napisz ksia˛żk˛e adresowa,˛ która b˛edzie zapisywała dane do pliku w formacie json. Każdy z
użytkowników jest reprezentowany przez:
• imi˛e
• nazwisko
• telefon
• adres
• ulica
• miasto
• kod_pocztowy
• wojewodztwo
• panstwo
Wszystkie dane w ksia˛żce musza˛ być reprezentowane przez typy proste.
Zadanie 2 Bardzo cz˛esto wykorzystywanym typem pliku jest CSV, czyli wartości oddzielone
przecinkami. Zamień format pliku na ten typ. Zrób tak, aby dane trafiły do odpowiednich kolumn nawet po przesortowaniu. Użyj csv.DictWriter(). Wszystkie pola musza˛ być zawsze w
cudzysłowiach i oddzielone średnikami.
Zadanie 3 Zmodyfikuj aby można było wpisywać wiele adresów.
Zadanie 4 Zmodyfikuj program aby wykorzystywał klasy do reprezentowania wpisów w ksia˛żce. Które
podejście jest lepsze?
Zadanie 5 Teraz wykorzystaj plik bazy danych sqlite aby trzymać informacje w tabeli. Które podejście
jest lepsze?
Zadanie 6 Wykorzystaj Django do stworzenia takiego modelu i wygeneruj panel administracyjny.
Trudne?
Pytanie
• Które podejście było najłatwiejsze?
• W jakim formacie najlepiej przechowywać dane?
• Które podejście jest najlepsze dla innych programistów, a które dla użytkowników?
Zbalansowanie nawiasów
Nazwa skryptu bin/zbalansowanie-nawiasow.py
Uruchamianie python bin/zbalansowanie-nawiasow.py
Zadanie 1 Napisz kod który sprawdzi zbalansowanie nawiasów, tzn. czy ilość otwieranych nawiasów
jest równa ilości nawiasów zamykanych. Zwórć uwag˛e, że moga˛ być cztery typy nawiasów:
• okragłe:
˛
(i)
• kwadratowe: [ i ]
• klamrowe { i }
• trójkatne
˛ <i>
Zadanie 2 Rozbuduj poniższy zestaw testów i napisz funkcjonalność.
44
Chapter 3. Podstawy
Python Workshop, Release 3f9e170, 2017-02-21
>>> dane = "() [] () ([]()[])"
>>> zbalansowanie_nawiasow(a)
True
>>> dane = "( (] ([)]"
>>> zbalansowanie_nawiasow(a)
False
Zadanie 3 Spróbuj użyć rekurencji.
3.15. Zadania
45
Python Workshop, Release 3f9e170, 2017-02-21
46
Chapter 3. Podstawy
CHAPTER 4
Średniozaawansowany
Biblioteka standardowa
datetime
import datetime
datetime.datetime.now()
datetime.date.today()
datetime.datetime.now() - datetime.timedelta(hours=3)
datetime.datetime.now().replace(tzinfo=datetime.timezone.utc)
time
os
import os
os.path
os.walk
os.path.join
os.path.abspath
os.path.dirname
sys
import sys
sys.path
sys.path.append
sys.platform
warnings
47
Python Workshop, Release 3f9e170, 2017-02-21
import warnings
warnings.warn('Wersja API jest już nieaktualna', PendingDeprecationWarning)
pprint
from pprint import pprint
data = [
{'first_name': 'Baked', 'last_name': 'Beans'},
{'first_name': 'Lovely', 'last_name': 'Spam'},
{'first_name': 'Wonderful', 'last_name': 'Spam'}
]
pprint(data)
csv
import csv
csv.DictReader()
csv.DictWriter()
memoize
json
import json
json.loads()
json.dumps()
sqlite
re
import re
re.search()
re.findall()
re.match()
re.compile()
48
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
httplib
urllib
socket
tempfile
io
import io
io.StringIO
functools
itertools
math
import math
math.sin()
math.cos()
math.tan()
math.pi
statistics
import statistics
statistics.avg()
statistics.mean()
statistics.stdev()
random
import random
random.sample()
random.random()
subprocess
import subprocess
subprocess.Popen()
4.1. Biblioteka standardowa
49
Python Workshop, Release 3f9e170, 2017-02-21
doctest
import doctest
doctest.testmod()
Collections
Name
namedtuple()
deque
ChainMap
Counter
OrderedDict
defaultdict
UserDict
UserList
UserString
Description
factory function for creating tuple subclasses with named fields
list-like container with fast appends and pops on either end
dict-like class for creating a single view of multiple mappings
dict subclass for counting hashable objects
dict subclass that remembers the order entries were added
dict subclass that calls a factory function to supply missing values
wrapper around dictionary objects for easier dict subclassing
wrapper around list objects for easier list subclassing
wrapper around string objects for easier string subclassing
Biblioteki zewnetrzne
˛
Do zastosowań naukowych
num.py
sci.py
pandas
pybrain
Wspierajacych
˛
programowanie sieciowe
Standard WSGI
requests
>>> import requests
>>>
>>>
>>>
>>>
requests.put('http://httpbin.org/put', data = {'key':'value'})
requests.delete('http://httpbin.org/delete')
requests.head('http://httpbin.org/get')
requests.options('http://httpbin.org/get')
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.get('http://httpbin.org/get', params=payload)
>>> print(r.url)
http://httpbin.org/get?key2=value2&key1=value1
>>> payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
50
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
>>> r = requests.get('http://httpbin.org/get', params=payload)
>>> print(r.url)
http://httpbin.org/get?key1=value1&key2=value2&key2=value3
>>> import requests
>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
>>> r.status_code
200
>>> r.headers['content-type']
'application/json; charset=utf8'
>>> r.encoding
'utf-8'
>>> r.text
u'{"type":"User"...'
>>> r.json()
{u'private_gists': 419, u'total_private_repos': 77, ...}
>>> url = 'https://api.github.com/some/endpoint'
>>> headers = {'user-agent': 'my-app/0.0.1'}
>>> r = requests.get(url, headers=headers)
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> print(r.text)
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
>>> r = requests.head('http://github.com', allow_redirects=True)
>>> r.url
'https://github.com/'
>>> r.history
[<Response [301]>]
>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, json=payload)
• http://docs.python-requests.org/en/master/user/quickstart/#json-response-content
• http://docs.python-requests.org/en/master/dev/contributing/#kenneth-reitz-s-code-style
4.2. Biblioteki zewnetrzne
˛
51
Python Workshop, Release 3f9e170, 2017-02-21
suds
Google App Engine
django
flask
webapp2
tornado
atlassian-python-api
fabric
BeautifulSoup
Bazy danych
pyMySQL
psycopg2
pymongo
SQLAlchemy
Inne
py2app
docopt
Jinja2
pytz
ldap3
import datetime
import time
from pprint import pprint
from ldap3 import Server, Connection, SEARCH_SCOPE_WHOLE_SUBTREE
USER = "myusername"
PASS = "mypassword"
BASEDN = "OU=Users,DC=local"
SERVER = Server("127.0.0.1", port=389)
ATTRIBUTES = ['mail', 'pwdLastSet']
52
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
def construct_filter(wintimestamp):
return """(&
(objectCategory=Person)
(objectCategory=User)
(userAccountControl=512)
(pwdLastSet<={wintimestamp})
(mail=*)
)""".format(wintimestamp=wintimestamp)
def search(filter):
with Connection(SERVER, user=USER, password=PASS) as c:
c.search(BASEDN, filter, SEARCH_SCOPE_WHOLE_SUBTREE, attributes=ATTRIBUTES)
return [record['attributes'] for record in c.response]
def datetime_to_mstimestamp(date):
"""
Active Direcotry has different approach to create timestamp than Unix.
Here's a function to convert the Unix timestamp to the AD one.
>>> datetime_to_mstimestamp(datetime.datetime(2000, 1, 1, 0, 0))
125911548000000000
"""
timestamp = int(time.mktime(date.timetuple()))
magic_number = 116444736000000000
return timestamp * 10000000 + magic_number
def mstimestamp_to_datetime(mstimestamp):
"""
Active Direcotry has different approach to create timestamp than Unix.
Here's a function to convert AD timestamp to the Unix one.
>>> mstimestamp_to_datetime(130567328471235643)
datetime.datetime(2014, 10, 2, 16, 14, 7, 123563)
"""
magic_number = 11644473600
return datetime.datetime.fromtimestamp(mstimestamp / 10000000 - magic_number)
def month_ago(date):
"""
>>> month_ago(datetime.datetime(2000, 1, 31, 0, 0))
datetime.datetime(2000, 1, 1, 0, 0)
"""
return date - datetime.timedelta(days=30)
def print_users_with_expiring_password():
now = datetime.datetime.now()
expiration_date = month_ago(now)
wintimestamp = datetime_to_mstimestamp(expiration_date)
older_than_month_ago = construct_filter(wintimestamp)
for user in search(older_than_month_ago):
user['pwdLastSet'] = mstimestamp_to_datetime(int(user['pwdLastSet'][0]))
pprint(user)
4.2. Biblioteki zewnetrzne
˛
53
Python Workshop, Release 3f9e170, 2017-02-21
if __name__ == "__main__":
print_users_with_expiring_password()
Parametry linii poleceń
argparse
• https://docs.python.org/3/library/argparse.html#the-add-argument-method
ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices
Define how a single command-line argument should be parsed. Each parameter has its own more detailed description
below, but in short they are:
• name or flags - Either a name or a list of option strings, e.g. foo or -f, –foo.
• action - The basic type of action to be taken when this argument is encountered at the command line.
• nargs - The number of command-line arguments that should be consumed.
• const - A constant value required by some action and nargs selections.
• default - The value produced if the argument is absent from the command line.
• type - The type to which the command-line argument should be converted.
• choices - A container of the allowable values for the argument.
• required - Whether or not the command-line option may be omitted (optionals only).
• help - A brief description of what the argument does.
• metavar - A name for the argument in usage messages.
• dest - The name of the attribute to be added to the object returned by parse_args().
import argparse
parser = argparse.ArgumentParser(
prog='PROGRAM NAME',
description='A foo that bars',
epilog="And that's how you'd foo a bar")
parser.add_argument('--sum', dest='accumulate', action='store_const', const=sum,
default=max, help='sum the integers (default: find the max)')
parser.add_argument('--foo', nargs='?', help='foo help')
parser.add_argument('--bar', nargs='+', help='bar help')
parser.add_argument('--foobar', nargs='*', default=[1, 2, 3], help='BAR!')
parser.add_argument('--integers', metavar='int', type=int, choices=range(10),
nargs='+', help='an integer in the range 0..9')
parser.add_argument('--bar', nargs='?', type=int, default=42,
help='the bar to %(prog)s (default: %(default)s)')
parser.add_argument('--move', choices=['rock', 'paper', 'scissors'])
54
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
parser.add_argument('--length', default='10', type=int, required=True)
parser.add_argument('--width', default=10.5, type=int,
help='foo the bars before frobbling')
parser.add_argument('--input', default='input.csv', type=argparse.FileType('r'))
parser.add_argument('--output', default='output.c', type=argparse.FileType('w'))
script = parser.parse_args()
try:
script = parser.parse_args()
except SystemExit:
pass
Uruchamianie poleceń
import subprocess
import shlex
cmd = 'ls -la'
with subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE) as proc:
ret = proc.stdout.read()
print(ret)
Timeout dla wykonywania poleceń
• subprocess.run() - New in Python 3.5
import subprocess
cmd = ['ping', 'www.google.com']
try:
subprocess.run(cmd, timeout=5)
except subprocess.TimeoutExpired:
print('process ran too long')
Parsowanie i sanityzacja argumentów
>>> import shlex
>>> import subprocess
>>> command_line = input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print(args)
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!
4.3. Parametry linii poleceń
55
Python Workshop, Release 3f9e170, 2017-02-21
Modularyzacja, wersjonowanie i dystrybucja
Modularyzacja
Plik __init__.py
Linia if __name__ == ’__main__’
Importowanie wzgledne
˛
from .
import *
__all__
Konwencja nazewnicza - main.py
Tworzenie paczek
setup.py
import sys
from setuptools import find_packages
from setuptools import setup
assert sys.version_info >= (3, 4), 'Python 3.4+ required.'
setup(
name='atlassian-python-api',
description='Python Atlassian REST API Wrapper',
long_description='Python Atlassian REST API Wrapper',
license='Apache License 2.0',
version='0.14.0',
download_url='https://github.com/MattAgile/atlassian-python-api',
author='Matt Harasymczuk',
author_email='[email protected]',
url='http://mattagile.com/',
packages=find_packages(),
package_data={'': ['LICENSE', 'README.rst'], 'atlassian': ['*.py']},
package_dir={'atlassian': 'atlassian'},
include_package_data=True,
zip_safe=False,
install_requires=['requests==2.7.0'],
platforms='Platform Independent',
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: Apache Software License',
'Natural Language :: English',
'Operating System :: OS Independent',
'Operating System :: POSIX',
56
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.0',
'Programming Language :: Python :: 3.1',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Topic :: Internet',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: Libraries :: Application Frameworks']
)
setup.cfg
[pep8]
max-line-length = 939
ignore = E402,W391
python setup.py sdist upload
Instalacja i korzystanie z zewnetrznych
˛
bibliotek
pip search
pip install
pip install -r requirements.txt
requirements.txt a setup.py
wheel
distutils i setuptools
Przyszłość paczkowania i dystrybucji
• https://www.youtube.com/watch?v=jOiAp3wtx18
• https://www.youtube.com/watch?v=Oc9khbXBes8
4.4. Modularyzacja, wersjonowanie i dystrybucja
57
Python Workshop, Release 3f9e170, 2017-02-21
Wyrażenia regularne
Konstruowanie wyrażeń
Wyciaganie
˛
parametrów (zmiennych)
Najcze˛ ściej wykorzystywane funkcje
match()
search()
findall() i finditer()
compile()
Greedy search
Testy
Doctest
def km_na_metry(ile):
"""
>>> km_na_metry(1)
1000
>>> km_na_metry(0)
0
>>> km_na_metry(-1)
Traceback (most recent call last):
...
ValueError
>>> km_na_metry('adas')
Traceback (most recent call last):
...
TypeError
"""
return ile * 1000
if __name__ == "__main__":
import doctest
doctest.testmod()
MINIMALNA_TEMPERATURA = -273.15
def przelicz_celsius_na_kelvin(temperatura):
"""
>>> przelicz_celsius_na_kelvin(1)
274.15
>>> przelicz_celsius_na_kelvin(0)
58
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
273.15
>>> przelicz_celsius_na_kelvin(-300)
Traceback (most recent call last):
...
ValueError: Nie może być mniejsze niż minimalna temperatura
>>> przelicz_celsius_na_kelvin('jeden')
Traceback (most recent call last):
...
ValueError: Temperatura musi być float
>>> przelicz_celsius_na_kelvin([1.0, 1, 0])
Traceback (most recent call last):
...
TypeError: Nie obsługiwany typ argumentu
"""
try:
temperatura = float(temperatura)
except ValueError:
raise ValueError('Temperatura musi być float')
except TypeError:
raise TypeError('Nie obsługiwany typ argumentu')
if temperatura < MINIMALNA_TEMPERATURA:
raise ValueError('Nie może być mniejsze niż minimalna temperatura')
else:
return temperatura - MINIMALNA_TEMPERATURA
Unit Test
import unittest
class Prostokat:
def __init__(self, a, b):
self.a = float(a)
self.b = float(b)
if self.a <= 0 or self.b <= 0:
raise ValueError('Dlugosc bokow musi byc liczba naturalna')
def pole(self):
return self.a * self.b
def obwod(self):
return (self.a + self.b) * 2
def __str__(self):
return 'Prostokat(a=%s, b=%s)' % (self.a, self.b)
class ProstokatTest(unittest.TestCase):
def setUp(self):
self.prostokat = Prostokat(a=5, b=10)
4.6. Testy
59
Python Workshop, Release 3f9e170, 2017-02-21
def test_obliczania_pola(self):
self.assertEqual(self.prostokat.pole(), 50)
def test_obliczania_obwodu(self):
self.assertEqual(self.prostokat.obwod(), 30)
def test_ustawienia_bokow(self):
with self.assertRaises(TypeError):
Prostokat(a=0)
with self.assertRaises(TypeError):
Prostokat(b=0)
def test_dlugosci_bokow(self):
with self.assertRaises(ValueError):
Prostokat(a=-1, b=-2)
def test_prostokat_to_string(self):
self.assertEqual(str(self.prostokat), 'Prostokat(a=5.0, b=10.0)')
if __name__ == '__main__':
unittest.main()
selenium
Mock
Stub
Tworzenie dokumentacji
Format reStructuredText
Po co?
Paragrafy
Nagłówki
Odnośniki
Obrazki i media
Specjalne wstawki
TODO
Listy
60
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
Tabele
reStructuredText vs. Markdown
Sphinx
Generowanie dokumentacji
Buildery
make html
make singlehtml
4.7. Tworzenie dokumentacji
61
Python Workshop, Release 3f9e170, 2017-02-21
toctree
Django
Co to jest Django?
Architektura aplikacji Django
Modele
Widoki
Panel admina
Dokumentacja
Widoki generyczne
Localization
Sygnały
Migracje schematów bazy danych
Management Commands
ORM
Skrypty z Django
Projektowanie GUI
Biblioteka Tkinter
• http://www.tkdocs.com/tutorial/index.html
#!/usr/bin/env python3
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def say_hi(self):
print("hi there, everyone!")
def create_hi_button(self):
self.hi_there = Button(self)
self.hi_there["text"] = "Hello",
self.hi_there["command"] = self.say_hi
62
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
self.hi_there.pack({"side": "left"})
def create_quit_button(self):
self.QUIT = Button(self)
self.QUIT["text"] = "QUIT"
self.QUIT["command"] = self.quit
self.QUIT.pack({"side": "left"})
def create_yesno_button(self):
self.yesno = Button(self)
self.yesno['text'] = 'Ask me a question'
self.yesno['fg'] = 'white'
self.yesno['command'] = self.show_yesno_screen
self.yesno.pack({'side': 'right'})
def show_yesno_screen(self):
messagebox.askyesno(
message='Do you like it?',
icon='question',
title='Hi there!')
def create_widgets(self):
self.create_quit_button()
self.create_hi_button()
self.create_yesno_button()
def __init__(self, master=None):
self.frame = Frame.__init__(self, master)
self.pack()
self.create_widgets()
root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
#!/usr/bin/env python3
from tkinter import *
from tkinter import ttk
def print_hello():
print('Hello World!')
root = Tk()
content = ttk.Frame(root, padding=(3, 3, 12, 12))
frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100)
namelbl = ttk.Label(content, text="Name")
name = ttk.Entry(content)
onevar = BooleanVar()
twovar = BooleanVar()
threevar = BooleanVar()
4.9. Projektowanie GUI
63
Python Workshop, Release 3f9e170, 2017-02-21
onevar.set(True)
twovar.set(False)
threevar.set(True)
one = ttk.Checkbutton(content, text="One", variable=onevar, onvalue=True)
two = ttk.Checkbutton(content, text="Two", variable=twovar, onvalue=True)
three = ttk.Checkbutton(content, text="Three", variable=threevar, onvalue=True)
ok = ttk.Button(content, text="Okay")
cancel = ttk.Button(content, text="Cancel")
ok['command'] = print_hello
content.grid(column=0, row=0, sticky=(N, S, E, W))
frame.grid(column=0, row=0, columnspan=3, rowspan=2, sticky=(N, S, E, W))
namelbl.grid(column=3, row=0, columnspan=2, sticky=(N, W), padx=5)
name.grid(column=3, row=1, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
one.grid(column=0, row=3)
two.grid(column=1, row=3)
three.grid(column=2, row=3)
ok.grid(column=3, row=3)
cancel.grid(column=4, row=3)
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
content.columnconfigure(0, weight=3)
content.columnconfigure(1, weight=3)
content.columnconfigure(2, weight=3)
content.columnconfigure(3, weight=1)
content.columnconfigure(4, weight=1)
content.rowconfigure(1, weight=1)
root.mainloop()
#!/usr/bin/env python3
from tkinter import *
from tkinter import ttk
root = Tk()
l = Listbox(root, height=5)
l.grid(column=0, row=0, sticky=(N,W,E,S))
s = ttk.Scrollbar(root, orient=VERTICAL, command=l.yview)
s.grid(column=1, row=0, sticky=(N,S))
l['yscrollcommand'] = s.set
ttk.Sizegrip().grid(column=1, row=1, sticky=(S,E))
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
for i in range(1, 101):
l.insert('end', 'Line %d of 100' % i)
64
Chapter 4. Średniozaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
root.mainloop()
Introspekcja
Pola obiektu
class Address:
def __init__(self, host, port):
self.host = host
self.port = port
addr = Address(host='127.0.0.1', port=1337)
a = addr.__dict__
print('Listowanie za pomoca __dict__:\n{}\n\n'.format(a))
a = [x for x in dir(addr) if not x.startswith('__')]
print('Listowanie pól klasy:\n{}\n\n'.format(a))
a = vars(addr)
print('Listowanie za pomoca vars():\n{}\n\n'.format(a))
Metody obiektu
class Address:
def __init__(self, host, port):
self.host = host
self.port = port
addr = Address(host='127.0.0.1', port=1337)
a = dir(addr)
print('Listowanie za pomoca˛ dir():\n"{}\n\n"'.format(a))
4.10. Introspekcja
65
Python Workshop, Release 3f9e170, 2017-02-21
66
Chapter 4. Średniozaawansowany
CHAPTER 5
Zaawansowany
Generatory i list comprehension
List comprehension
• wykonywane natychmiast
[x*x for x in range(0, 30) if x % 2]
Generator expressions
• lazy evaluation
(x*x for x in range(0, 30) if x % 2)
Operator yield
osoby_w_klasie =
{'username':
{'username':
{'username':
{'username':
]
[
'wykladowca1', 'czy_wykladowca': True},
'uczen1', 'czy_wykladowca': False},
'uczen2', 'czy_wykladowca': False},
'uczen3', 'czy_wykladowca': False},
def uczestnicy_kursu(osoby):
def jest_wykladowca(user):
if user['czy_wykladowca']:
return True
else:
return False
for osoba in osoby:
if not osoba['czy_wykladowca']:
yield {
'wykladowcy': jest_wykladowca,
'uczestnicy': [x for x in osoby if not x['czy_wykladowca']],
'wszystkie_username': [x['username'] for x in osoby]
}
67
Python Workshop, Release 3f9e170, 2017-02-21
uczestnicy_kursu = [osoba.get('username') for osoba in osoby_w_klasie if not osoba['czy_wykladowca']]
pprint(uczestnicy_kursu)
Iteratory
Czym jest iterator?
• __next__()
• raise StopIteration
Iterowanie po obiektach
Iterowanie po stringu
for znak in 'python':
print(znak)
Iterowanie po list(), dict(), set(), tuple()
for liczba in [1, 2, 3, 4]:
print(liczba)
for key, value in [(0, 0), (1, 1), (1, 2)]:
print('%s -> %s' % (key, value))
slownik = {'x': 1, 'y': 2}
for key in slownik:
print(slownik.get(key))
for key, value in slownik.items():
print(key, value)
Własny iterator
class ListaFigurGeometrycznych:
lista = []
aktualny_elemtent = 0
def __iter__(self):
return self
def push(self, figura):
self.lista.append(figura)
def next(self):
self.aktualny_elemtent += 1
return self.lista[self.aktualny_elemtent]
68
Chapter 5. Zaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
prostokaty = ListaFigurGeometrycznych()
prostokaty.push('kwadrat', 'prostokat')
for figura in prostokaty:
print(figura)
System Operacyjny
eval
sys.platform
sys.exit()
subprocess
Kolejki, watki
˛ i procesy
Kolejki
Queue
PriorityQueue
__all__ = [’Empty’, ‘Full’, ‘Queue’, ‘PriorityQueue’, ‘LifoQueue’]
Watki
˛ a procesy
Watki
˛
Tworzenie watków
˛
from threading import Timer
def hello():
print("hello, world")
t = Timer(5.0, hello)
t.start()
print('hej')
Synchronizacja watków
˛
5.3. System Operacyjny
69
Python Workshop, Release 3f9e170, 2017-02-21
import queue
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print("Starting %s" % self.name)
process_data(self.name, self.q)
print("Exiting %s" % self.name)
def process_data(threadName, q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print("%s processing %s" % (threadName, data))
else:
queueLock.release()
time.sleep(1)
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threads = []
threadID = 1
# Create new threads
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# Fill the queue
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()
70
Chapter 5. Zaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
# Wait for queue to empty
while not workQueue.empty():
pass
# Notify threads it's time to exit
exitFlag = 1
# Wait for all threads to complete
for t in threads:
t.join()
print("Exiting Main Thread")
Zamykanie watków
˛
Workery
import queue
import logging
import threading
kolejka = queue.Queue()
class Worker(threading.Thread):
daemon = True
def run(self):
while True:
# Remove and return an item from the queue.
job = kolejka.get()
# Execute work
logging.warning('Will do the work: %s' % job)
# Indicate that a formerly enqueued task is complete.
kolejka.task_done()
def spawn_workers(number_of_workers):
for i in range(number_of_workers):
Worker().start()
if __name__ == '__main__':
spawn_workers(3)
# Zapełnij kolejk˛
e
for todo in ['ping', 'ls -la', 'echo "hello world"', 'cat /etc/passwd']:
kolejka.put(todo)
# wait to complete all tasks
kolejka.join()
5.4. Kolejki, watki
˛ i procesy
71
Python Workshop, Release 3f9e170, 2017-02-21
Procesy
Tworzenie procesów
Synchronizacja procesów
IPC - komunikacja miedzyprocesowa
˛
figury.py
class Prostokat:
def __init__(self, a, b):
self.a = float(a)
self.b = float(b)
def pole(self):
return self.a * self.b
def obwod(self):
return (self.a + self.b) * 2
def __str__(self):
return 'Prostokat(a=%s, b=%s)' % (self.a, self.b)
processes-client.py
from multiprocessing.connection import Client
import logging
import pickle
from .figury import Prostokat
rectangle = Prostokat(a=5, b=10)
rect = pickle.dumps(rectangle)
address = ('localhost', 6000)
conn = Client(address, authkey=b'secret password')
logging.warning('Sending objects')
conn.send([rect, 'a', 2.5, None, int, sum])
logging.warning('Sending close')
conn.send('close')
conn.close()
processes-listener.py
from multiprocessing.connection import Listener
import logging
import pickle
from .figury import Prostokat
address = ('localhost', 6000)
# family is deduced to be 'AF_INET'
logging.warning('Listening on %s:%s' % address)
72
Chapter 5. Zaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
listener = Listener(address, authkey=b'secret password')
conn = listener.accept()
logging.warning('connection accepted from %s %s' % listener.last_accepted)
while True:
msg = conn.recv()
logging.warning('Received: %s' % msg)
if msg == 'close':
conn.close()
break
else:
# do something with msg
prostokat = pickle.loads(msg[0])
logging.warning('Prostokat %s' % prostokat)
print('Pole: %s' % prostokat.pole())
listener.close()
Zamykanie procesów
Programowanie funkcyjne
lambda
def czy_parzysta(x):
if x % 2 == 0:
return True
else:
return False
parzyste = filter(czy_parzysta, liczby)
foo = lambda x: x*x
print(foo(10))
liczby = [1, 2, 3, 4]
parzyste = filter(lambda x: x % 2 == 0, liczby)
closure
def f(x):
def g(y):
return x + y
return g
5.5. Programowanie funkcyjne
73
Python Workshop, Release 3f9e170, 2017-02-21
decorator
• Modify arguments
• Modify returned value
• Do things before call
• Do things after call
• Avoid calling
• Modify global state
• Metadata
def my_decorator(f):
def wrapper(*args, **kwargs):
return f(*args, **kwargs)
return wrapper
# usage
@my_decorator
def func(x):
return x
import os
import logging
def if_file_exists(function):
def check(filename):
if os.path.exists(filename):
function(filename)
else:
logging.error('File "%(filename)s" does not exists, will not execute!', locals())
return check
@if_file_exists
def print_file(filename):
with open(filename) as file:
content = file.read()
print(content)
if __name__ == '__main__':
print_file('/etc/passwd')
print_file('/tmp/passwd')
74
Chapter 5. Zaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
złożenia funkcji
map()
lista = [1, 2, 3]
def inkrementuj(y):
return 1 + y
map(inkrementuj, lista)
map(lambda y: 1 + y, l)
zip()
>>> x = [1, 2, 3]
>>> y = [4, 5, 6]
>>> zipped = zip(x, y)
>>> list(zipped)
[(1, 4), (2, 5), (3, 6)]
>>> # unzip
>>> x2, y2 = zip(*zip(x, y))
>>> x == list(x2) and y == list(y2)
True
filter()
OSOBY = [
{'imie':
{'imie':
{'imie':
{'imie':
]
'Matt', 'wiek': 10},
'Angelika', 'wiek': 18},
'Mateusz', 'wiek': 21},
'Tadeusz', 'wiek': 35},
def osoba_pelnoletnia(osoba):
if osoba['wiek'] >= 18:
return True
else:
return False
dorosli = filter(osoba_pelnoletnia, OSOBY)
print(list(dorosli))
all()
any()
Programowanie sieciowe
Socket
5.6. Programowanie sieciowe
75
Python Workshop, Release 3f9e170, 2017-02-21
Otwieranie połacze
˛
ń
Nasłuchiwanie
Przekazywanie informacji
Prosty serwer HTTP
httplib
urllib
smtp
HTML Scrapping
• BeautifulSoup
Wzorce projektowe
• Wzorce kreacyjne
• Wzorce strukturalne
• Wzorce czynnosciowe
Wzorce kreacyjne
Izolacja reguł tworzenia obiektow od reguł okreslajacych sposob uzywania obiektow (oddzielenie w kodzie programu
kodu tworzacego obiekty od kodu, ktory uzywa obiekty) – klasy typu „Control”
1. Budowniczy - Builder - Sposob tworzenia złozonych obiektow
2. Fabrykaabstrakcyjna – AbstractFactory - Rodziny obiektow
3. Metodawytwórcza – FactoryMethod - Podklasa tworzonego obiektu
4. Prototyp - Prototype - Typ klasy tworzonego obiektu
5. Singleton - Jedna kopia obiektu
C Extensions
C Types
#include <stdio.h>
void ehlo() {
printf("Ehlo World");
}
void greeting(char *name) {
76
Chapter 5. Zaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
printf("Ehlo %s!\n", name);
}
void number(int num) {
printf("My number %d\n", num);
}
int myint(int num) {
return num;
}
gcc -fPIC -c -o hello-ctypes.o hello-ctypes.c -I/usr/local/Cellar/python3/3.5.2/Frameworks/Python.fra
gcc -shared hello-ctypes.o -o hello-ctypes.so
import ctypes
ehlo = ctypes.CDLL('hello-ctypes.so')
ehlo.ehlo()
ehlo.greeting.argtypes = [ctypes.c_char_p]
name = ctypes.create_string_buffer('Matt'.encode())
ehlo.greeting(name)
ehlo.number(10)
print(dir(ehlo))
i = ehlo.myint(15)
print(i)
C Modules
Python 3
#include <Python.h>
/* Implementation */
static PyObject* say_hello(PyObject* self, PyObject* args) {
const char* name;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
printf("Hello %s!\n", name);
Py_RETURN_NONE;
}
static PyObject* version(PyObject* self) {
return Py_BuildValue("s", "Version 1.0");
}
/* Python Binding Definitions */
5.8. C Extensions
77
Python Workshop, Release 3f9e170, 2017-02-21
static PyMethodDef HelloMethods[] = {
{"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
{"version"}, (PyCFunction)version, METH_NOARGS, "returns the version"},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef hello = {
PyModuleDef_HEAD_INIT,
"hello",
/* name of module */
"",
/* module documentation, may be NULL */
-1,
/* size of per-interpreter state of the module, or -1 if
HelloMethods
};
PyMODINIT_FUNC PyInit_hello(void) {
return PyModule_Create(&hello);
}
Python 2
#include <Python.h>
/* Implementation */
static PyObject* say_hello(PyObject* self, PyObject* args) {
const char* name;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
printf("Hello %s!\n", name);
Py_RETURN_NONE;
}
static PyObject* version(PyObject* self) {
return Py_BuildValue("s", "Version 1.0");
}
/* Python Binding Definitions */
static PyMethodDef HelloMethods[] = {
{"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
{"version"}, (PyCFunction)version, METH_NOARGS, "returns the version"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC inithello(void) {
(void) Py_InitModule("hello", HelloMethods);
}
78
Chapter 5. Zaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
setup.py
import sys
from distutils.core import setup, Extension
if sys.version_info >= (3,):
print('Building for Python 3')
module = Extension('hello', sources = ['hello-py3.c'])
elif sys.version_info >= (2,):
print('Building for Python 2')
module = Extension('hello', sources=['hello-py2.c'])
else:
print('Unsupported Python version')
sys.exit(1)
setup(
name = 'hello',
version='1.0',
description = 'Ehlo World!',
ext_modules = [module])
python setup.py build
cd build/lib*
python
import hello
hello.say_hello('Matt')
Zadania
REST API
Używajac
˛ biblioteki standardowej w Pythonie zaciagnij
˛
informacje o repozytoriach użytkownika Django na
https://github.com
• w przegladarce
˛
internetowej wygeneruj w swoim profilu token https://github.com/settings/tokens
• Nast˛epnie z przegladnij
˛
list˛e z poziomu Pythona i znajdź URL dla repozytorium django.
"name": "django",
"full_name": "django/django",
# wyszukaj "commits_url": ???
• Przegladnij
˛
to repozytorium i jego list˛e commitów.
• Podaj dat˛e i opis ostatniego commita
• Znajdź numery ID ticketów (Fixed #...) z issue trackera, które zostały rozwiazane
˛
w ostatnim miesiacu
˛
• Spróbuj skorzystać zamiast biblioteki standardowej z pakietu requests
https://api.github.com/
GET /orgs/django/repos
GET /repos/dajngo/django/commits
5.9. Zadania
79
Python Workshop, Release 3f9e170, 2017-02-21
curl https://api.github.com/orgs/django/repos
>>> auth = b'username:token'
>>> headers={
...
'Authorization': 'Basic {}'.format(base64.b64encode(auth).decode('ascii')),
...
'User-Agent': 'Python HTTP',
...}
# ...
>>> body = resp.read().decode()
>>> data = json.loads(body)
Generatory vs. Przetwarzanie Listy
Napisz program, który wczyta plik /etc/passwd, a nast˛epnie:
• przefiltruje linie, tak aby nie zawierały komentarzy (zaczynajace
˛ si˛e od #)
• przefiltruje linie, aby wyciagn
˛ ać
˛ konta systemowe - użytkowników, którzy maja˛ UID (trzecie pole) mniejsze niż
1000
• zwróci list˛e loginów takich użytkowników
• Zaimplementuj rozwiazanie
˛
wykorzystujac
˛ zwykła˛ funkcj˛e.
• Zaimplementuj rozwiazanie
˛
wykorzystujac
˛ generator i słówko kluczowe yield.
• Porównaj wyniki jednego i drugiego rozwiazania
˛
przez użycie sys.getsizeof()
Wielowatkowo
˛
ść
• Stwórz kolejk˛e queue do której dodasz różne polecenia systemowe do wykonania, np.
/etc/’, ’/bin/echo "test"’, ’/bin/sleep 2’].
[’/bin/ls
• Nast˛epnie przygotuj trzy watki
˛ workerów, które b˛eda˛ wykonywały polecenia z kolejki.
• Watki
˛
powinny być uruchamiane jako subprocess w systemie operacyjnym z timeoutem równym
PROCESSING_TIMEOUT = 2.0 sekundy
• Ilość poleceń może si˛e zwi˛ekszać w miar˛e wykonywania zadania.
• Watki
˛ powinny być uśpione za pomoca˛ Timer przez 5.0 sekund, a nast˛epnie ruszyć do roboty.
• Watki
˛ maja˛ być uruchomione w tle (ang. daemon)
• Użyj logowania za pomoca˛ biblioteki logging tak aby przy wyświetlaniu wyników widoczny był identyfikator
procesu i watku
˛
• Napisz testy do workerów i kolejki
Podpowiedź
import subprocess
import shlex
cmd = 'ls -la'
with Popen(shlex.split(cmd), stdout=PIPE) as proc:
log.write(proc.stdout.read())
80
Chapter 5. Zaawansowany
Python Workshop, Release 3f9e170, 2017-02-21
Mini Botnet
Stwórz program, który otworzy socket na porcie na localhoście podanym przez użytkownika z linii poleceń (wykorzystaj argparse) i b˛edzie nasłuchiwał połaczeń.
˛
Zweryfikuj za pomoca˛ telnet albo netcat czy program
odpowiada. Nast˛epnie napisz w pythonie klienta, który b˛edzie wysyłał polecenia do tamtego programu.
Uwaga, nigdy nie rób tego na produkcji bez tzw. sanityzacji parametrów, np. lista zaufanych hostów, możliwe
polecenia!
• zrób aby przetwarzanie requestów było nieblokujace,
˛ tzn. otwieraj watek
˛ dla każdego zapytania
• program wykona polecenie za pomoca˛ eval, które przyszło z zapytania
• wykonaj polecenie w systemie operacyjnym i zwróć klientowi odpowiedź
• dodaj funkcj˛e aby wyświetlał dowolny plik
• dodaj funkcj˛e aby listował dowolny katalog - wykorzystaj os.walk oraz os.path.join do łaczenia
˛
nazw
katalogów
• zmodyfikuj program aby przyjmował zapytania w formacie XML, pole command oraz arguments powinny być
osobno
• zmodyfikuj program aby przyjmował zapytania w formacie JSON, pole command oraz arguments powinny być
osobno
• stwórz dekorator localhost_only, który b˛edzie sprawdzał IP źródłowe połaczenia
˛
i jeżeli nie pochodzi z
127.0.0.1 odmówi wykonania polecenia
• stwórz dekorator log_request, który weźmie parametry zapytania (IP, polecenie, argumenty) i zapisze je do pliku /tmp/botnet.log w formacie Request from IP:PORT to execute COMMAND
ARGUMENTS
Podpowiedź
• subprocess.Popen
• użyj os.path.join do łaczenia
˛
sciezki i nazwy pliku
5.9. Zadania
81
Python Workshop, Release 3f9e170, 2017-02-21
82
Chapter 5. Zaawansowany
CHAPTER 6
Załaczniki
˛
Przydatne odnośniki
Doumentacja
• https://www.python.org - Strona do pobrania Pythona
• https://pyformat.info - Formatowanie stringów w Python
• http://devdocs.io
Video
• http://www.infoq.com/python/
• http://pyvideo.org/
• https://www.youtube.com/watch?v=-5wpm-gesOY
Środowisko developerskie
• https://www.jetbrains.com/pycharm/download/
Ponadto
• https://python3wos.appspot.com - Python 3 lista kompatybilnych bibliotek
• http://www.unixtimestamp.com
• https://coloredlogs.readthedocs.io/en/latest/
Humor IT
• http://geekandpoke.typepad.com
• http://devopsreactions.tumblr.com
83
Python Workshop, Release 3f9e170, 2017-02-21
Inne
Poniższe materiały i linki pochodza˛ z:
programowanie-wstep-pod-/
* http://www.wykop.pl/wpis/9876900/python-naukaprogramowania-
2. Video (i inne): Screencasty / kursy video potrafia˛ sporo pomóc, nie korzystaj wyłacznie
˛
z nich, to po prostu kolejna
pomoc naukowa.
http://shop.oreilly.com/product/110000448.do - Dobra seria filmów dla bardzo poczatkuj
˛ acych,
˛
świetny materiał do
ogladania
˛
na zmian˛e z czytaniem pierwszej ksia˛żki i eksperymentowaniem z pierwszymi programami.
http://learnpythonthehardway.org/ - jest ksia˛żka złożona z praktycznie samych ćwiczeń oraz seria screencastów
pokazujacych
˛
rozwiazania
˛
tych ćwiczeń.
http://shop.oreilly.com/product/110000667.do - wst˛ep do algorytmów z użyciem pythona, należy uważać - prezenter
pisze sporo kodu który jest uważany za nie-pythoniczny
http://www.pluralsight.com/tag/python - wiele godnych uwagi serii screencastów ( mi˛edzy innymi ucza˛
cych podstawowego i zaawansowanego pythona, pisania aplikacji GUI w Qt), ale najważniejsza z nich:
http://www.pluralsight.com/courses/python-developers-toolkit - to bardzo krótka seria uczacy
˛ najważniejszych i
niemal niezb˛ednych każdemu programiście pythona narz˛edzi
Filmy
z
ostatnich
konferencji
(dużo
tego,
każdy
znajdzie
coś
dla
siebie)
https://www.youtube.com/playlist?list=PLBGl1tVyiWQSVwxne3yOH79uaSqgbnCqL - Kiwi Pycon 2014
https://www.youtube.com/playlist?list=PLE7tQUdRKcybbNiuhLcc3h6WzmZGVBMr3
Filmy
z
DjangoCon 2014 https://www.youtube.com/channel/UC45KSayx_kwQAnhpaPAuVkw/videos - Filmy z PyGotham
2014
http://pyvideo.org/category/56/pycon-australia-2014
http://pyvideo.org/category/55/pydataberlin-2014
http://pyvideo.org/category/54/europython-2014
http://pyvideo.org/category/52/pyohio-2014
http://pyvideo.org/category/51/scipy-2014
http://www.codecademy.com/en/tracks/python - to interaktywny kurs pythona w przegladarc˛
˛
e, nie trzeba nic instalować, wystarczy wykonywać polecenia. Jest całkiem w porzadku,
˛
ale nie polecam go jako “jedynego” źródła
wiedzy o Pythonie, oraz (ostatnio gdy sprawdzałem) nie wspierał Pythona 3.
3. Wyzwania i potyczki TO SUPER WAŻNE żebyś podczas czytania i ogladania
˛
programował i nie kopiował gotowego kodu z paczek źródłowych do ksia˛żek tylko r˛ecznie pisał, starajac
˛ si˛e zrozumieć co piszesz. Musisz eksperymentować, wprowadzać własne zmiany, pisać własne projekty i realizować własne pomysły.
https://warosu.org/data/g/img/0441/94/1410874830625.png - zbiór 100 pomysłów na projekty treningowe aby
nauczyć si˛e na nich programowania
Strony z zadaniami i zagadkami algorytmicznymi, poćwicza˛ twoje myślenie i niejednokrotnie optymalizacj˛e kodu.
Miłe oderwanie od innej nauki. Uwaga - nie przesadzać, bo wpadniesz w złe praktyki i spiral˛e przedwczesnej optymalizacji.
http://pl.spoj.com/
http://codeeval.com/
https://www.reddit.com/r/dailyprogrammer
https://www.hackerrank.com/
http://www.codechef.com/
Naucz si˛e j˛ezyka SQL i opanuj przynajmniej jeden system zarzadzania
˛
baza˛ danych: O SQL jest 4
tony całkiem niezłych ksia˛żek, kursów i tutoriali, łatwo znaleźć wi˛ec nic konkretnego nie podam. PostgreSQL - goraco
˛ polecam - http://www.postgresql.org/ MySQL (MariaDB) - https://www.mysql.com/ Oracle http://www.oracle.com/pl/products/database/overview/index.html
Interesuj si˛e i badź
˛
na bieżaco:
˛
https://www.reddit.com/r/learnpython https://www.reddit.com/r/python
https://www.reddit.com/r/learnprogramming https://www.reddit.com/r/programming
Jeżeli prosisz kogoś o pomoc pami˛etaj żeby: - Wkleić kod na jakieś pastie - np. http://dpaste.com/ ,
http://hastebin.com/ - Sprawdzić czy kod faktycznie nie działa -u siebie i np na http://ideone.com/ - Wklejajac
˛ fragmenty kodu na wykop używać http://wykop-code.appspot.com/ w celu zachowania czytelności i wci˛eć - Opisać zrozumiale z czym masz problem i czego już probowałeś żeby temu zaradzić - Wkleić pełna˛ treść bł˛edu (jeżeli jest długo to
na pastie) jeżeli takowy wystapił
˛
84
Chapter 6. Załaczniki
˛
Python Workshop, Release 3f9e170, 2017-02-21
Python 2 vs. 3
six
Python six
Lista kompatybilności Python 2 i Python 3
Wall of Super Powers
Unicode i kodowanie znaków
Biblioteki standardowe w 2 i 3
Name
builtins
configparser
copyreg
cPickle
cStringIO
dbm_gnu
_dummy_thread
email_mime_multipart
email_mime_nonmultipart
email_mime_text
email_mime_base
filter
filterfalse
getcwd
getcwdb
http_cookiejar
http_cookies
html_entities
html_parser
http_client
BaseHTTPServer
CGIHTTPServer
SimpleHTTPServer
input
intern
map
queue
range
reduce
reload_module
reprlib
shlex_quote
socketserver
6.2. Python 2 vs. 3
Python 2 name
py2:__builtin__
py2:ConfigParser
py2:copy_reg
py2:cPickle
py2:cStringIO.StringIO()
py2:gdbm()
py2:dummy_thread
py2:email.MIMEMultipart
py2:email.MIMENonMultipart
py2:email.MIMEText
py2:email.MIMEBase
py2:itertools.ifilter()
py2:itertools.ifilterfalse()
py2:os.getcwdu()
py2:os.getcwd()
py2:cookielib
py2:Cookie
py2:htmlentitydefs
py2:HTMLParser
py2:httplib
py2:BaseHTTPServer
py2:CGIHTTPServer
py2:SimpleHTTPServer
py2:raw_input()
py2:intern()
py2:itertools.imap()
py2:Queue
py2:xrange()
py2:reduce()
py2:reload()
py2:repr
py2:pipes.quote
py2:SocketServer
Python 3 name
py3:builtins
py3:configparser
py3:copyreg
py3:pickle
py3:io.StringIO
py3:dbm.gnu
py3:_dummy_thread
py3:email.mime.multipart
py3:email.mime.nonmultipart
py3:email.mime.text
py3:email.mime.base
py3:filter()
py3:itertools.filterfalse()
py3:os.getcwd()
py3:os.getcwdb()
py3:http.cookiejar
py3:http.cookies
py3:html.entities
py3:html.parser
py3:http.client
py3:http.server
py3:http.server
py3:http.server
py3:input()
py3:sys.intern()
py3:map()
py3:queue
py3:range()
py3:functools.reduce()
py3:imp.reload(), py3:importlib.relo
py3:reprlib
py3:shlex.quote
py3:socketserver
Con
85
Python Workshop, Release 3f9e170, 2017-02-21
Name
_thread
tkinter
tkinter_dialog
tkinter_filedialog
tkinter_scrolledtext
tkinter_simpledialog
tkinter_ttk
tkinter_tix
tkinter_constants
tkinter_dnd
tkinter_colorchooser
tkinter_commondialog
tkinter_tkfiledialog
tkinter_font
tkinter_messagebox
tkinter_tksimpledialog
urllib.parse
urllib.error
urllib.request
urllib.response
urllib.robotparser
urllib_robotparser
UserDict
UserList
UserString
winreg
xmlrpc_client
xmlrpc_server
xrange
zip
zip_longest
Table 6.1 – continued from previous page
Python 2 name
Python 3 name
py2:thread
py3:_thread
py2:Tkinter
py3:tkinter
py2:Dialog
py3:tkinter.dialog
py2:FileDialog
py3:tkinter.FileDialog
py2:ScrolledText
py3:tkinter.scrolledtext
py2:SimpleDialog
py3:tkinter.simpledialog
py2:ttk
py3:tkinter.ttk
py2:Tix
py3:tkinter.tix
py2:Tkconstants
py3:tkinter.constants
py2:Tkdnd
py3:tkinter.dnd
py2:tkColorChooser
py3:tkinter.colorchooser
py2:tkCommonDialog
py3:tkinter.commondialog
py2:tkFileDialog
py3:tkinter.filedialog
py2:tkFont
py3:tkinter.font
py2:tkMessageBox
py3:tkinter.messagebox
py2:tkSimpleDialog
py3:tkinter.simpledialog
See six.moves.urllib.parse
py3:urllib.parse
See six.moves.urllib.error
py3:urllib.error
See six.moves.urllib.request
py3:urllib.request
See six.moves.urllib.response py3:urllib.response
py2:robotparser
py3:urllib.robotparser
py2:robotparser
py3:urllib.robotparser
py2:UserDict.UserDict
py3:collections.UserDict
py2:UserList.UserList
py3:collections.UserList
py2:UserString.UserString
py3:collections.UserString
py2:_winreg
py3:winreg
py2:xmlrpclib
py3:xmlrpc.client
py2:SimpleXMLRPCServer
py3:xmlrpc.server
py2:xrange()
py3:range()
py2:itertools.izip()
py3:zip()
py2:itertools.izip_longest() py3:itertools.zip_longest()
Httplib w 2 i 3
Python 3.5 i deklaracja typów
def suma(a: int, b: int) -> int:
return a + b
Wybór IDE
Czym jest IDE?
Do edycji skryptów Pythona wystarczy sam Notatnik. Kod źródłowy jest na tyle czytelny i prosty, że bardzo łatwo
b˛edziemy w stanie poradzić sobie z prostymi skryptami bez jakiejkolwiek pomocy od zaawansowanego edytora. Jednakże w miar˛e rośni˛ecia złożoności projektu oraz ilości plików przyda nam si˛e coś co ułatwi nam prac˛e.
Wybór edytora to temat wielce kontrowersyjny. Od kilku dziesi˛ecioleci w środowisku programistów jest prowadzona
wojna mi˛edzy minimalistycznym VIMem oraz posiadajacym
˛
ogromne możliwości EMACSem. Jeden i drugi edytor
86
Chapter 6. Załaczniki
˛
Python Workshop, Release 3f9e170, 2017-02-21
wspaniale posłuży nam do pisania skryptów w Pythonie i po odpowiedniej konfiguracji lub instalacji pluginów podpowie składni˛e. I choć sam jestem fanem jednego z powyższych rozwiazań
˛ (ale nie powiem którego :) to do wi˛ekszych
projektów korzystam z czegoś zupełnie z innej beczki. Po przetestowaniu kilkunastu środowisk IDE zaprzyjaźniłem
si˛e z edytorem PyCharm. PyCharm ma dwie wersj˛e płatna˛ oraz darmowa.˛ Ta druga w zupełności nam wystarczy.
Ciekawa˛ alternatywa˛ może być PyDev - plugin do środowiska Eclipse.
W poniższych materiałach b˛ed˛e posługiwał si˛e kodem źródłowym, który wykonywany jest przez interpreter i nie ma
znaczenia z jakiego IDE skorzystasz.
Poniższe materiały i linki pochodza˛ z:
programowanie-wstep-pod-/
* http://www.wykop.pl/wpis/9876900/python-naukaprogramowania-
Korzystaj z dobrego IDE (lub edytora): W kategorii IDE jest PyCharm i później długo długo nic. Należy si˛e z tym
pogodzić i nie zaprzeczać rzeczywistości, ponieważ ani Wingware ani Komodo IDE (konkurencja) nie graja˛ w tej
samej lidze. Darmowa wersja “Community Edition” powinna jak najbardziej wystarczyć do nauki Pythona.
Jeżeli IDE uważasz za coś potwornego i zb˛ednego - to si˛e mylisz, ale nie mam zamiaru ci˛e w tym miejscu przekonywać. Dla takich ludzi jak ty też jest nadzieja. Zarówno dobrze skonfigurowany vim jak i Sublime Text 3 moga˛ posłużyć
za dobry edytor do nauki Pythona.
Korzystaj z dobrego interpretera: Pobierz najnowsza˛ wersj˛e z serii 3 (w tej chwili to 3.4.2) bezpośrednio z:
https://www.python.org/downloads/
Znaj narz˛edzia potrzebne do pracy w dobrym środowisku pythona: (uczy tego wyżej już wymienione
http://www.pluralsight.com/courses/python-developers-toolkit ) Pomocny może okazać si˛e też taki podr˛ecznik: http://docs.python-guide.org/en/latest/ Pip - http://pip.readthedocs.org/en/latest/index.html Virtualenv
- http://virtualenv.readthedocs.org/en/latest/ Debugger - http://pymotw.com/2/pdb/
Nauczyć si˛e ładnego formatowania kodu i odpowiedzi na najcz˛eściej zadawane pytania: To niezmiernie ważne, szacuje
si˛e że ponad 80% kodu napisanego w Pythonie stosuje si˛e do poniższych zasad. http://legacy.python.org/dev/peps/pep0008/ https://code.google.com/p/google-styleguide/
Poznaj filozofi˛e Pythona: http://legacy.python.org/dev/peps/pep-0020/ https://gist.github.com/evandrix/2030615
Naucz si˛e GITa (system kontroli wersji): http://git-scm.com/book https://try.github.io/ https://www.atlassian.com/git/
http://www.git-tower.com/learn/ebook/command-line/introduction
Publikuj swój kod i czytaj kod innych: https://github.com/ https://bitbucket.org/
Ekosystem Narzediowy
˛
Code Quality
PEP8
About Python style guide checker. pep8 is a tool to check your Python code against some of the style
conventions in PEP 8.
• Plugin architecture: Adding new checks is easy.
• Parseable output: Jump to error location in your editor.
• Small: Just one Python file, requires only stdlib. You can use just the
• pep8.py file for this purpose.
• Comes with a comprehensive test suite.
Installation
6.4. Ekosystem Narzediowy
˛
87
Python Workshop, Release 3f9e170, 2017-02-21
pip install pep8
pip install --upgrade pep8
pip uninstall pep8
Usage
pep8
pep8
pep8
pep8
FILENAME.py
DIRECTORY/
--statistics -qq DIRECTORY/
--show-source --show-pep8 FILENAME.py
Config setup.cfg
[pep8]
max-line-length = 939
ignore = E402,W391
SonarQube
About SonarQube software (previously called Sonar) is an open source quality management platform,
dedicated to continuously analyze and measure technical quality, from project portfolio to method.
More information
• https://sonarqube.com
• http://docs.sonarqube.org/display/SONAR/Documentation
• https://sonarqube.com/dashboard/index?did=143
• https://sonarqube.com/governance?id=662857
Pylint
About Pylint is a Python source code analyzer which looks for programming errors, helps enforcing a
coding standard and sniffs for some code smells (as defined in Martin Fowler’s Refactoring book).
Pylint has many rules enabled by default, way too much to silence them all on a minimally sized program. It’s highly configurable and handle pragmas to control it from within your code. Additionally,
it is possible to write plugins to add your own checks.
Install
pip install pylint
pip install --upgrade pylint
pip uninstall pylint
Usage
pylint DIRECTORY/
pylint FILENAME.py
More information
• https://pypi.python.org/pypi/pylint/
88
Chapter 6. Załaczniki
˛
Python Workshop, Release 3f9e170, 2017-02-21
Pyflakes
About A simple program which checks Python source files for errors. Pyflakes analyzes programs and
detects various errors. It works by parsing the source file, not importing it, so it is safe to use on
modules with side effects. It’s also much faster.
Install
pip install pyflakes
pip install --upgrade pyflakes
pip uninstall pyflakes
Usage
pyflakes DIRECTORY/
python -m pyflakes DIRECTORY/
More information
• https://pypi.python.org/pypi/pyflakes
Coverage
About Coverage.py measures code coverage, typically during test execution. It uses the code analysis
tools and tracing hooks provided in the Python standard library to determine which lines are executable, and which have been executed.
Install
pip install coverage
pip install --upgrade coverage
pip uninstall coverage
Usage
coverage run FILENAME.py
coverage report -m
More information
• https://pypi.python.org/pypi/coverage
• https://coverage.readthedocs.io/
unittest
Usage
python -m unittest FILENAME.py
Automation and Releases
Fabric
Install
6.4. Ekosystem Narzediowy
˛
89
Python Workshop, Release 3f9e170, 2017-02-21
pip install fabric
pip install --upgrade fabric
pip uninstall fabric
Testy Mutacyjne
• https://pypi.python.org/pypi/MutPy
Transifex
• https://www.transifex.com
Ksiażki
˛
Design patterns
• Design Patterns: Elements of Reusable Object-Oriented Software
Refactoring
• Working effectively with legacy code
Quality
• Clean Code
Python
Poniższe materiały i linki pochodza˛ z:
programowanie-wstep-pod-/
* http://www.wykop.pl/wpis/9876900/python-naukaprogramowania-
http://www.amazon.com/Learning-Python-Edition-Mark-Lutz/dp/1449355730/ to podstawowa pozycja, dobra, do
nauki Pythona. Jednocześnie uczy/pokazuje Pythona 2 jak i 3. Jeżeli ktoś chce mieć, w miar˛e, wszystko w jednym
miejscu, to warto si˛e w ta˛ ksia˛żk˛e zaopatrzyć. Ważne żeby to było wydanie 5, a nie wcześniejsze.
http://www.amazon.com/Python-Programming-Introduction-Computer-Science/dp/1590282418/ Ci którzy znaja˛ już
jakiś j˛ezyk bardzo dobrze lub studiuja˛ informatyk˛e moga˛ chcieć zamiast ksia˛żki Lutza wybrać ta˛ pozycj˛e. Jest krótsza,
zwi˛eźlejsza i tłumaczy znacznie mniej, szczególnie rzeczy podstawowych. Wydanie drugie zostało zaktualizowane na
potrzeby Pythona 3.
http://inventwithpython.com/ Jeżeli jesteś #cebula i nie chcesz wydać ani złotówki na pierwsza˛ ksia˛żk˛e, jest dla ciebie
nadzieja. Al Sweigart napisał ksia˛żki uczace
˛ programować w Pythonie przy okazji tworzenia prostych gier lub poznawania podstaw kryptografii. Oprócz sprzedawania ich na Amazonie, udost˛epnia je też za darmo na swojej stronie.
Pozycje obowiazkowe
˛
(numer 2, 3 i 4):
http://www.amazon.com/Python-Cookbook-David-Beazley/dp/1449340377/
90
Chapter 6. Załaczniki
˛
Python Workshop, Release 3f9e170, 2017-02-21
To jest ksia˛żka która powinna si˛e znaleźć u każdego na półce niezależnie od obranej drogi nauki. Pozycja absolutnie obowiazkowa.
˛
Zawiera ton˛e (kilkaset?) gotowców, podzielonych na kategori˛e z wyjaśnieniem jaki problem
rozwiazuj
˛ a˛ oraz dlaczego tak a nie inaczej. Wydanie trzecie, wspiera oczywiście Pythona 3.
https://www.jeffknupp.com/writing-idiomatic-python-ebook/
Ebook z kategorii obowiazkowych.
˛
Uczy jak pisać kod uważany za Pythonowy i unikać szkodliwych kalek np. z C++.
Jest wersja dla Pythona 3.
http://www.amazon.com/Python-Practice-Concurrency-Libraries-Developers/dp/0321905636/
wzorce projektowe, programowanie współbieżne. Warta każdej złotówki.
Dobre
praktyki,
Tyle jeżeli chodzi o pozycje obowiazkowe,
˛
jest jednak jeszcze par˛e ciekawych pozycji, które mog˛e polecić: http://learnpythonthehardway.org/book/ - darmowa wersja ksia˛żki złożonej z praktycznie samych ćwiczeń
http://anandology.com/python-practice-book/index.html - jeszcze wi˛ecej ćwiczeń http://www.amazon.com/Python3-Object-Oriented-Programming/dp/1849511268/ - ksia˛żka uczaca
˛ (i skupiajaca
˛ si˛e tylko na tym) koncepcji programowania obiektowego na konkretnych przykładach Pythona 3 http://shop.oreilly.com/product/0636920032519.do
- pozycja w trakcie tworzenia, zapowiada si˛e na dobra˛ ksia˛żk˛e o zaawansowanym pythonie.
Znajomość j˛ezyka to jednak nie wszystko i jeżeli chcesz być ogólnie kompetentnym programista˛ polecam poniższe
ksia˛żki: Algorytmy: http://www.amazon.com/Introduction-Algorithms-Edition-Thomas-Cormen/dp/0262033844/
http://www.amazon.com/Algorithms-4th-Edition-Robert-Sedgewick/dp/032157351X/
Wzorce obiektowe: http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/
Bazy
danych:
http://www.amazon.com/Database-Design-Mere-Mortals-Hands-/dp/0321884493/
http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557/
Pozycje
nieobowiazkowe,
˛
ale najdogł˛ebniejsze - http://www.amazon.com/C.-J.-Date/e/B000AQ6OJA/
Dobre praktyki i inne: http://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/
http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X/
http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/
http://www.amazon.com/The-Mythical-Man-Month-Engineering-Anniversary/dp/0201835959/
Python WAT?!
>>> 999 + 1 is 1000
False
>>> 1 + 1 is 2
True
>>> 2.2 * 3.0 == 3.3 * 2.0
False
>>> a = ('hello', 'word')
>>> a = ('hello')
>>> for x in a:
...
print(x)
h
e
l
l
o
>>> a = ('hello', 'word')
>>> a = ('hello',)
6.6. Python WAT?!
91
Python Workshop, Release 3f9e170, 2017-02-21
>>> for x in a:
...
print(x)
hello
>>> a = 'hello', 'word'
>>> a = 'hello'
>>> for x in a:
...
print(x)
h
e
l
l
o
>>> a = 'hello', 'word'
>>> a = 'hello',
>>> for x in a:
...
print(x)
hello
92
Chapter 6. Załaczniki
˛
CHAPTER 7
Receptury
LDAP Expiring Passwords
#!/usr/bin/env python3
import datetime
import time
from pprint import pprint
from ldap3 import Server, Connection, SEARCH_SCOPE_WHOLE_SUBTREE
USER = "myusername"
PASS = "mypassword"
BASEDN = "OU=Users,DC=local"
SERVER = Server("127.0.0.1", port=389)
ATTRIBUTES = ['mail', 'pwdLastSet']
def construct_filter(wintimestamp):
return """(&
(objectCategory=Person)
(objectCategory=User)
(userAccountControl=512)
(pwdLastSet<={wintimestamp})
(mail=*)
)""".format(wintimestamp=wintimestamp)
def search(filter):
with Connection(SERVER, user=USER, password=PASS) as c:
c.search(BASEDN, filter, SEARCH_SCOPE_WHOLE_SUBTREE,
attributes=ATTRIBUTES)
return [record['attributes'] for record in c.response]
def datetime_to_mstimestamp(date):
"""
Active Direcotry has different approach to create timestamp than Unix.
Here's a function to convert the Unix timestamp to the AD one.
>>> datetime_to_mstimestamp(datetime.datetime(2000, 1, 1, 0, 0))
125911548000000000
"""
93
Python Workshop, Release 3f9e170, 2017-02-21
timestamp = int(time.mktime(date.timetuple()))
magic_number = 116444736000000000
return timestamp * 10000000 + magic_number
def mstimestamp_to_datetime(mstimestamp):
"""
Active Direcotry has different approach to create timestamp than Unix.
Here's a function to convert AD timestamp to the Unix one.
>>> mstimestamp_to_datetime(130567328471235643)
datetime.datetime(2014, 10, 2, 16, 14, 7, 123563)
"""
magic_number = 11644473600
return datetime.datetime.fromtimestamp(
mstimestamp / 10000000 - magic_number)
def month_ago(date):
"""
>>> month_ago(datetime.datetime(2000, 1, 31, 0, 0))
datetime.datetime(2000, 1, 1, 0, 0)
"""
return date - datetime.timedelta(days=30)
def print_users_with_expiring_password():
now = datetime.datetime.now()
expiration_date = month_ago(now)
wintimestamp = datetime_to_mstimestamp(expiration_date)
older_than_month_ago = construct_filter(wintimestamp)
for user in search(older_than_month_ago):
user['pwdLastSet'] = mstimestamp_to_datetime(
int(user['pwdLastSet'][0]))
pprint(user)
if __name__ == "__main__":
print_users_with_expiring_password()
94
Chapter 7. Receptury