Wstęp¶
Przedmowa¶
Geneza języka¶
Open Source,
Nazwa języka pochodzi od serialu BBC Latający Cyrk Monty Pythona. Twórca jest fanem serialu,
Python (jego interpreter) zaczął powstawać od 1989,
Guido van Rossum - były dobrotliwy, dożywotni dyktator. Jest jak Linus Torvalds dla kernela Linuxa,
Potrzeba było łatwe tworzenie narzędzi systemowych do systemu operacyjnego Amoeba,
Coś co byłoby pomiędzy językiem C a Shell,
Python 2.0 – październik 2000,
Python 3.0 - grudzień 2008
Zastosowanie¶
DevOps
Boto3,
Redhat - narzędzia,
Instalator Anaconda,
system-config-network-tui,
system-config-services,
inne system-config-,
instalatory paczek (yum - python2, dnf - python3),
OpenStack,
Ansible ( zarządzanie konfiguracją / wdrożeniem )
Data Science / Machine Learning
sklearn,
Tensorflow,
pySpark
Web Development
Django,
Flask
Kto używa¶
Google – jako główny język w firmie, obok jest Java oraz C++. Do przetwarzania ogromnej ilości danych od użytkowników,
Netflix – do skalowania infrastruktury, alerty w przypadku zmiany ustawień zabezpieczeń,
Instagram (framework Django), Facebook (Framework Tornado),
Spotify (Duży wolumen danych do przeprocesowania – Luigi),
Nasa
Instalacja¶
Linux¶
Na debianie lub ubuntu
sudo apt-get update && sudo apt-get install python python3-pip python3-venv
Na fedorze
sudo dnf install python
albo konkretna wersjasudo dnf install python37
Hint
Aby sprawdzić używaną wersję pythona wykonujemy polecenie: python --version
lub python -V
Środowisko uruchomieniowe¶
Pythona można uruchomić na kilka sposobów w zależności od zapotrzebowania.
Środowisko wirtualne (venv)¶
Odseparowuje środowiska od siebie,
Rozwiązuje problem konfliktów wersji,
Pozwala utrzymywać różne wersje bibliotek/pythona w naszych projektach
Note
Aby stowrzyć środowisko wirtualne wykonujemy jedno z dwóch poleceń
- python -m venv <KATALOG>
zamiast KATALOG najczęściej występuje venv lub env
- virtualenv <KATALOG>
np. virtualenv venv
Note
Uby użyć środowiska musimy wykonać dodatkowe polecenia:
source venv/bin/activate
Hint
W przypadku Windows użytkownik aktywuje środowisko bez użycia source
Środowisko globalne¶
Wszystkie paczki są globalne - nie ma separacji,
Często pojawiają się problemy z zależnościami
Środowisko w kontenerze¶
Python dostępny jedynie w kontenerze,
Dobre rozwiązanie w przypadku testowania oprogramowania,
Integralna część obecnych środowisk CI/CD
Ide¶
pyCharm¶
Płatne środowisko od JetBrains * Dużo pluginów, * Wsparcie dla Frameworków, * Integracja z Docker, bazami danych, konsolą, usługami chmurowymi

Visual Studio Code¶
Narzędzie darmowe,
Trzeba dogrywać pluginy aby rozszerzyć możliwości
Eclipse¶
Narzędzie darmowe
Spyder¶
Narzędzie darmowe
Używane w celach naukowych lub analizie danych. Mało popularny, wyparty raczej przez Jupyter Notebook
IDLE¶
Narzędzie darmowe,
Niezalecane,
Trudny proces developmentu
Python¶
Język strukturalny¶
Możliwe jest pisanie prostych skryptów
Język obiektowy¶
Wszystko jest obiektem
Język funkcyjny¶
>>> liczby = [1, 2, 3, 4, 5]
>>> potegi_dwojki = [2**n for n in liczby]
>>> potegi_dwojki
[2, 4, 8, 16, 32]
Dynamicznie typowany¶
Typy określane są w trakcie wykonania programu,
Z jednej strony swoboda, z drugiej wolniejsze oprogramowanie,
Brak kompilacji - błędy związane ze złym typem pojawiają się dopiero po uruchomieniu wadliwej linni kodu
miejsce = 43 # int
miejsce = "przy oknie" # str
print(miejsce)
W wyniku zostanie nadpisana zmienna (również typ się zmieni)
przy oknie
Garbage collector¶
Zarządza oczyszczaniem pamięci,
Oparty na algorytmie zliczającym ilość referencji na dany obiekt
Przekazywanie wartości przez referencje¶
Powłoki Python¶
python¶
domyślnie zainstalowany shell
ipython¶
można łatwo doinstalować,
posiada dodatkowe funkcje,
koloruje składnie
jupyter-notebook¶
oparty na ipython,
używany najczęściej w zespołach data science,
oferuje dodatkowe funckje jak np. drukowanie projektu z kodem
Konwencje nazewnicze¶
Contents
Wcięcia¶
Definiują blok podprogramu np. w definicji funkcji, klasy czy bloku if/else,
Nie można mieszać tabulatora z czteroma spacjami,
4 spacje - jako zalecany sposób,
tabulator jest dozwolony (lecz jeśli zaczynamy lepiej użyć spacji),
można ustawić środowisko aby tabulator był zamieniany na 4 spacje
Systemy notacji¶
lower_case_with_underscores¶
Używane do:
Nazw funkcji,
Nazw parametrów,
Nazw pakietów,
Nazw modułów,
def pole_kwadratu(a, b):
return a * b
print(pole_kwadratu(5, 4))
Poniżej wypisane pole kwadratu o bokach 4 i 5
20
PascalCase¶
Note
PascalCase lub UpperCamelCase to styl w którym:
Wyrazy pisane są łącznie,
Każdy wyraz pisany jest wielką literą,
PascalCase jako nazwa typu danych
>>> from pandas import DataFrame
PascalCase użyty do definiowania klasy
class SportsCar:
def __init__(self, name):
self.name = name
# Utworzenie obiektu porsch klasy SportsCar
porsch = SportsCar("porsche")
print(porsch.name)
Poniżej wypisany atrybut: nazwa
porsche
Hint
Wyjątki powinny być klasą, stąd też pisane są PascalCase
Podstawy¶
Podstawy¶
Ciągi znaków¶
Wypisywanie ciągów znaków¶
>>> print('Hello World!')
Hello World!
albo w innej formie cudzysłowów >>> print(“Hello World!”) Hello World!
Sprawdzenie typu¶
>>> type(tekst)
<class 'str'>
Sprawdzenie długości napisu¶
>>> len(tekst)
12
Wyświetlanie specjalnych znaków¶
Znak nowej linni
>>> print("Hello\nWorld!")
Hello
World!
Znak tabulatora
>>> print("Hello\tWorld!")
Konkantenacja znaków¶
>>> print('Hello ' + 'uczestniku')
Hello uczestniku
Konkantenacja znaków - format¶
>>> print('Hello {}, have a great day'.format('Tomasz'))
Hello Tomasz, have a great day
Różne reprezentacje - format¶
>>> '{:s}'.format('Ciąg znaków') # w przypadku podania liczby zamiast stringa - wyjątek
'Ciąg znaków'
class Data:
"""Simple Data class"""
def __str__(self):
return 'str'
def __repr__(self):
return 'repr'
print("{0!s} {0!r}".format(Data(), Data()))
print("{obiekt!s} {obiekt!r}".format(obiekt=Data()))
str repr
str repr
>>> '{:>10}'.format('test')
' test'
>>> '{:10}'.format('test')
'test '
>>> '{:^10}'.format('test')
' test '
Podciągi w ciągach znaków¶
>>> 'Hello'[-1]
'o'
>>> 'Hello'[0:6:2]
'Hlo'
imiona = 'Marta, Kasia, Monika, Tomek, Przemek, Janek, Marta, Malgosia'
print(imiona.count('Ma'))
W wyniku dostajemy ilość wystąpień ciągu
3
>>> imiona.find('Kasia')
7
Dzielenie ciagów po danym seperatorze¶
>>> imiona.split(',')
['Marta', ' Kasia', ' Monika', ' Tomek', ' Przemek', ' Janek', ' Marta', ' Malgosia']
Otrzymaliśmy listę ciągów
Operacje na stringach¶
>>> imiona = imiona.replace("Janek", "Adam")
>>> print(imiona)
Marta, Kasia, Monika, Tomek, Przemek, Adam, Marta, Malgosia
Sprawdzenie czy ciąg jest liczbą
>>> imiona.isdigit()
False
>>> temperatura = "34"
>>> print(temperatura.isdigit())
True
Pisanie ciągu z wielkich liter
>>> print(imiona.upper())
MARTA, KASIA, MONIKA, TOMEK, PRZEMEK, ADAM, MARTA, MALGOSIA
Pisanie ciągu z małych liter
>>> print(imiona.lower())
marta, kasia, monika, tomek, przemek, adam, marta, malgosia
Zadania¶
Stwórz program wypisujący twoje imienie i nazwisko,
Stwórz kod wypisujący: “Test znaków: ‘, /, ” “
Stwórz dwóch uczestników szkolenia ( wybierz dowolne imiona i przypisz do osobnych zmiennych)
pierwszy_uczestnik,
drugi uczestnik
Zamień uczestników miejscami
Wypisz uczestników,
Czy jest możliwy inny sposób na zamianę miejsc ?
Niech użytkownik podaje swoje imie przy każdym uruchomieniu kodu (Użyj google)
Liczby całkowite¶
Definiowanie¶
>>> wynagrodzenie_netto = 8000
>>> print(wynagrodzenie_netto)
8000
Sprawdzenie typu¶
>>> type(wynagrodzenie_netto)
<class 'int'>
Przyrównanie typów: string oraz integer
>>> wynagrodzenie_str = '8000'
>>> wynagrodzenie_str == wynagrodzenie_netto
False
Konwersja typów¶
>>> wynagrodzenie_converted = int(wynagrodzenie_str)
>>> wynagrodzenie_converted == wynagrodzenie_netto
True
Operacje na liczbach¶
Po podwyżce dostajemy o 5% więcej pieniędzy
>>> wynagrodzenie_netto = wynagrodzenie_netto*1.05
>>> print(wynagrodzenie_netto)
8400.0
>>> type(wynagrodzenie_netto) == float
True
>>> type(wynagrodzenie_netto)
<class 'float'>
Dodawanie - dostaliśmy miesięczny bonus 200 zł
>>> wynagrodzenie_netto += 200
>>> wynagrodzenie_netto = int(wynagrodzenie_netto)
>>> print(wynagrodzenie_netto)
8600
Dzielenie całkowito liczbowe - Chcemy policzyć jaki jest dochód netto na osobę w 3 osobowej rodzienie, - Przyjmniej dokładnośc do drugiego miejsca po przecinku (zaokrąglenie)
>>> print(round(wynagrodzenie_netto / 3, 2))
2866.67
>>> wynagrodzenie_netto // 3
2866
Jak widzimy straciliśmy precyzję. Wartości po przecinku zostały zignorowane
Dzielenie modulo - Sprawdzenie czy nasza kwota jest liczbą parzystą
>>> print(wynagrodzenie_netto % 2)
0
Nie ma reszty z dzielenia - więc liczba jest parzysta
Liczby zmienno przecinkowe¶
Definiowanie¶
>>> wynagrodzenie_netto = 8000.63
>>> print(wynagrodzenie_netto)
8000.63
Sprawdzenie typu¶
>>> type(wynagrodzenie_netto)
<class 'float'>
Konwersja typów¶
>>> wynagrodzenie_converted = int(wynagrodzenie_netto)
>>> wynagrodzenie_converted == wynagrodzenie_netto
False
Ciekawostki¶
>>> print(0.1 + 0.2)
0.30000000000000004
Hint
Podpowiedz na stronie.
Dodatkowo wpis na wikipedi.
import decimal
ctx = decimal.getcontext() print(ctx)
a = decimal.Decimal(0.2) b = decimal.Decimal(0.1)
ctx.prec = 6 print(a + b)
Zadania¶
Oblicz sumę liczb 123, 321, 675 oraz wyświetl ją na ekranie,
Sprawdz czy suma ta jest wielokrotnością liczby 5,
Oblicz należny podatek (linniowy 19%) od kwoty podanej przez użytkownika (input). Załóż że kwota wolna od podatków to 5000
oblicz pole koła (o podanym promieniu przez użytkownika), zaimportuj dodatkowy moduł google
Listy¶
Definiowanie¶
>>> lista_plac = [4000, 5000, 3000, 8000]
>>> print(lista_plac)
[4000, 5000, 3000, 8000]
Sprawdzenie typu¶
>>> type(lista_plac)
<class 'list'>
Operacje na listach¶
Sprawdzenie długości listy
>>> len(lista_plac)
4
Sprawdzanie wystąpienia elementu
>>> 3000 in lista_plac
True
Dodanie elementu do listy
lista_plac.append(12000)
print(lista_plac)
[4000, 5000, 3000, 8000, 12000]
Wstawienei elementu na konkretną pozycję listy
lista_plac.insert(1, 4500)
print(lista_plac)
[4000, 4500, 5000, 3000, 8000, 12000]
Posortowanie listy
lista_plac = sorted(lista_plac)
print(lista_plac)
[3000, 4000, 4500, 5000, 8000, 12000]
print(sorted(lista_plac, reverse=True))
[12000, 8000, 5000, 4500, 4000, 3000]
lista_plac.extend([2800, 15000])
lista_plac.sort()
print(lista_plac)
[2800, 3000, 4000, 4500, 5000, 8000, 12000, 15000]
Wyciąganie ostatniego elementu z listy
>>> wydobyty = lista_plac.pop()
>>> print(wydobyty)
15000
Ponownie “dorzucimy” element do listy
>>> lista_plac.append(wydobyty)
>>> print(lista_plac)
[2800, 3000, 4000, 4500, 5000, 8000, 12000, 15000]
Dorzucimy też element który jest niepoprawny (ujemne wynagrodzenie)
>>> lista_plac.append(-300)
>>> print(lista_plac)
[2800, 3000, 4000, 4500, 5000, 8000, 12000, 15000, -300]
Taki element jest nam niepotrzebny - usuniemy go:
>>> del lista_plac[-1]
>>> print(lista_plac)
[2800, 3000, 4000, 4500, 5000, 8000, 12000, 15000]
Konwersja typów¶
to tupli
tupla_plac = tuple(lista_plac)
print(tupla_plac)
(2800, 3000, 4000, 4500, 5000, 8000, 12000, 15000)
do set-a
>>> set_plac = set(lista_plac)
>>> print(set_plac)
Zadania¶
Pierwsze¶
Stwórz listę składających się z elementów:
A = „audi”
B = „bmw”
C = „mercedes”
D = „mazda”
Zamień Audi z Mazdą miejscami
Usuń ostatni samochód
Wypisz ostatni element z listy
Drugie¶
Utwórz listę temperatu
[-5, -4, 0, -3, -2, 9, 10]
,Posortuj od największej,
Przeiteruj listę od tyłu,
Czy jest jakaś różnica ?
Słowniki¶
Typ danych klucz - wartość
Definiowanie¶
>>> pracownicy = {1: 'Adam', 3: 'Tomasz', 4: 'Kasia'}
>>> print(pracownicy)
Sprawdzenie typu¶
>>> type(pracownicy)
<class 'dict'>
Operacje na slownikach¶
Sprawdzenie długości słownika
>>> len(pracownicy)
3
Sprawdzanie wystąpienia elementu
>>> 3000 in pracownicy
False
>>> 1 in pracownicy
True
Pracownik o id 1 znajduje sie w slowniku
Dodanie elementu do listy
>>> pracownicy[15] = "Marek"
>>> print(pracownicy)
>>> print(len(pracownicy))
4
Sety¶
Typ danych - tak jak zbióry w matematyce
Definiowanie¶
>>> A = {1, 2, 3, 4, 5}
>>> B = {4, 5, 6, 7, 8}
Sprawdzenie typu¶
>>> type(A)
<class 'set'>
Operacje na zbiorach¶
Sprawdzenie długości zbioru
>>> len(A)
5
Sprawdzanie wystąpienia elementu
>>> 17 in A
False
>>> 3 in A
True
Dodanie elementu do listy
>>> A.add(17)
>>> 17 in A
True
Unia
>>> C = A | B
>>> print(C.issuperset(A))
True
>>> print(C.issuperset(A))
True
Część wspólna
>>> D = A & B
>>> print(D)
Różnica
>>> E = A - B
>>> F = B - A
Różnica symetryczna
>>> print(A.symmetric_difference(B))
Zbiory imutowalne¶
>>> A = frozenset([1, 2, 3, 4])
Implementacja¶
Kod w C do podejrzenia
Zadania¶
Pierwsze¶
mając biory:
A = {‘wp.pl’, ‘onet.pl’, ‘google.com’, ‘ing.pl’, ‘facebook.com’}
B = {‘wp.pl’, ‘youtube.pl’, ‘wikipedia.org’, ‘ovh.com’, ‘facebook.com’}
Znajdz:
Te domeny które w obu zbirach są wspolne
Domeny występującę wyłącznie albo w jednym albo w drugim zbiorze
Drugie¶
mając listę [1, 2, 4, 5, 7, 7, 7] wyświetl jedynie jej unikatowe wartości
Sterowanie wykonaniem kodu¶
Instrukcje warunkowe¶
if-y
if True:
print('Wartość prawdziwa')
Powyższy kod zwraca tekst:
Wartość prawdziwa
if False:
print('Wartość fałszywa')
Konwersje typów do Boolean¶
if []:
print('Lista z zawartoscia')
else:
print('Lista pusta')
Powyższy kod zwraca tekst:
Lista pusta
Sprawdzanie wartości logicznych¶
>>> bool(-1)
True
>>> bool(0)
False
>>> bool(124)
True
>>> bool({})
False
Sprawdzanie zakresów¶
temperatura = 18
if 16 <= temperatura < 24:
print('Temperatura dobra na rower')
else:
print('Temperatura nieodpowiednia na jazdę rowerem')
Temperatura dobra na rower
temperatura = -3
if 16 <= temperatura < 24:
print('Temperatura dobra na rower')
elif 3 <= temperatura < 16:
print('Temperatura dobra na spacer')
elif -5 <= temperatura < 3:
print('Temperatura dobra na narty')
else:
print('Niewiadomo co robić :(')
Temperatura dobra na narty
Zadania¶
Pierwsze¶
Nie użytkownik poda swój wiek, sprawdź czy jest pełnoletni,
Niech użytkownik poda liczbę, sprawdź czy liczba ta jest int czy float
Drugie¶
Stwórz prosty kalkulator BMI który będzie przyjmował wartości z
input
w wyniku będzie zwracał status czy masz nadwagę, niedowagę czy w normie
Trzecie¶
Użyj biblioteki
os
funkcjisystem
aby sprawdzić czy host jest aktywnyW zależności od stanu wyświetl stosowny komunikat,
Pętle¶
for¶
for i in range(5):
print(i)
0
1
2
3
4
for i in range(2, 6):
print(i)
2
3
4
5
for i in range(2, 7, 2):
print(i)
2
4
6
while¶
# i to nasz iterator
i = 0
while i < 10:
print(i)
i += 1
0
1
2
3
4
5
6
7
8
9
# i to nasz iterator
i = 6
while i < 10:
if i == 7:
print('Szczęśliwa 7ka')
i += 1
continue
print(i)
i += 1
6
Szczęśliwa 7ka
8
9
# i to nasz iterator
i = 6
while i < 10:
if i == 7:
print('Szczęśliwa 7ka ?')
break
print(i)
i += 1
6
Szczęśliwa 7ka ?
iterowanie po iterables¶
for samochod in ['BMW', 'Audi', 'Mercedes']:
print(samochod)
BMW
Audi
Mercedes
Zadania¶
Pierwsze¶
Utwórz
słownik hostów
których zapiszesz datę wykonania “skanowania” oraz status czy się powiodło
Możesz zdefiniować listę hostów np.
wp.pl, google.com, ing.pl, nieistniejacyhost.domena
Możesz użyć biblioteki
datetime
googleSpróbuj zczytać datę dostępną w systemie (os.popen)
Drugie¶
Utwórz listę parzystych liczb z zakresu 0, 100,
Wyświetl listę
List/Dict/Set comprehensions¶
Używa się w celu zwiększenia czytelności kodu.
Hint
Z początku warto napisać wersję linniową, dopiero później przejść na “comprehension”
lista_parzystych_comprehension = [element for element in range(2, 21, 2)]
print(lista_parzystych_comprehension)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
lista_parzystych_comprehension2 = [element for element in range(2, 21) if (element % 2) == 0 ]
print(lista_parzystych_comprehension2)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
lista_parzystych_comprehension3 = [element for element in range(2, 21) if not (element % 2)]
print(lista_parzystych_comprehension3)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Dict comprehension¶
slownik = {'Adam': 'Audi', 'Tomek': 'BMW', 'Kasia': 'Citroen'} # doctest: +SKIP
Zadania¶
Pierwsze¶
Znajdz 20 liczb podzielnych jednocześnie przez 2 i 5
Drugie¶
Stwórz mapowanie (dict comprehension)
klucz to liczba, wartość to kolejne litery z alfabetu,
{0: 'A', 1: 'B', 2: 'C', 3: 'D'}
Hint
Spójrz na tablicę ASCII
Da się konwertować liczbę na literę,
da się użyć funkci
chr()
google
Funkcje¶
Daje możliwośc reużywalności kodu,
Ułatwia śledzenie jego używania,
Bardziej logiczna struktura kodu niz linnia po linni
Poniżej definicja funkcji
def funkcja():
""""Docstring dokuentujacy funkcje - definicja"""
print('To jest funkcja')
# "Uruchomienie" funkcji
funkcja()
To jest funkcja
Funkcja z parametrami¶
def suma_trzech_liczb(a, b, c):
"""Prosta funcka zliczająca 3 liczby"""
print(a + b + c)
wynik = suma_trzech_liczb(3, 5, 8)
print(wynik)
16
None
def suma_czterech_liczb(a, b, c=0, d=0):
"""Prosta funkcja zliczająca 4 liczby"""
return (a + b + c + d)
print(suma_czterech_liczb(3, 5))
print(suma_czterech_liczb(3, 5, 8))
print(suma_czterech_liczb(3, 5, 8, 16))
8
16
32
Args¶
def suma_wielu_liczb(wyswietl, *liczby):
suma = 0
for liczba in liczby:
suma += liczba
if wyswietl:
print('Suma wynosi {}'.format(suma))
return suma
wynik = suma_wielu_liczb(True, 1, 2, 3, 4, 5, 6, 7)
print(wynik)
Suma wynosi 28
28
Kwargs¶
def suma_zarobkow(**kwargs):
"""sumuje wszystkie osoby"""
suma = 0
for czlowiek, zarobki in kwargs.items():
suma += zarobki
return suma
print(suma_zarobkow(Adam=3000, Tomek=2500, Kasia=4320))
9820
Zadania¶
Pierwsze¶
Nie użytkownik poda swój wiek, sprawdź czy jest pełnoletni,
Niech użytkownik poda liczbę, sprawdź czy liczba ta jest int czy float
Drugie¶
Stwórz prostą funkcję która będzie sprawdzała siłę hasła (własny algorytm)
Hasło może być przynajmniej 6 literowe, maksymalnie 9
Hasło jest tyle mocniejsze, gdy:
Posiada wielkie litery,
Posiada liczbę,
Posiada znak specjalny (możesz sam zdefiniować listę specjalną np.
['_', '*', '&']
Trzecie¶
Zmodyfikuj kod na liczenie BMI - tak aby była to teraz funkcja, która dodatkowo przyjmuje
Imię,
Czwarte¶
Napisz funkcje
dane_zarobkow(dzial, statystyki=True, *args)
która dla podanego dzialu zwróci średnią zarobków działu - zaokrąglij do pełnych złotówekDodatkowo gdy flaga statystyki jest wlączona funkcja opisze więcej statystyk:
Średnią,
Medianę (własna funkcja),
Minimalna wartosc,
Maksymalną wartość
Hint
W celu obliczenia mediany można napisać funkcję. Można także wykorzystać rozwiązanie z bibliotek
Wyjątki¶
W przypadku wykonania niedozwolonej operacji,
W sytuacjach gdy zasób jest dla nas niedostępny - np. niewystarczające uprawnienia / za mało pamięci itp.
Syntax Errors¶
>>> while True print('Hello world')
File "<stdin>", line 1
while True print('Hello world')
^
SyntaxError: invalid syntax
Key Errors¶
stolice = {"Francja": "Paryz", "Niemcy":"Berlin", "Polska":"Warszawa", "Czechy":"Praga"}
stolice["USA"]
KeyError: 'USA'
Indentation Error¶
def testfunc():
print('Hello ;)')
print('My name is:')
File "<ipython-input-4-9cd3c6fb52a1>", line 3
print('My name is:')
^
IndentationError: unexpected indent
ModuleNotFoundError¶
import not_existing_module
ModuleNotFoundError: No module named 'not_existing_module'
Tablica hierarchi wyjątków w Python.
IndexError¶
uczestnicy = ['Kasia', 'Adam', 'Tomek']
uczestnicy[6]
IndexError: list index out of range
Obsługa wyjątków¶
for i in range(3, -3, -1):
try:
print('Próba dzielenia przez {}'.format(i))
3 / i
except ZeroDivisionError:
print('Pomijam, nielegalna operajca !!!')
finally:
print('Koniec obsługi')
Próba dzielenia przez 3
Koniec obsługi
Próba dzielenia przez 2
Koniec obsługi
Próba dzielenia przez 1
Koniec obsługi
Próba dzielenia przez 0
Pomijam, nielegalna operajca !!!
Koniec obsługi
Próba dzielenia przez -1
Koniec obsługi
Próba dzielenia przez -2
Koniec obsługi
Podniesienie wyjątku¶
def generate_report(input_data, outputfile):
raise NotImplementedError('Function development still in progress')
NotImplementedError: Function development still in progress
Iteratory¶
Lazy evaluation,
Oszczędne pamięciowo,
Używane są w wielu miejscach
open,
zip,
enumerate,
reversed
from typing import Iterable
print(issubclass(range, Iterable))
True
Hint
Podobnie można sprawdzić inne typy tj. list, string
from typing import Iterable, Iterator
print(isinstance(range(10), Iterable))
print(hasattr(range(10),'__iter__'))
print(callable(range(10).__iter__))
print(isinstance(iter([1,2]) , Iterator))
True
True
True
True
Iteratoru vs listy¶
# nie zużywa pamięci - iteruje w locie
for i in ( i ** 2 for i in range(10**8)):
print(i)
# zużywa dużo pamięci
lista = [ i ** 2 for i in range(10**8)]
Hint
Porównaj procesy dla listy oraz generatora przy użyciu ps aux PID
Dodatkowo możesz użyć funckji linuxowej watch -d -n 0.1
Definiowanie iteratorów¶
class Numbers:
def __iter__(self):
self.value = 1
return self
def __next__(self):
value = self.value
self.value += 1
return value
numbers = Numbers()
my_iter = iter(numbers)
print(next(my_iter))
print(next(my_iter))
print(next(my_iter))
1
2
3
Zip¶
from typing import Iterable, Iterator za = zip([1,2,3], ['a', 'b', 'c']) print(isinstance(za, Iterable)) print(isinstance(za, Iterator))True True
Generatory¶
Lazy evaluation,
Oszczędne pamięciowo
import collections, types
print(issubclass(types.GeneratorType, collections.Iterator))
True
Note
Generator jest Iteratorem, lecz Iterator nie jest Generatorem !
Wyrażenie jako generator¶
g = (n for n in range(20) if not n % 2) # tylko parzyste !
for x in g:
print(x)
Funkcja jako generator¶
def simple_gen():
yield 5
yield 10
yield 15
s = simple_gen()
print(next(s))
print(next(s))
print(next(s))
5
10
15
# już nie ma elementów aby przeiterować
print(next(s))
StopIteration:
def new_range(start=0, stop=None, step=1):
i = start
if stop is None:
while True:
yield i
i += step
else:
while i < stop:
yield i
i += step
g = new_range(2, 5)
print(next(g))
print(next(g))
2
3
Note
Generatory to funkcje produkujace kolejne wartosci. Gdy iteratory to obiekty używające metody next()
Zadania¶
Pierwsze¶
Utwórz generator, który generuje wartości będące 3 krotnością wartości od 0 do 20
Trzecie¶
Wykorzystując plik z zadnia z list comprehension
Ściągnij plik przy użyciu pythona
Hint
Można użyć biblioteki:
urllib
Można użyć domyślnej funcki
open
orazreadline
Oczyść plik,
Napisz generator konwertujący datę w tekscie na format datowy
Jako, że w trakcie generowania logów mieliśmy źle ustawiony zegar - musimy dodać jedną godzinę
Hint
W pakiecie datetime
jest timedelta
Biblioteka standardowa¶
Biblioteka standardowa¶
Pickling¶
Proces serializacji danych binarnych do postaci pliku
Dump¶
godziny = ['Tue Mar 29 23:40:17 +0000 2016', 'Tue Mar 29 23:40:19 +0000 2016']
plik_zapis = open('/Users/kamil/daty.pickle', 'wb') # write/binary
pickle.dump(godziny, pliczek)
Zadania¶
Pierwsze¶
Ściągnąć podany plik
Przetworzyć daty (stringi) do formatu z paczki datetime, w przypadku gdy
Hint
Aby ustalić format można zajrzeć do dokumentacji
Zapisać pickle po przetworzeniu
Odczytać pickle do innej zmiennej - sprawdzić
Operacje plikowe¶
Odczytywanie plików¶
file = 'plik.txt'
Czytanie linnia po linni¶
with open(r'../plik.txt') as plik_deskryptor:
lines = deskryptor_pliku.readlines()
Zapis¶
with open(r'/tmp/iris.csv', mode='w') as plik_deskryptor:
plik_deskryptor.write('hello')
Context manager¶
with open(r'plik.txt') as deskryptor_pliku:
for linia in deskryptor_pliku:
print(linia)
Wyrażenia regularne¶
Import¶
>>> import re
Zastosowania¶
Przetwarzanie tekstu,
Znajdowanie wzorców,
Oczyszczanie danych
Walidacja poprawności danych
Funkcje w pakiecie re¶
funkcja |
znaczenie oraz użycie |
Wynik |
---|---|---|
re.match |
Czy pasuje |
True/False |
re.search |
Pierwsze położenie |
|
re.split |
Dzieli po seperatorze |
Lista |
re.findall |
Znajdź wszystkie wystąpienia |
Lista |
re.finiter |
Znajdź wszystkie wystąpienia |
Iterator |
Klasy znaków¶
klasa |
znaczenie |
|
---|---|---|
. |
Dowolny znak |
|
^ |
Początek linni |
|
$ |
Koniec linni |
|
Zero lub więcej wystąpień |
||
Jeden lub więcej wystąpień |
||
? |
Jeden lub zero wystąpień |
|
{n} |
N wystąpięń |
|
{n, m} |
Ilość wystąpięń w przedziale od |
|
d |
Grupa liczbowa synonim [0-9] |
|
D |
Anty grupa liczbowa synonim [^0-9] |
|
w |
Grupa “słowna” - synonim [a-zA-Z0-9_] |
|
W |
Anty grupa “słowna” - synonim [^a-zA-Z0-9_] |
|
s |
Grupa białych znaków - synonim [rntfv] |
|
[abc] |
Grupa znaków a, b lub c |
|
[a-z] |
Znaki w zakresie od |
|
() |
Grupa |
Zadania¶
Pierwsze¶
Stwórz funkcję
sprawdz_ip
Funkcja będzie sprawdzać czy IP jest poprawne,
Przetestuj funkcję na slowniku hostow
{
'127.0.0.1': {'poprawny': None},
'8.8.8.8': {'poprawny': None},
'x.x.x.x': {'poprawny': None}
}
* W miejsce ``x.x.x.x`` wstaw adres hosta w swojej sieci,
* Zaktualizuj flagę ``poprawny``
Hint
Można użyć poniższego wyrażenia regularnego, lub znaleźć / stworzyć bardziej dokładne wyrażenie
^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$
Drugie¶
Stwórz funkcję
sprawdz_email
Funkcja będzie sprawdzać czy email jest poprawny
Trzecie¶
Używając biblioteki
requests
Ściągnij zawartość strony
Wydobądź wszystkie tagi html,
Wydobądź słowa - które człowiek jest w stanie przeczytać
Czwarte¶
Używając biblioteki
collections
Wylicz wystąpienia słów z punktu Trzeciego,
Wyświetl top 10 najczęstszych słów - wnioski ?,
Wyświetl top 70 najczęstszych słów - wnioski ?
Zasoby¶
Regex Expressions 101 - strona
Regular Expressions Cookbook by Steven Levithan, Jan Goyvaerts - książka
Stack overflow disscussion
Programowanie obiektowe¶
Programowanie obiektowe¶
Zadania¶
Pierwsze¶
Stworz klase pojazd_mechaniczny, który będzie dziedziczyl po pojazdach,
Przy tworzeniu pojazdu mech. Pytamy o numer VIN
Dodaj właściwości:
Ilosc paliwa
Spalanie na 100 km
Dodaj własciwosc (property)
Dodaj metode liczaca spalanie na 100 km na MPG (statyczna metoda)
Drugie¶
Stworz klase Server posiadajaca:
Nazwe,
Ip,
Uzyj importu os,
Stworz metode pinguj (uzyj os – opal ping systemowy),
Zapisuj historie pingów - data i czy sie udalo,
Stworz liste hostow do pingowania [ ‘127.0.0.1’, …..],
Wyswietl komunikat czy się udalo zrobic pinga
Programowanie sieciowe¶
Web api - Django¶
Stworzenie środowiska wirtualnego¶
python -m venv venv
source venv/bin/activate
Instalacja¶
pip install django
pip install djangorestframework # pamietaj o dodaniu 'rest_framework', do settings.py - INSTALLED_APPS
pip install django-extensions # pamietaj o dodaniu 'django_extensions', do settings.py - INSTALLED_APPS
pip install markdown # Markdown support for the browsable API.
pip install django-filter # Filtering support - pamietaj o dodaniu do settings.py 'django_filters' - INSTALLED_APPS
Utworzenie pliku zależności¶
pip freeze > requirements.txt
Utworzenie nowego projektu¶
django-admin startproject servermonitoring
cd servermonitoring
python manage.py migrate
python manage.py runserver
Utworzenie nowej aplikacji¶
django-admin startapp api
Sprawdzenie w przeglądarce¶
Chrome/Postman pod adres
http://127.0.0.1:8000/
Curl
http://127.0.0.1:8000/
Dostosowanie ustawień¶
Tip
podejrzyj plik manage.py
np. poprzez polecenie
cat manage.py
można tam znaleźć w jaki sposób django jest uruchamiane
zmień ustawienia w settings.py
vim servermonitoring/settings.py
Hint
można to zrobić np. poprzez uruchomienie
vim servermonitoring/settings.py
albo bezpośredni w pyCharm
# servermonitoring/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_filters',
'django_extensions',
'rest_framework',
'api'
]
Utworzenie testów¶
# api/tests.py
from django.test import TestCase
from rest_framework import status
from api.models import Server
class ServerModelTestCase(TestCase):
"""Klasa testów modelu Server"""
def setUp(self):
"""Definicja wartosci startowych"""
self.server = Server(address='127.0.0.1')
def test_model_repr(self):
self.assertEqual("<Server address: 127.0.0.1>", repr(self.server))
def test_model_str(self):
self.assertEqual("Server o adresie: 127.0.0.1", str(self.server))
Odpalenie testu¶
python manage.py test
Tworzenie modeli¶
from django.db import models
class Server(models.Model):
created = models.DateTimeField(auto_now_add=True)
location = models.CharField(max_length=100, null=True, blank=True, default='')
available = models.BooleanField(default=False)
address = models.GenericIPAddressField()
admin_contact = models.EmailField(max_length=70, null=True, blank=True)
admin_phone = models.CharField(max_length=70, null=True, blank=True, default='')
def __repr__(self):
return "<{} address: {}>".format(self.__class__.__name__, self.address)
def __str__(self):
return "{} o adresie: {}".format(self.__class__.__name__, self.address)
Utworzenie oraz uruchomienie migracji¶
python manage.py makemigrations
python manage.py migrate
Sprawdzenie kodu sql migracji¶
python manage.py sqlmigrate api 0001
Odpalenie testu po dodaniu modelu¶
python manage.py test
Dodanie testu widoku¶
# api/tests.py
# ............
from django.test import TestCase
from rest_framework import status
from api.models import Server
from django.urls import reverse
class ViewServerTestCase(TestCase):
"""Test dla widoku serwera"""
def test_create_server(self):
"""Sprawdzimy czy mozna utworzyc serwer (post)"""
url = reverse('servers')
data = {"location": "office", "address": "127.0.0.1"}
response = self.client.post(url, data, format="json")
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(len(response.data), 1)
def test_view_server_list(self):
"""Sprawdzimy czy pobierze wlasciwa ilosc serverow"""
url = reverse('servers')
response = self.client.get(url, format="json")
self.assertEqual(response.status_code, status.HTTP_200_OK)
Serializer¶
# api/serializers.py
from rest_framework import serializers
from .models import Server
class ServerSerializer(serializers.ModelSerializer):
class Meta:
model = Server
fields = '__all__' # albo fields = ('location', 'address',)
Dodanie widoku¶
# api/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import ServerSerializer
from .models import Server
class ServerList(APIView):
"""Lista serwerow"""
serializer_class = ServerSerializer
def get_queryset(self):
queryset = Server.objects.all()
location = self.request.query_params.get('location', None)
if location is not None:
queryset = queryset.filter(location__icontains=location)
return queryset
def get(self, request, format=None):
servers = self.get_queryset()
serializer = ServerSerializer(servers, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = ServerSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Dodanie urls¶
from django.contrib import admin
from django.urls import path
from api import views
urlpatterns = [
path('admin/', admin.site.urls),
path('servers/', views.ServerList.as_view(), name='servers')
]
Metody¶
Get
Post
Put
Delete
Kody HTTP¶
200
- powodzenie. Request poprawy. Odpowiedź poprawna.400
- zły request. Źle sformuowany request / problemy z autentykacją.403
- dostęp zabroniony,404
- nie ma takiej strony,500
- błąd wewnętrzny serwera. Najczęściej gdy popełniliśmy jakiś błąd w kodzie np. w django.
Requesty¶
Odpowiedzi (response)¶
Settingsy¶
Widok¶
Migracja¶
Hint
Aby podejrzeć migracje można użyć:
python manage.py showmigrations
Orm¶
Django extensions¶
python manage.py show_urls
python manage.py shell_plus # lepsza konsola - ipython
python manage.py runserver_plus # server
Programowanie zaawansowane¶
Dekoratory¶
Cel¶
Dekoratory pozwalają rozszerzyć funkcjonalność funkcji lub klasy. Dektoratory są funkcjami które “opakowują” inne funkcje lub klasy.
Przypadki użycia¶
Pamięć podręczna - (Cache),
Sprawdzanie argumentów,
Logowanie,
Rejestracja,
Weryfikacja
Definicja¶
def decorator_function(origin_function):
def wraper_function():
print('przed funkcją o nazwie {}'.format(origin_function.__name__))
return origin_function()
return wraper_function
@decorator_function
def main_function():
print('główna funkcja')
main_function()
przed funkcją o nazwie main_function
główna funkcja
Definicja gdy funkcja ma parametry (*args / **kwargs)¶
def decorator_function(origin_function):
def wraper_function(*args, **kwargs):
print('przed funkcją o nazwie {}'.format(origin_function.__name__))
return origin_function(*args, **kwargs)
return wraper_function
@decorator_function
def hello_function(imie, nazwisko):
print('Czesc jestem {} {}'.format(imie, nazwisko))
hello_function("Adam", "Nowak")
przed funkcją o nazwie hello_function
Czesc jestem Adam Nowak
Sparametryzowany dekorator¶
Przykład¶
Cache dla stron w Django cache_page
Metoda require http methods
Note
hasattr
opisane jest w Include/abstract.h
Note
hasattr
zaimplementowane jest w Objects/object.c
Użycie¶
Tip
podejrzyj plik manage.py
np. poprzez polecenie
cat manage.py
można tam znaleźć w jaki sposób django jest uruchamiane
zmień ustawienia w settings.py
Hint
można to zrobić np. poprzez uruchomienie
vim servermonitoring/settings.py
albo bezpośredni w pyCharm
Wzorzec projektowy - Proxy/Pełnomocznik¶
Klasa proxy
to klasa która może ograniczać dostęp do następnej klasy
Przypadki użycia¶
Względy bezpieczeństwa
Diagram UML¶
Referencje¶
Hashe¶
Przykład z hashem frozenseta
Python internals¶
Pozyskanie kodu¶
Utworzenie forka na githubie
Sklonowanie lokalnie repozytorium
Dodanie upstream remote
Kompilacja¶
Hint
Najlepiej skompilować z opcjami tls/ssl
W przeciwnym wypadku pip
będzię zgłaszał poniższy problem.
Can't connect to HTTPS URL because the SSL module is not available
Poniżej polecenie do konfigurowania oraz kompilacji
./configure --with-pydebug --with-openssl=$(brew --prefix openssl) && make -j
# Kompilacja
make -j2 # 2 joby
Hint
Parametr -j
określa ilość “jobów” odpalonych dla kompilacji.
Więc możemy uzyć takiej kombinacji na Macu
make -j$(sysctl hw.ncpu | grep -Eo "\d+")
Aby używać tymczasowo naszego skompilowanego pythona
musimy wskazać go w ścieżce path
PATH="/usr/local/bin:$PATH"
export PATH
Po tej operacji python3
wskazywać będzie na naszą skompilowaną wersję
Caution
Zmienna PATH
będzie zmieniona jedynie w trakcjie sesji terminala.
Instalacja¶
make altinstall
Hint
Aby zaistalować python3
na stałe musimy zrobić make install
zamiast altinstall
Wartości predefiniowane - Makra kompilatora¶
Wyświetlenie wszystkich predefiniowanych wartości
gcc -dM -E - </dev/null
Zmiany w module os¶
Powiedzmy, że chcielibyśmy zmienić zachowanie metod z modułu os
.
Założenia¶
listdir
będzie pokazywał pliki/foldery które nie są ukryte (Wszystkie pliki/foldery z kropką na początku będą pomijane)
Wyszukiwanie kodu¶
Domyślnie moduły znajdują się w: Lib/
. Do podejrzenia na github
Jako że używamy systemu posix
(mac). W kodzie mamy sprawdzenie tego faktu w linni 48 os.py
.
Linia 48 - sprawdzenie systemu
Linia 51 - załadowanie wszystkiego z
posix
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | if 'posix' in _names:
name = 'posix'
linesep = '\n'
from posix import *
try:
from posix import _exit
__all__.append('_exit')
except ImportError:
pass
import posixpath as path
try:
from posix import _have_functions
except ImportError:
pass
import posix
__all__.extend(_get_exports_list(posix))
del posix
|
Po wyszukaniu
listdir
niczego nie znaleziono,Prawdopodobnie
listdir
jest w innym module - np.posix
.
Hint
Biblioteka posix
jest napisana w niskopoziomowy sposób język C
Jego prawdziwa nazwa to:
posixmodule.c
Linia 2 - nazwa funkcji dostępna w debugerze,
Linia 8 - sprawdzenie czy jest dostępna funkcja
fdopendir
- funkcja Unixowa
Hint
Można sprawdzić tą funkcję przy użyciu man fdeopendir
Zadania¶
Zmienić
python3 range vs python2 range vs python2 xrange¶
9999999999999999999 - 21 in range(1000000000, 9999999999999999999, 3)
# w python 3 szybkie
Python 3 bierze pod uwagę __start__, __stop__ oraz __step__
9999999999999999999 - 21 in xrange(1000000000, 9999999999999999999, 3)
# w python 2 wolne
analiza kodu¶
Algorytmy¶
Drzewo¶
Definicja drzewa¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def insert(self, value):
if value <= self.value:
if self.left is None:
self.left = Node(value)
else:
self.left.insert(value)
else:
if self.right is None:
self.right = Node(value)
else:
self.right.insert(value)
def __repr__(self):
return '<Node: value: {}'.format(str(self.value))
def search(self, value):
if self.value == value:
return True
elif value < self.value:
if isinstance(self.left, type(None)):
return False
if self.left.value == None:
return False
else:
return self.left.search(value)
else:
if isinstance(self.right, type(None)):
return False
if self.right.value == None:
return False
else:
return self.right.search(value)
def __contains__(self, value):
return self.search(value)
def in_order_traversal(self):
if self.left != None:
self.left.in_order_traversal()
print(self.value)
if self.right != None:
self.right.in_order_traversal()
def get_height(self):
height = 1
if not isinstance(self.left, type(None)):
height_left = self.left.get_height()
else:
height_left = 0
if not isinstance(self.right, type(None)):
height_right = self.right.get_height()
else:
height_right = 0
return height + max(height_left, height_right)
def __len__(self):
return self.get_height()
a = Node(6)
len(a)
|
Hint
tree
Linked list¶
Linked lists¶
Testy¶
Reprezentacja,
Wstawianie wartości na danej pozycji w liscie,
pozycja “0”,
pozycja n
Odwracanie listy
Implementacja testów¶
[25]:
## Implementacja testów
import unittest
class TestLinkedList(unittest.TestCase):
"""Test linked list"""
def setUp(self):
self.linked_list = Linked(1)
linked2 = Linked(2)
linked3 = Linked(3)
linked2.next = linked3
self.linked_list.next = linked2
def test_repr(self):
self.assertRegex(repr(self.linked_list), '<Linked with value:.*')
def test_insert_at_position_0(self):
new_linked = self.linked_list.insert_at(0, 4)
cur = new_linked
results = []
while cur:
results.append(cur.data)
cur = cur.next
self.assertEqual(sorted(results), [1, 2, 3, 4])
self.assertEqual(results, [4, 1, 2, 3])
def test_insert_at_postion_1(self):
self.linked_list.insert_at(1, 4)
cur = self.linked_list
results = []
while cur:
results.append(cur.data)
cur = cur.next
self.assertEqual(results, [1, 4, 2, 3])
def test_insert_at_position_2(self):
self.linked_list.insert_at(2, 4)
cur = self.linked_list
results = []
while cur:
results.append(cur.data)
cur = cur.next
self.assertEqual(results, [1, 2, 4, 3])
def test_insert_at_position_3(self):
self.linked_list.insert_at(3, 4)
cur = self.linked_list
results = []
while cur:
results.append(cur.data)
cur = cur.next
self.assertEqual(results, [1, 2, 3, 4])
Odpalenie testów¶
[26]:
if __name__ == '__main__':
unittest.main(argv=['first-arg-is-ignored'], exit=False)
.....
----------------------------------------------------------------------
Ran 5 tests in 0.008s
OK
Implementacja list¶
[20]:
class Linked:
def __init__(self, data):
self.data = data
self.next = None
def __repr__(self):
return '<{} with value: {}'.format(self.__class__.__name__, self.data)
def insert_at(self, pos, data):
if self.data == self.next == None:
self.data = data
cur = self
tmp_pos = 0
if pos == 0:
el = Linked(data)
el.next = self
return el
while cur and tmp_pos < pos:
tmp_pos += 1
if tmp_pos == pos:
el = Linked(data)
el.next = cur.next
cur.next = el
else:
cur = cur.next
return self
[1]:
class Element:
def __init__(self, val):
self.val = val
self.next = None
self.len = 1
def insert(self, val):
cur = self
while cur.next is not None:
cur = cur.next
cur.next = Element(val)
self.len += 1
def __repr__(self):
next_val = None
if hasattr(self.next, 'val'):
next_val = self.next.val
return '<{} {} long with value: {} and next element {}'.format(self.__class__.__name__, self.len, self.val, next_val)
def insert_first(self, val):
head = Element(val)
head.next = self
self.len += 1
return head
def deleteNode(self, position):
self[position-1].next = self[position+1]
self.len -= 1
return self[position]
def __iter__(self):
self.n = 0
self.cur = self
return self
def __next__(self):
if self.n < self.len:
ret_val = self.cur
self.n += 1
self.cur = self.cur.next
return ret_val
else:
raise StopIteration
def __getitem__(self, index):
cur_iter = iter(self)
cur_item = None
for i, item in enumerate(cur_iter):
if i < index:
continue
elif i == index:
cur_item = item
else:
break
return cur_item
def __len__(self):
return self.len
[ ]:
Stos¶
Implementacja testów¶
[2]:
import unittest
class TestStack(unittest.TestCase):
def setUp(self):
self.stack = Stack()
self.stack.values = [1, 2, 3]
def test_pop(self):
result = self.stack.pop()
self.assertEqual(result, 3)
result2 = self.stack.pop()
self.assertEqual(result2, 2)
def test_push(self):
self.stack.push(9)
result = self.stack.pop()
self.assertEqual(result, 9)
Implementacja stosu¶
[3]:
class Stack:
def __init__(self):
self.head = None
self.values = []
def push(self, value):
self.values.append(value)
self.head = value
def pop(self):
ret = self.values.pop()
return ret
Uruchomienie testów¶
[4]:
if __name__ == '__main__':
unittest.main(argv=['first-arg-is-ignored'], exit=False)
..
----------------------------------------------------------------------
Ran 2 tests in 0.003s
OK
[ ]:
Kontakt¶
Kontakt¶
Mail: kpazik@variantcore.com
LinkedIn: https://www.linkedin.com/in/kamil-pazik