Inżynieria oprogramowania Ćwiczenia 26 lutego 2014 Cele przedmiotu 1 nabycie praktycznych umiejętności związanych z wytwarzaniem oprogramowania 2 opanowanie języka Python Treści Programowanie w języku Python Wprowadzenie do programowania proceduralnego Typy danych Funkcje i struktury kontrolne Moduły Wprowadzenie do programowania obiektowego Obsługa plików Zaawansowane techniki; programowanie funkcjonalne Programowanie wielowątkowe Programowanie sieci Wykorzystanie wyrażeń regularnych Techniki usuwania błędów Praca z repozytorium kodu Automatyzacja procesu budowania projektu ... Literatura 1 http: //openbookproject.net/thinkcs/python/english2e/ 2 http://docs.python.org/tutorial/ 3 Mark Summerfield, Python 3. 4 ... dowolna inna pozycja do Pythona. Zasady zaliczenia Regulamin studiów Zaliczenie ćwiczeń: na każdych zajęciach oprócz ostatnich punkty za kodowanie zadań; 14 zajęć, zawsze do zdobycia 5-6 punktów (w sumie min. 75 punktów) każde zadanie będzie można dokończyć w domu (termin zawsze podany na zajęciach) quiz na 25 punktów w sumie można będzie zdobyć 100 punktów (lub nieco ponad) Praca niesamodzielna Minus 10 punktów na koniec za każdy wykryty przypadek niesamodzielnej pracy, brak punktów za zadanie. Zasady zaliczenia Progi PUNKTOWE: 0.00 – 59.99 60.00 – 69.99 70.00 – 79.99 80.00 – 89.99 90.00 – 94.99 95.00 – 100 powyżej 100 ndst dst dst pl db db pl bdb cel brak wystarczającej liczby puntków = poprawka we wrześniu formuła poprawki: quiz + do napisania zadanie programistyczne Quiz quiz na moodle test wyboru Termin Kolokwium odbędzie się na ostatnich zajęciach. Nieobecności usprawiedliwienia przynosimy na najbliższych zajęciach po powrocie na uczelnię po tym terminie brak możliwości usprawiedliwienia zajęć do 2 nieusprawiedliwionych nieobecności – nie odejmujemy punktów każda kolejna nieobecność to –3 punkty frekwencja poniżej 50% – brak klasyfikacji reguły dotyczące obecności nie dotyczą studentów z IOZ wykonywanie zadań nie wymaga obecności na zajęciach Coursera możliwość zdobycia dodatkowych 10 punktów - ukończenie kursu z Pythona na Courserze Link do kursu https://www.coursera.org/course/interactivepython Start kursu: 24 marca IOZ Podpisujemy zgodę na IOZ, ale zasady zaliczenia się nie zmieniają. Wszystkich studentów, bez względu na to, czy uzyskali IOZ, czy nie, obowiązują takie same reguły zdobywania punktów. Wyjątkiem jest frekwencja, co reguluje regulamin studiów. Reguły ogólne W przypadkach spornych głównymi obowiązujacymi regułami jest regulamin studiów i zasady zaliczenia obowiązujące w KIE: http: //www.kie.ue.poznan.pl/pl/content/zasady-zaliczania Rejestracja na przedmiot Hasło: ... Rejestracja do sprawdzarki http://150.254.36.78/judge/sharifjudge/index.php/ register Wprowadzenie do programowania w języku Python Uniwersytet Ekonomiczny w Poznaniu 26 lutego 2014 Wprowadzenie do programowania w języku Python Język Python Definicja (Wikipedia) Język programowania wysokiego poziomu ogólnego przeznaczenia i rozbudowanym pakiecie bibliotek standardowych, którego ideą przewodnią jest czytelność i klarowność kodu źródłowego. Jego składnia cechuje się przejrzystością i zwięzłością. Wprowadzenie do programowania w języku Python Hello world w javie public class HelloWorld { public static void main ( String [] args ) { System . out . println ( " Hello , world ! " ); } } ./hello world.java Wprowadzenie do programowania w języku Python 1 2 3 4 5 Hello world w Pythonie print ( " Hello world ! " ) 1 ./hello.py Wprowadzenie do programowania w języku Python Wybór języka programowania Język C C++ Fortran 95 Java Perl Python Smalltalk Microsoft Visual Basic Poziom w stosunku do C 1 2.5 2 2.5 6 6 6 4.5 Tabela: Poziomy języka w stosunku do C. Źródło: Code Complete 2 - Steve McConnell, za “Estimating Software Costs” (Jones 1998), “Software Cost Estimation with Cocomo II” (Boehm 2000), “An Empirical Comparison of Seven Programming Languages” (Prechelt 2000). Wprowadzenie do programowania w języku Python Wersje Pythona Ciągle wykorzystywane są dwie wersje: Python 2 (ostatnia wersja: Python 2.7) Python 3 Wersje te nie są ze sobą w pełni zgodne! My na zajęciach korzystamy z wersji trzeciej. Wprowadzenie do programowania w języku Python Python – różne implementacje Różne implementacje języka Python: CPython (Python) – główna implementacja, najczęściej stosowana, także podczas tych zajęć. Jython – uruchamia programy w Pythonie na wirtualnej maszynie Java. Iron Python – uruchamia programy w Pythonie w środowsku .NET. PyPy – szybsze działanie, ale brak kompatybilności z niektórymi elementami języka. Różnią się m. in.: szybkością wykonywania konkretnych operacji dostępnymi bibliotekami Wprowadzenie do programowania w języku Python Co można zrobić za pomocą Pythona? Przykładowe biblioteki: django – web application framework scipy – obliczenia naukowe nltk – przetwarzanie języka naturalnego pyQT – aplikacje okienkowe Przykłady programów napisanych w pythonie: BitTorrent OpenERP Dropbox Ubuntu software center Wprowadzenie do programowania w języku Python Korzystanie z Pythona korzystanie z interpretera na bieżąco pisanie kodu w pliku Wprowadzenie do programowania w języku Python Tworzenie i uruchamianie programów Dowolny edytor tekstowy Standardowo kodowanie - UTF-8, może być ASCII pliki z rozszerzeniem .py lub .pyw (aplikacje okienkowe) Uruchamianie: w konsoli - python hello.py lub tylko nazwa pliku w przypadku zawarcia w pliku linii shebang # !/ usr / bin / python print ( " Hello world ! " ) 1 2 ./hello shebang.py Wprowadzenie do programowania w języku Python Programowanie na zajęciach na zajęciach korzystamy z systemu Linux edytor: zalecany gedit podczas pracy w domu, w przypadku korzystania z systemu Windows, polecamy notepad++ Ważne! kodowanie znaków: UTF-8 wcięcia: każdy tabulator to cztery spacje Wprowadzenie do programowania w języku Python Standard ASCII Przewiduje użycie jednego bajtu na znak Poszczególne liczby, które można wpisać w bajt są interpretowane jako znaki Obsługuje podstawowy zestaw znaków (litery, cyfry, podstawowe znaki matematyczne itp.) Nie obsługuje alfabetów niełacińskich lub zawierających dodatkowe znaki (polski, hiszpański, chiński itp.) Wprowadzenie do programowania w języku Python Problem stron kodowych Możliwy do użycia w ramach jednego bajtu zakres liczb podzielono na dwa podzakresy - 0-127 i 128-255 Liczbom z drugiego podzakresu można przyporządkować znaki z alfabetów np. polskiego (ogonki) czy niemieckiego (umlauty) Każde takie przyporządkowanie to inna strona kodowa. Powstało ich wiele (dla Polski np. windows-1250 i iso-8859-2) problem chińskiego i podobnych nie rozwiązany Wprowadzenie do programowania w języku Python Unicode Przedsięwzięcie skatalogowania wszystkich (!) znaków używanych w jakimkolwiek języku w jakimkolwiek czasie i różnych innych znaków użytych w piśmie Każdy symbol ma przyporządkowany identyfikator - to obejmuje Unicode (tabela ok 100 tys. symboli) Identyfikatory trzeba przetłumaczyć na zapis w bajtach - zakodować Różne kodowania: UTF-7,UTF-8,UTF-16,UTF-32 różnią się ilością bajtów przewidzianych do reprezentacji pojedynczego znaku Wprowadzenie do programowania w języku Python Uwagi o kodowaniu plików Strona kodowa użyta do kodowania plików nie jest oznaczana w jakikolwiek sposób w pliku tekstowym! Edytor (notepad i inne) używa ustawień domyślnych - dla MS Windows - windows-1250 (cp1250) dla j. polskiego, Linux - iso lub UTF-8 (częstsze) Zalecane - UTF-8! Zawsze i do wszystkich zastosowań na wszystkich systemach. Windows (od Vista) wewnętrznie pracuje na UTF-8 i obsługuje je bez problemów. Używać edytora tekstowego który umożliwia ustalenie kodowania pliku! Wprowadzenie do programowania w języku Python Typy danych Liczby całkowite - int Nieograniczonej długości (długie wolniej działają) - pamięć granicą Ciągi tekstowe - str Unicode - dowolne znaki Ujęte w cudzysłów podwójny lub pojedynczy Wprowadzenie do programowania w języku Python Dostęp do elementów ciągu tekstowego ‘‘Trudne czasy’’[7] ‘‘muflon’’[0] ‘‘Trudne czasy’’[0:4] działa dla każdej sekwencji Wprowadzenie do programowania w języku Python Konwersje int(‘‘45’’) int(‘‘ 45 ’’) - toleruje spacje str(912) w przypadku niemożności konwersji - wyjątek można zaprojektować własny typ danych, który będzie obsługiwał konwersję Wprowadzenie do programowania w języku Python Identyfikatory Identyfikator - nazwa referencji (“zmienna”) Reguły bez spacji zaczyna się literą lub podkreśleniem (uwaga - podkreślenia raczej zastrzeżone do specjalnych zadań) może zawierać cyfry wielkość liter ma znaczenie Wprowadzenie do programowania w języku Python Dynamiczna kontrola typu Python ustala typ obiektu w trakcie wykonania programu, nie trzeba go deklarować. Ten typ jest niezmienny. Referencja do obiektu akceptuje obiekt dowolnego typu i można w każdym momencie przypisać jej obiekt innego typu. a = 7 a = a + 1 a = " kura " 1 2 3 funkcja type() zwraca typ obiektu print (a , type ( a )) 1 Wprowadzenie do programowania w języku Python Standardowe wejście print ( " Jak masz na imie ? " ) imie = input () print ( " Czesc " , imie ) 1 2 3 ./input.py Wprowadzenie do programowania w języku Python Zadanie na rozgrzewkę – formularz Program zadaje kolejno następujące pytania (w nawiasach znajdują się nazwy zmiennych): 1 Podaj imię: (imie) 2 Podaj nazwisko: (nazwisko) 3 Rok studiów: (rok) 4 Specjalność: (specjalnosc) 5 Miasto rodzinne: (miasto) Zainteresowania: (zainteresowania) 6 Wypisanie na ekranie frazy: Student nazywa się (imie) (nazwisko) i jest na (rok) roku studiów, na specjalności (specjalnosc). Jego miasto rodzinne to (miasto), a jego zainteresowania obracają się wokół takich tematów jak: (zainteresowania). Wprowadzenie do programowania w języku Python Warunek Najprostszy warunek w Pythonie if 5 > 0: print ( " Piec jest wieksze od zera " ) print ( " Koniec programu " ) ./if.py Na co zwracamy uwagę: dwukropek po warunku wcięcie w linijkach po warunku sygnalizuje zasięg warunku (który fragment kodu będzie wywołany warunkowo) Wprowadzenie do programowania w języku Python 1 2 3 Prosta pętla Pętla for: for i in range (0 ,6): print ( i ) 1 2 ./for.py Na co zwracamy uwagę: dwukropek po definicji pętli wcięcie w linijkach wskazuje który fragment kodu wykonywany jest w pętli proszę przetestować: co robi funkcja range? Wprowadzenie do programowania w języku Python Zadanie 1 – licznik użytkownik wprowadza 5 wyrazów (po każdym wciska Enter) cel: liczymy, ile z tych wyrazów zaczynało się od wielkiej litery Przykładowe wejście: OJEJKU Jacek bINGO Ciastko czkawka 1 2 3 4 5 ./zad1 input.txt Przykładowe wyjście: 3 1 ./zad1 output.txt Podpowiedź na kolejnej stronie :) Wprowadzenie do programowania w języku Python Zadanie 1 – podpowiedź Przeanalizuj co robią następujące linie: print ( str . lower ( " Aaa " )) print ( str . lower ( " AAA " )) print ( str . lower ( " aaa " )) 1 2 3 ./lower.py Przy rozwiązaniu zadania wykorzystaj: funkcję str.lower() dostęp do elementu sekwencji pętlę warunek Wprowadzenie do programowania w języku Python Zadanie 2 – Weryfikacja numeru PESEL 1 użytkownik wprowadza numer PESEL 2 sprawdzamy, czy zgadza się ostatnia cyfra 3 jeśli ostatnia cyfra jest prawidłowa program ma zwrócić 1 4 jeśli nie - program ma zwrócić 0 Zakładamy, że numer ma prawidłową długość (11 znaków). Regułę poprawności numeru proszę odszukać w Sieci. Przykładowe wejście: 97082123152 1 Przykładowe wyjście: 0 1 Wprowadzenie do programowania w języku Python Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekurencja) Uniwersytet Ekonomiczny w Poznaniu 11 marca 2014 Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Obsługa wyjątku polecenia objęte pakietem try zostaną wykonane jeżeli w czasie ich wykonania nastąpi błąd rodzaju wskazanego przez jedną z klauzul except to: nastąpi przerwanie wykonania programu w linii, która spowodowała błąd kontrola zostanie przekazana do właściwego pakietu obsługi pozostałe polecenia w pakiecie try nie zostaną wykonane jeżeli nie nastąpi błąd, bloki except zostaną pominięte jeżeli nastąpi błąd w pakiecie except lub powstanie błąd nie obsługiwany przez żaden z except to: interpreter przekazuje wyjątek do zewnętrznego zasięgu (funkcji wywołującej daną funkcję) przekazywanie postępuje “w górę” aż do złapania wyjątku lub opuszczenia programu Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Przykład # !/ usr / bin / env python3 try : text = " test5 " i = int ( text ) print ( " i wynosi " ,i ) except ValueError as ex1 : print ( " konwersja " , text , " do i sie nie powiodla " ) 1 2 3 4 5 6 7 ./wyjatek.py Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure EAFP: Easier to ask for forgiveness than permission. Zalecany styl kodowania w Pythonie (ale np. w Javie już nie. . . dlaczego?). Lepiej tak: try : 1 el = elements [ key ] # do sth except IndexError as e : # do sth else 2 3 4 5 A nie tak: if len ( elements ) > key : el = elements [ key ] # do sth else : # do sth else 1 2 3 4 5 Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Operatory arytmetyczne Standardowe: +,-,*,/ dzielenie daje liczbę z przecinkiem! Operatory rozszerzone: +=,-=,*=,/= Uwaga: liczby w Pythonie to obiekty niezmienne, zatem a=a-1 utworzy nowy obiekt i przypisze go do a Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Przeciążone operatory dla list Operator + i += są przeciążone dla ciągów znaków (str) imie = " Jan " imie += " Kowalski " 1 2 Uwaga - powstaje nowy ciąg znaków (str jest niezmienny) Dla list + powoduje dodanie do listy ziarna =[ " sezam " ," slonecznik " ] ziarna +=[ " dynia " ] 1 2 Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Przeciążone operatory - uwagi Operand po prawej stronie += musi być iterowalny (w przypadku list) ziarna +=5 # error ! ziarna +=[5] # OK 1 2 Można dodawać do siebie listy ziarna +=[3 ,4 ,6 , " mak " ] 1 Uwaga: ciąg znaków jest iterowalny więc dodanie go może przynieść nieoczekiwany efekt: ziarna += " siemie " 1 [ ’ sezam ’ , ’ slonecznik ’ , ’ dynia ’ ,5 ,3 ,4 ,6 , ’ mak ’ , ’s ’ , ’i 2 ’ , ’e ’ , ziarna +=[ " siemie " ] 3 Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Tworzenie i wywoływanie funkcji bloki instrukcji można ujmować w funkcje def nazwaFunkcji ( argument , argument2 ): pakiet 1 2 argumenty są opcjonalne wartość zwracana domyślnie to None, chyba że funkcja zwróci wartość przy pomocy polecenia return def działa jak operator przypisania - powoduje utworzenie obiektu funkcji i przypisanie go do referencji o wskazanej nazwie funkcje jako obiekty mogą być przechowywane w kolekcjach, przekazywane jako argumenty do innych funkcji Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Przykład funkcji def pobierzLiczbe ( msg ): while True : try : line = input ( msg ) i = int ( line ) return i except ValueError as err : print ( err ) 1 2 3 4 5 6 7 8 funkcja pobiera liczbę jeżeli błąd to wraca do ponownego wykonania pętli, jeżeli bez błędów - zwraca liczbę wywołanie: wiek = pobierzLiczbe ( " Podaj swoj wiek " ) 1 Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Zadanie na rozgrzewkę. . . Zaimplementuj funkcję policz, która przyjmuje na wejściu dwa argumenty: lista, zawierający listę elementów, które zostaną policzone, dzialanie, zawierający funkcję obliczającą wartość na podstawie dwóch elementów. Przykładowym wynikiem wywołania funkcji policz dla listy trzech elementów powina być wartość, którą można przedstawić jako dzialanie(dzialanie(lista[0], lista[1]), lista[2]) . Inny przykład: dla definicji funkcji def suma(a, b): return a+b, wynikiem wywołania policz([1,2,3,4,5,6], suma) powinna być suma wszystkich elementów (1+2+3+4+5+6). Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Zadanie na rozgrzewkę. . . c.d. Zaimplementuj działanie na mnożenie, zastosuj je w wywołaniu funkcji policz. Zaimplementuj sumę w taki sposób, żeby w liście mogły znaleźć się dowolne wartości, a te, które nie będą liczbami, będą ignorowane. Przykładowo wywołanie dzialanie([1,‘‘a’’,-3,‘‘ 2 ’’], suma ignorowanie) powinno zwrócić 0. Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Rekurencja Przykład: definicja ciągu arytmetycznego: 1 a0 = 10 2 b=7 3 an+1 = an + b czyli w Pythonie: def a ( n ): if n == 0: return 10 else : return 7 + a ( n - 1) 1 2 3 4 5 albo: def a ( n ): return 10 if n == 0 else 7 + a ( n - 1) 1 Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Zadanie na rozgrzewkę. . . c.d. Zaimplementuj funkcję zliczającą n wyrazów ciągu arytmetycznego. Dlaczego w tym wypadku zastosowanie funkcji rekurencyjnej na n-ty wyraz ciągu jest niewskazane? Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Moduły Moduł to plik Pythona zawierający klasy i funkcje Można zaimportować moduł aby używać funkcji (dostęp przy pomocy kropki) import sys print ( sys . argv ) 1 2 Python posiada bogatą bibliotekę gotowych modułów Przykład: import random x = random . randint (1 ,16) y = random . choice ([ " jablko " ," gruszka " ," banan " ]) 1 2 3 moduły standardowe zaczynają się małymi literami, własne można nazywać dużymi (dla odróżnienia) konwencja: importy na początku pliku sugerowana kolejność importowania: standardowe, zewn., własne Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Zadanie 1 n Oblicz symbol Newtona, zdefiniowany jako k = n! k!(n−k)! Na wejściu dwie liczby oddzielone spacją (n i k), np.: 6 4 1 Na wyjściu obliczony symbol Newtona, np.: 15 1 Uwaga! Proszę zwrócić uwagę, czy na wyjściu zwracana jest liczba całkowita, tj. np. 15, a nie 15.0. W drugim przypadku może być błąd przy sprawdzaniu. Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Zadanie 2 Oblicz, na ile sposobów można rozmienić określoną kwotę pieniędzy, mając do dyspozycji określone nominały. Przykładowo dla nominałów [1, 2] kwotę 4 można rozmienić na 3 sposoby: 1+1+1+1 1+1+2 2+2 Wskazówka: warto użyć rekurencji. Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Zadanie 2 c.d. Wejście: W pierwszej linii podana jest kwota. W drugiej linii podane są nominały (jako liczby oddzielone spacjami). Nominały są zawsze posortowane rosnąco (!). Przykładowe wejście: 6 1 2 3 1 2 Wyjście: Liczba reprezentująca, ile jest sposobów rozmienienia pieniędzy. Przykładowe wyjście: 7 1 Wprowadzenie do programowania w języku Python (wyjątki, funkcje, rekure Listy składane Zbiory Słowniki Uniwersytet Ekonomiczny w Poznaniu 18 marca 2014 Listy składaneZbiorySłowniki Listy składane tworzenie listy pętlą for przestepne =[] for rok in range (1900 ,1940): if ( rok % 4 ==0 and rok % 100 !=0) or ( rok % 400 == 0): przestepne . append ( rok ) 1 2 3 4 5 lista składana - [element for element in iteracja] lata = [ y for y in range (1900 ,1940)] 1 lista składana z warunkiem przestepne = [ rok for rok in range (1900 ,1940) if ( rok % 4 ==0 and rok % 100 !=0) or ( rok % 400 == 0)] Listy składaneZbiorySłowniki 1 2 3 Przykłady list składanych W matematyce często opisujemy zbiory w taki sposób: S = {x 2 |x ∈ {0, ..., 9}} V = {2i |i ∈< 0, 13) ∧ i ∈ N} M = {x|x ∈ S ∧ x parzyste} W Pythonie w naturalny sposób można wyrazić to tak: S = [ x **2 for x in range (10)] V = [2** i for i in range (13)] M = [ x for x in S if x % 2 == 0] Listy składaneZbiorySłowniki 1 2 3 Przykłady list składanych Liczby pierwsze to takie,... które nie są niepierwsze (nie są wielokrotnością innej liczby niż 1) npr =[ j for i in range (2 ,8) for j in range ( i *2 ,50 , i )] 1 pr = [ x for x in range (2 , 50) if x not in npr ] 2 Listy składaneZbiorySłowniki Przykłady list składanych Przykład ze słowami: words = ’ The quick brown fox jumps ’. split () stuff =[[ w . upper () , w . lower () , len ( w )] for w in words ] Listy składaneZbiorySłowniki 1 2 Zbiór - set obsługuje in, len, iterację zbiory modyfikowalne - set, niemutowalne - frozenset dodane do zbioru mogą być tylko typy które dają hash tzn. float,frozenset,int,str,tuple typy mutowalne nie mogą być dodawane do zbioru bo ich hash byłby zmienny (dict,list,set) S = {7 , ‘ ‘ welon ’ ’ ,( ‘ ‘ a ’ ’ ,1) , frozenset ({3 ,6 ,8})} 1 pusty zbiór - tylko przez funkcję set() zbiory nie przechowują duplikatów. Trick na usunięcie duplikatów z listy x = list ( set ( x )) 1 Listy składaneZbiorySłowniki Operatory i funkcje dla zbiorów suma set ( ‘ ‘ pecan ’ ’) | set ( ‘ ‘ pie ’ ’) 1 iloczyn set ( ‘ ‘ pecan ’ ’) & set ( ‘ ‘ pie ’ ’) 1 różnica set ( ‘ ‘ pecan ’ ’) - set ( ‘ ‘ pie ’ ’) 1 różnica symetryczna set ( ‘ ‘ pecan ’ ’) ^ set ( ‘ ‘ pie ’ ’) Listy składaneZbiorySłowniki 1 Operatory i funkcje dla zbiorów powyższe operatory i funkcje aktualizujące im odpowiadające tworzą kopie. Są wersje aktualizujące lewy argument funkcje isdisjoint, pop, remove, update, add, clear, copy zbiory można tworzyć przez zbiór składany Listy składaneZbiorySłowniki Frozenset tworzenie - tylko przez funkcję frozenset() obsługuje z API zbioru tylko funkcje nie zmieniające zbioru Listy składaneZbiorySłowniki Słownik Słownik albo mapa (dictionary, map) to kolekcja par klucz - wartość obsługuje in, len() oraz iterację w Pythonie 3.0 jest dict oraz collections.defaultdict - słownik z wartościami domyślnymi słownik jest kolekcją nieuporządkowaną tak jak zbiór jako klucze mogą służyć tylko wartości hashowalne (tak jak przy zbiorach - float, frozenset, int, str, tuple) wartości mogą być dowolne słownik jest modyfikowalny można porównywać słowniki operatorami == i != Listy składaneZbiorySłowniki Słownik - tworzenie d = dict ({ ’ id ’ :1948 , ’ nazwa ’: ’ Zmywarka ’ , 1 ’ rozmiar ’ :3}) 2 d2 = dict ([( ’ id ’ ,1948) , ( ’ nazwa ’ , ’ Zmywarka ’) , 3 ( ’ rozmiar ’ ,3)]) 4 d3 = dict ( zip (( ’ id ’ , ’ nazwa ’ , ’ rozmiar ’) , 5 (1948 , ’ Zmywarka ’ ,3))) 6 d4 = { ’ id ’ :1948 , ’ nazwa ’: ’ Zmywarka ’ , ’ rozmiar ’ :3}7 d2 tworzy słownik z kolekcji par d3 używa funkcji zip która zwraca listę krotek odpowiednio sparowanych Listy składaneZbiorySłowniki Słownik - wykorzystanie można odwoływać się do elementów słownika po kluczu d1 [ ’ nazwa ’] 1 jeżeli nie ma klucza to wyjątek KeyError można wstawiać do słownika d [ ’x ’ ]=234 1 usuwanie - del - uwaga na wyjątek KeyError del d [ ’x ’] 1 słownik obsługuje funkcje clear, copy, fromkeys, get, items, k eys, pop, popitem, setdefault, update, values Listy składaneZbiorySłowniki Iteracja po słowniku - po parach for klucz , wartosc in d . items (): print ( klucz , wartosc ) 1 for element in d . items (): print ( element [0] , element [1]) 1 Listy składaneZbiorySłowniki 2 2 Iteracja po kluczach i wartościach for klucz in d : print ( klucz ) 1 for klucz in d . keys (): print ( klucz ) 1 for w in d . values (): print ( w ) 1 2 2 2 Listy składaneZbiorySłowniki Widoki keys, values, items to widoki na słownik widok to niemutowalna sekwencja umożliwiająca iterację widok zostanie zaktualizowany w przypadku aktualizacji słownika na widokach można wykonywać operacje jak na zbiorach - suma, iloczyn, różnica, różnica symetryczna d . fromkeys ( ’ ABCD ’ ,3) s = set ( ’ ACX ’) dopasowania = d . keys () & s Listy składaneZbiorySłowniki 1 2 3 Słowniki składane Słownik obsługuje podobnie jak lista i zbiór składanie { klucz : wartosc for klucz , wartosc in iteracja if warunek 1 } wielkosci = { nazwa : os . path . getsize ( nazwa ) for nazwa 2 in os . listdir ( ’. ’) if os . path . isfile ( nazwa )} 3 odwracanie słownika - uwaga na TypeError przy mutowalnych wartościach odwrocony = { v : k for k , v in d . items ()} Listy składaneZbiorySłowniki 1 Słownik domyślny Słownik domyślny nigdy nie zgłasza KeyError jeżeli nie ma klucza, który jest wykorzystany w danej linii to zostanie wygenerowany wpis w słowniku z pustą lub domyślną wartością przy tworzeniu słownika domyślnego podaje się funkcję fabryczną funkcję , która zwraca obiekt domyślny określonego typu words = collections . defaultdict ( int ) 1 uwaga - tutaj int jest referencją do funkcji! (funkcja jest w Pythonie obiektem) words [ word ]+=1 1 powyższy kod nie zgłosi wyjątku nawet jeżeli klucz word nie istnieje zostanie utworzony wpis o wartości 0 i zwiększony o 1 Listy składaneZbiorySłowniki Zadanie 1 – konkurs jedzenia pączków Konkurs w tłusty czwartek: kto zje najwięcej pączków w 10 minut? Na wejściu po kolei: unikalne imiona uczestników (w jednej linii) pojedyncza linia złożona z imion uczestników w takiej kolejności w jakiej kończyli jeść kolejne pączki Na wyjściu: Lista krotek (imię uczestnika, liczba zjedzonych pączków) posortowana malejąco po liczbie zjedzonych pączków Upraszczające założenie: każdy z uczestników zjadł inną liczbę pączków Listy składaneZbiorySłowniki Zadanie 1 – przykładowe wejście i wyjście Przykładowe wejście: pawel kasia lukasz 1 pawel kasia lukasz kasia pawel lukasz pawel kasia pawel 2 Przykładowe wyjście: [( ’ pawel ’ , 4) , ( ’ kasia ’ , 3) , ( ’ lukasz ’ , 2)] Listy składaneZbiorySłowniki 1 Zadanie 2 – Indeksowanie Wejście (w kolejnych linijkach): liczba dokumentów do przetworzenia (n) n linijek z wielowyrazowymi dokumentami (1 dokument na linijkę) liczba zapytań do przetworzenia (m) m linijek z jednowyrazowymi zapytaniami Wyjście: m linijek (jedna na każde zapytanie) w każdej linijce lista zawierająca numery (indeksy) dokumentów, w których wystąpił wyraz z danego zapytania każda lista posortowana według częstości wystąpienia wyrazu z zapytania w danym dokumencie przy równej częstości powinna być zachowana kolejność wczytywania dokumentów Listy składaneZbiorySłowniki Zadanie 2 – przykład 3 Your care set up , do not pluck my care down . My care is loss of care with old care done . Your care is gain of care when new care is won . 2 care is 1 [1 , 2 , 0] [2 , 1] 1 2 3 4 5 6 7 2 Listy składaneZbiorySłowniki Zadanie 2 – dodatkowe założenia zapytania formułowane są małymi literami, ale odpowiedź powinna uwzględniać wyrazy, które w dokumentach zapisane są różną wielkością liter, np.: dokument: A Rose is a rose is a roSE zapytanie: rose występowanie: 3 razy wyrazy powinny zawierać tylko znaki alfanumeryczne (bez interpunkcyjnych), tzn. wystąpienie znaku interpunkcyjnego lub spacji, tabulatora itp. powoduje podział ciągu znaków na oddzielne wyrazy, jeśli zapytanie nie zwraca rezultatów jako wynik na zapytanie powinna być wypisana pusta lista. Listy składaneZbiorySłowniki Zadania – podpowiedź # !/ usr / bin / python3 1 2 import string 3 4 l = " aaa bbb ccc " . split () # [" aaa " ," bbb " ," ccc "] j = " ," . join ( l ) # " aaa , bbb , ccc " 5 6 7 p = string . punctuation # ciag wszystkich # znakow interpunkcyjnych s = string . whitespace # ciag wszystkich # znakow bialych 8 9 10 11 12 # jak posortowac slownik po wartosciach ? import operator test_dict = dict ({ ’a ’:1 , ’c ’ :50 , ’f ’ :17}) wynik = sorted ( test_dict . items () , key = operator . itemgetter (1)) Listy składaneZbiorySłowniki 13 14 15 16 17 Zadania – podpowiedź Jak posortować słownik malejąco po wartościach i rosnąco po kluczach? Sortujemy dwa razy: najpierw po kluczach rosnąco (w pierwszej linijce) następnie malejąco po wartościach (w drugiej linijce) Odpowiednia kolejność w kluczach zostanie zachowana. Listy składaneZbiorySłowniki Klasy Obiekty Uniwersytet Ekonomiczny w Poznaniu 24 marca 2014 KlasyObiekty Problemy programowania proceduralnego Brak możliwości nazywania elementów przy tworzeniu bardziej złożonych struktur danych, np. okrąg, punkt, itd. Przy wykorzystaniu krotki (nawet nazwanej) - brak możliwości zmiany elementu składowego. Przy wykorzystaniu listy lub słownika - brak możliwości kontrolowania wartości (np. podanie ujemnego promienia okręgu). KlasyObiekty Python, a programowanie obiektowe Python pozwala tworzyć programy proceduralne, obiektowe i funkcyjne oraz mieszać te style zależnie od potrzeb. Programy proceduralne mogą wykorzystywać obiekty, ale dopiero program tworzący klasy można nazwać obiektowym. Python jest całkowicie zorientowany obiektowo: można definiować własne klasy, dziedziczyć z własnych lub wbudowanych klas, a także tworzyć instancje zdefiniowanych przez siebie klas. KlasyObiekty Podstawowe pojęcia Klasa, typ, typ danych - synonimy, oznaczają zbiór obiektów, ich rodzaj, stanowią ”wzorzec” dla tworzenia obiektów w pamięci. s = str ( ’ abc ’) type ( s ) 1 2 Instancja, egzemplarz, obiekt - synonimy, oznaczają pojedyncze wystąpienia, obiekty danej klasy występujące w pamięci. Enkapsulacja - obiekty zawierają w sobie dane (atrybuty) definiowane przez klasy; klasy definiują funkcje (metody), które można wykonywać na obiektach. Hermetyzacja - dostęp do atrybutów obiektu powinien być pośredni (przez metody), a nie bezpośredni. Właściwości - atrybuty dostępne pozornie bezpośrednio, ale w istocie obsługiwane przez metody. KlasyObiekty Konwencje i reguły dotyczące tworzenia klas Nazwy klas w Pythonie zaczynamy dużą literą. Metody specjalne __add__() lub __len__() umieszczone w klasie pozwalają obsługiwać operator + i funkcję len() dla obiektów tej klasy. Wszystkie metody specjalne zaczynają się i kończą __. Zwykłe metody zaczynają się od małej litery. Nazwa modułu nie musi być taka sama jak nazwa klasy. KlasyObiekty Tworzenie własnej klasy class NazwaKlasy : blok_instrukcji 1 2 blok_instrukcji może być pusty - wtedy pass. Polecenie class podobnie jak def umożliwia dynamiczne tworzenie klas. Metody tworzy się przy użyciu def, z tym że do każdej metody trzeba przekazać jawnie instancję obiektu - przez referencję self. KlasyObiekty Tworzenie obiektu Tworzenie (obiektu) instancji - poprzez wywołanie klasy tak jak funkcji: n = NazwaKlasy () 1 Obiekty biorą swoje zmienne i funkcje z klas. Klasy są podstawowym schematem, według których tworzone są obiekty. KlasyObiekty Zmienne w metodach 1 Atrybuty obiektu - dostępne po odwołaniu się do instancji self.x. Zmienne lokalne - dostęp po nazwie. Zmienne klasy (statyczne) - dostęp po nazwie klasy. Zmienne globalne (modułu) - dostęp po nazwie. modulowa = ’a ’ class Testowa : z =0 def __init__ ( self , x =1): self . x = x def test ( self ): print ( self . x ) y =7 print ( y ) print ( Testowa . z ) print ( modulowa ) 1 2 3 4 5 6 7 8 9 10 11 KlasyObiekty Zmienne w metodach 2 Atrybuty obiektu - dostępne po odwołaniu się do instancji self.x. Zmienne lokalne - dostęp po nazwie. Zmienne klasy (statyczne) - dostęp po nazwie klasy. Zmienne globalne (modułu) - dostęp po nazwie. t1 = Testowa () t1 . test () 1 2 3 t2 = Testowa (3) t2 . test () 4 5 KlasyObiekty Przykład class MojaKlasa : 1 zmienna =2 2 def __init__ ( self , wartosc =1): 3 self . wartosc = wartosc 4 def mojaFunkcja ( self ): 5 wynik1 = self . wartosc ** self . zmienna 6 wynik2 = self . wartosc ** MojaKlasa . zmienna 7 print ( self . wartosc , ’ podniesiona do potegi : ’ , 8 self . zmienna , ’ daje wynik : ’ , wynik1 ) 9 print ( self . wartosc , ’ podniesiona do potegi : ’ , 10 MojaKlasa . zmienna , ’ daje wynik : ’ , wynik2 ) 11 12 liczba1 = MojaKlasa () liczba1 . mojaFunkcja () 13 14 15 liczba1 . zmienna = 4 liczba1 . mojaFunkcja () 16 17 18 liczba2 = MojaKlasa (3) liczba2 . mojaFunkcja () 19 20 KlasyObiekty Zadanie na rozgrzewkę Utworzyć klasę obiektów Statek Każdy obiekt powinien mieć następujące cechy: model, ładowność, liczba masztów, wielkość. Liczba masztów powinna być podana jako liczba (int) Ładowność powinna być wyliczana z funkcji na podstawie wielkości: jeśli ’duzy’ - ładowność: 50 jeśli ’maly’ - ładowność: 10 Utworzyć trzy nowe obiekty: statek1, statek2 i statek3. KlasyObiekty Zadanie 1 - wynagrodzenie Obliczyć wynagrodzenie pracowników. Obliczyć wysokość składek pracodawcy (na pracownika). Obliczyć łączny koszt dla pracodawcy na pracownika. Założenia: każdy pracownik powinien być obiektem klasy pracowników, program przyjmuje pierwszą wartość: liczbę pracowników (i), dla liczby pracowników (i) wczytuje imię pracownika i wynagrodzenie brutto (int) (oddzielone spacją), każdy pracownik jest wprowadzany w nowej linii, w wyniku wypisać: imię pracownika, wynagrodzenie netto (float), składki pracodawcy (float), łączny koszt na pracownika (float), każdy pracownik wypisywany jest w nowej linii, w ostatniej linii wypisać łączny koszt dla pracodawcy (wszyscy pracownicy). KlasyObiekty Zadanie 1 - wynagrodzenie Przykładowe wejście: 2 Bartek 2580 Marek 1680 1 2 3 Przykładowe wyjście: Bartek 1863.91 535.09 3115.09 Marek 1237.20 348.43 2028.43 5143.52 KlasyObiekty 1 2 3 Zadanie 1 - podpowiedzi round (i , n ) # zaokraglanie 1 2 ’ %.3 f ’ % 1.29003 # daje 1.290 Poszukać sposobu obliczania wynagrodzenia od 01.01.2014 Za koszty uzyskania przychodu przyjąć zawsze: 111.25 Każdy wynik pośredni powinien być zaokrąglany do 2 miejsc po przecinku Wypisywane wyniki powinny być sformatowane do 2. miejsca po przecinku KlasyObiekty 3 Zadanie 2 - figury Obliczyć sumę pól figur geometrycznych. Założenia: program przyjmuje pierwszą wartość: liczbę figur (i), dla liczby figur (i) wczytuje liczby (oddzielone spacją), każda figura jest wprowadzona w nowej linii; jeśli linia zawiera: jedną liczbę - jest to promień koła, dwie liczby - boki prostokąta, trzy liczby - boki trójkąta, w wyniku wypisać sumę pól wprowadzonych figur (zaokrągloną do 2 miejsc po przecinku). Dla każdej figury geometrycznej (koło, prostokąt, trójkąt) utwórz oddzielną klasę. KlasyObiekty Zadanie 2 - figury Przykładowe wejście: 5 2 4 6 3 3.5 4 8 2.1 4.14 1 2 3 4 5 6 Przykładowe wyjście: 112.3 1 KlasyObiekty Klasy Obiekty część II Uniwersytet Ekonomiczny w Poznaniu 1 kwietnia 2014 KlasyObiektyczęść II Dziedziczenie KlasyObiektyczęść II Dziedziczenie c.d. class Konto : def __init__ ( self , numer , roczna_stopa ): self . numer = numer self . roczna_stopa = roczna_stopa self . kwota = 0.0 def wplac ( self , kwota ): self . kwota += kwota 1 2 3 4 5 6 7 8 9 class KontoKapRoczna ( Konto ): def __init__ ( self , numer , roczna_stopa ): super (). __init__ ( numer , roczna_stopa ) KlasyObiektyczęść II 10 11 12 Prywatne atrybuty class Konto : 1 2 numer = 2 __numer = 1 3 4 5 def __init__ ( self , roczna_stopa ): self . numer = Konto . __numer Konto . __numer += 1 self . roczna_stopa = roczna_stopa self . kwota = 0.0 6 7 8 9 10 11 def _ _prywa tna_metoda ( self ): print ( " Nie mozna jej wywolac spoza klasy " ) KlasyObiektyczęść II 12 13 Zadanie na rozgrzewkę Zaimplementuj system bankowy zgodnie z diagramem. KlasyObiektyczęść II Zadanie na rozgrzewkę c.d. Bank: W banku zapisane są wszystkie konta. Metoda pobierz konto, to metoda prywatna, która pozwala odwołać się do obiektu konta po jego numerze. Metoda zaloz konto pozwala na założenie konta. Podana jest roczna stopa procentowa jako float (np. 0.036) oraz typ kapitalizacji (możliwe wartości: "miesieczna", "dzienna"). Metoda zwraca numer nowego konta. Metoda wplac pozwala na wpłacenie pieniędzy na konto. Metoda nastepny miesiac powoduje zaksięgowanie miesięcznych odsetek na wszystkich kontach. Metoda przelej pozwala przelać określoną kwotę z jednego konta na inne. KlasyObiektyczęść II Zadanie na rozgrzewkę c.d. Konto, KontoKapDzienna, KontoKapMiesieczna: Każde konto posiada numer, który jest generowany automatycznie. Każde konto posiada kwotę – początkowa kwota, to 0.00. Każde konto ma zdefiniowaną roczną stopę procentową. Metoda wplac pozwala na dokonanie wpłaty na konto. Wypłata z konta to podanie kwoty jako wartości ujemnej. KlasyObiektyczęść II Zadanie na rozgrzewkę c.d. Konto, KontoKapDzienna, KontoKapMiesieczna: Każde konto ma metodę nastepny miesiac, jednak implementacja tej metody różni się w zależności od tego, czy mamy do czynienia z KontoKapMiesieczna, czy z KontoKapDzienna. Metoda nastepny miesiac w klasie KontoKapMiesieczna powoduje naliczenie odsetek dla kwoty konta z wykorzystaniem kapitalizacji miesiecznej. Końcowa kwota zaokrąglana jest do 2 miejsca po przecinku. Metoda nastepny miesiac w klasie KontoKapDzienna powoduje naliczenie odsetek dla kwoty konta za cały miesiąc z wykorzystaniem kapitalizacji dziennej. Po każdym dniu kwota zaokrąglana jest do drugiego miejsca po przecinku. Przyjmujemy, że miesiąc ma 30 dni. KlasyObiektyczęść II Zadanie na rozgrzewkę c.d. bank = Bank () k1 = bank . zaloz_konto (0.02 , " dzienna " ) k2 = bank . zaloz_konto (0.02 , " miesieczna " ) print ( bank ) 1 2 3 4 5 bank . wplac ( k1 , 1000) bank . wplac ( k2 , 1000) print ( bank ) 6 7 8 9 bank . nastepny_miesiac () print ( bank ) 10 11 12 bank . przelej ( k1 , k2 , 100) print ( bank ) 13 14 KlasyObiektyczęść II Zadania domowe KlasyObiektyczęść II Zadanie 1 Zaimplementuj dodawanie książek do biblioteki (metoda dodaj egzemplarz ksiazki) W tej metodzie do biblioteki powinien być dodawany nowy Egzemplarz oraz (jeśli to konieczne) nowa Ksiazka. Na wejściu w pierwszej linijce podana jest liczba egzemplarzy książek do dodania (n), a następnie w kolejnych n linijkach egzemplarze książek podane jako ("tytul", "autor", 2014). Wskazówka: aby wczytać krotkę z egzemplarzem, użyj: eval(input()). Na wyjściu w kolejnych linijkach wypisana lista książek wraz z liczbą egzemplarzy, też w postaci krotek (posortowana po tytułach). KlasyObiektyczęść II Zadanie 1 c.d. Przykładowe wejście: 5 1 ( " Chatka Puchatka " , " Alan Alexander Milne " , 2014)2 ( " Quo Vadis " , " Henryk Sienkiewicz " , 2010) 3 ( " Chatka Puchatka " , " Alan Alexander Milne " , 1998)4 ( " Pan Tadeusz " , " Adam Mickiewicz " , 2003) 5 ( " Quo Vadis " , " Henryk Sienkiewicz " , 2010) 6 Przykładowe wyjście: ( ’ Chatka Puchatka ’ , ’ Alan Alexander Milne ’ , 2) ( ’ Pan Tadeusz ’ , ’ Adam Mickiewicz ’ , 1) ( ’ Quo Vadis ’ , ’ Henryk Sienkiewicz ’ , 2) KlasyObiektyczęść II 1 2 3 Zadanie 2 Zaimplementuj wypożyczanie książek przez czytelnika. KlasyObiektyczęść II Zadanie 2 – wejście Na wejściu w pierwszej linijce podana jest liczba akcji (n). W kolejnych linijkach podane są akcje: dodaj – oznacza dodanie książki do biblioteki, zapisane np. jako: ("dodaj", "Pan Tadeusz", "Adam Mickiewicz", 2000) wypozycz – oznacza wypożyczenie egzemplarza ksiazki przez czytelnika (można wypożyczyć tylko jeden egzemplarz tej samej książki; przyjmij też, że domyślnie można wypożyczyć maksymalnie 3 egzemplarze różnych książek). Akcja może być zapisana jako: ("wypozycz", "Jakub Dzikowski", "Quo Vadis") oddaj – oznacza zwrócenie konkretnego egzemplarza książki do biblioteki. Może być zapisane jako: ("oddaj", "Jakub Dzikowski", "Quo Vadis") KlasyObiektyczęść II Zadanie 2 – wyjście Na wyjściu w kolejnych linijkach wypisane wartości logiczne True lub False, oznaczające powodzenie lub niepowodzenie wykonania konkretnej akcji. dodaj – akcja zawsze powinna kończyć się powodzeniem. wypozycz – może się skończyć niepowodzeniem, jeśli czytelnik wypożyczył za dużo egzemplarzy książki lub chciał wypożyczyć drugi egzemplarz tej samej książki, lub nie było już dostępnych egzemplarzy książki. oddaj – może się skończyć niepowodzeniem, jeśli czytelnik nie ma takiej książki. KlasyObiektyczęść II Zadanie 2 – przykładowe wejście 12 1 ( " dodaj " , " Pan Tadeusz " , " Adam Mickiewicz " , 2000) 2 ( " dodaj " , " Quo Vadis " , " Henryk Sienkiewicz " , 2010) 3 ( " dodaj " , " Chatka Puchatka " , " Alan Alexander Milne " , 4 1998) ( " dodaj " , " Pan Tadeusz " , " Adam Mickiewicz " , 2000) 5 ( " dodaj " , " Chatka Puchatka " , " Alan Alexander Milne " , 6 2014) ( " wypozycz " , " Bartek Perkowski " , " Pan Tadeusz " ) 7 ( " wypozycz " , " Bartek Perkowski " , " Pan Tadeusz " ) 8 ( " wypozycz " , " Jacek Malyszko " , " Quo Vadis " ) 9 ( " wypozycz " , " Bartek Perkowski " , " Quo Vadis " ) 10 ( " oddaj " , " Jacek Malyszko " , " Quo Vadis " ) 11 ( " wypozycz " , " Bartek Perkowski " , " Quo Vadis " ) 12 ( " oddaj " , " Jacek Malyszko " , " Quo Vadis " ) 13 KlasyObiektyczęść II Zadanie 2 – przykładowe wyjście True True True True True True False True False True True False 1 2 3 4 5 6 7 8 9 10 11 12 KlasyObiektyczęść II Zadanie 2 – wskazówki Warto, aby Biblioteka zapamiętywała obiekty czytelników (podobnie jak książki). Można w tym celu napisać metodę prywatną, która będzie pobierać czytelnika o podanym nazwisku (jeśli istnieje już zapisany taki obiekt czytelnika), a jeśli nie istnieje, to dodawać nowy obiekt czytelnika i zwracać ten obikt. Warto, żeby w obiekcie czytelnika były zapamiętane obiekty wypożyczonych egzemplarzy i sprawdzanie części poprawnych warunków na wypożyczenie i oddanie było oddelegowane na obiekty czytelnika. Pamiętaj, że zgodnie z podejściem Pythona, często „Easier to ask for forgiveness than permission” (EAFP). Korzystaj z try: ... except KeyError: .... KlasyObiektyczęść II Dokumentacja kodu Tworzenie modułów Uniwersytet Ekonomiczny w Poznaniu 9 kwietnia 2014 Dokumentacja kodu Tworzenie modułów Adnotacje funkcji Można opatrzyć sygnaturę funkcji adnotacjami korzystając ze składni: def nazwa_funkcji ( arg1 : ad1 , arg2 : ad2 ) -> ad3 : pass 1 2 Python dodaje te adnotacje do atrybutu __annotations__, który jest słownikiem - atrybutem w funkcji jako adnotację możemy użyć: stringa typu danych (w tym zdefiniowanych klas) Sam Python nie przywiązuje żadnej roli do tych adnotacji, ale można je wykorzystać wprost, np. do kontroli typów Dokumentacja kodu Tworzenie modułów Adnotacje funkcji Jak działa poniższa funkcja? def mnozenie ( a : int , b : int ) -> int : 1 print ( mnozenie . __annotations__ ) 2 anns = mnozenie . __annotations__ 3 if type ( a ) != anns [ ’a ’] or type ( b ) != anns [ ’b ’ ]: 4 raise Exception ( ’ Bledne typy parametrow ! ’) 5 else : 6 return a * b 7 8 print ( mnozenie ( ’ ojej ’ ,2)) 9 Dokumentacja kodu Tworzenie modułów Adnotacje funkcji w miejsce adnotacji można wstawić po prostu łańcuchy znaków opisujące co ma się znaleźć w danym parametrze class Biblioteka : def wypozycz ( self , nazw : ’ nazwisko czytelnika ’ , tyt : ’ tytul ksiazki ’ ): pass Dokumentacja kodu Tworzenie modułów 1 2 3 4 Ciągi dokumentujące (docstrings) Ciągi dokumentujące są to łańcuchy znaków umieszczane na początku dokumentowanej struktury programistycznej: modułu klasy funkcji umieszczane są w specjalnym atrybucie __doc__ zainstancjonowanego obiektu istnieją secjalne formaty do przygotowywania ciągów dokumentujących, np. reStructuredText, z których można korzystać w większych projektach Dokumentacja kodu Tworzenie modułów Ciągi dokumentujące – funkcje aby dołączyć dokumentację do funkcji wystarczy po linii definicji umieścić ją w komentarzu wielolinijkowym dokumentacja funkcji może mieć np. następującą strukturę: krótki opis w jednej linii linię odstępu dłuższy opis opis parametrów funkcji przykłady wykorzystania - w trybie interaktywnym interpretera Dokumentacja kodu Tworzenie modułów Ciągi dokumentujące + tworzenie modułów Stwórz plik o następującej zawartości: import math 1 2 def heron (a ,b , c ): """ Oblicza pole trojkata wg wzoru Herona 3 4 5 a ,b , c dlugosci bokow trojkata >> heron (3 ,4 ,5) 6.0 """ s = ( a + b + c )/2 return math . sqrt ( s * (s -1) * (s - b ) * (s - c )) 6 7 8 9 10 11 12 if __name__ == ’ __main__ ’: print ( heron . __doc__ ) print ( heron (3 ,4 ,5)) 13 14 15 Dokumentacja kodu Tworzenie modułów Ciągi dokumentujące + tworzenie modułów zapisz plik na dysku (np. pod nazwą heron_modul.py) otwórz interpreter pythona zaimportuj go jako moduł (import heron_modul) wykonaj na module funkcję help() oblicz pole trójkąta o bokach za pomocą funkcji zdefiniowanej w module Co robi następująca linijka? if __name__ == ’__main__’: Dokumentacja kodu Tworzenie modułów Zadanie – odległość węzłów w drzewie w zadaniu operujemy na drzewie, czyli strukturze reprezentującej hierarchię danych: drzewo składa się z węzłów i krawędzi każdy węzeł ma nad sobą dokładnie jeden inny węzeł, za wyjątkiem węzła – korzenia (który nie ma nad sobą węzłów) każdy węzeł może mieć dowolną liczbę pod-węzłów na moodle znajduje się plik 07_zad_szkielet.py z dokumentacją, która może pomóc w rozwiązaniu zadania Dokumentacja kodu Tworzenie modułów Dokumentacja kodu Tworzenie modułów Zadanie 1 – wejście i wyjście Na wejściu otrzymujemy: Listę krotek, gdzie każda krotka składa się z dwóch elementów: nad-węzła i pod-węzła. W liście może być wiele takich krotek i reprezentują one nasze drzewo. Kolejność krotek w liście nie powinna mieć znaczenia. Listę wybranych wierzchołków drzewa. Na wyjściu, dla każdego zadanego wierzchołka w osobnym wierszu wypisujemy jego wszystkie nad-węzły aż do korzenia drzewa, rozpoczynając od zadanego węzła (nad-węzeł stopnia zerowego). Dokumentacja kodu Tworzenie modułów Zadanie 1 – przykładowe wejście i wyjście Wejście: [( ’F ’ , ’B ’) , ( ’B ’ , ’A ’) , ( ’B ’ , ’D ’) , ( ’D ’ , ’C ’) , ( ’D ’ , ’E ’) , ( ’F ’ , ’G ’) , ( ’G ’ , ’I ’) , ( ’I ’ , ’H ’ )] [ ’B ’ , ’F ’ , ’C ’] 1 2 3 Wyjście: [ ’B ’ , ’F ’] [ ’F ’] [ ’C ’ , ’D ’ , ’B ’ , ’F ’] 1 2 3 Dane odpowiadają drzewu przedstawionemu na ilustracji na wcześniejszych slajdach Dokumentacja kodu Tworzenie modułów Zadanie 2 – odległość węzłów w drzewie (miara prosta) Zdefiniujemy miarę prostą liczenia odległości pomiędzy węzłami w drzewie jako liczbę krawędzi, które trzeba pokonać, aby dojść od jednego do drugiego węzła Możemy ją obliczyć poprzez znalezienie najniższego wspólnego nadwęzła dla obu wierzchołków, a następnie określenia i zsumowania jego odległości od ich obu Poniżej, odległość między węzłami A i C wynosi 3 (najnizszym wspólnym nadwęzłem jest B, jego odległość od A wynosi 1 a od C wynosi 2) Dokumentacja kodu Tworzenie modułów Zadanie 2 – wejście i wyjście Na wejściu otrzymujemy: Listę krotek reprezentującej drzewo, analogicznie do zad. 1. Listę krotek, reprezentujących zapytania; każda krotka składa się z trzech elementów: dwóch nazw wierzchołków i nazwy metryki wykorzystywanej do mierzenia odległości: prosta – miara prosta, opisana na poprzednim slajdzie potęgowa – opisana w komentarzu do metody licz odleglosc klasy MiaraPotegowa Mamy za zadanie obliczyć odległość pomiędzy wierzchołkami za pomocą zadanej miary. Na wyjściu wypisujemy listę liczb, które reprezentują odległości pomiędzy węzłami. Dokumentacja kodu Tworzenie modułów Zadanie 2 – przykładowe wejście i wyjście Dane odpowiadają rysunkowi drzewa na wcześniejszych zlajdach. Przykładowe wejście [( ’F ’ , ’B ’) , ( ’B ’ , ’A ’) , ( ’B ’ , ’D ’) , ( ’D ’ , ’C ’) , ( ’D ’ , ’E ’) , ( ’F ’ , ’G ’) , ( ’G ’ , ’I ’) , ( ’I ’ , ’H ’ )] [( ’ prosta ’ , ’C ’ , ’G ’) , ( ’ prosta ’ , ’G ’ , ’C ’) , ( ’ potegowa ’ , ’G ’ , ’C ’ )] 1 2 3 4 Przykładowe wyjście [4 , 4 , 8] 1 Dokumentacja kodu Tworzenie modułów Wczytywanie danych Praca z CSV Uniwersytet Ekonomiczny w Poznaniu 23 kwietnia 2014 Wczytywanie danych Praca z CSV Wczytywanie danych input() pobiera dane wprowadzone z klawiatury można przekazywać dane wejściowe bez ręcznego wpisywania przygotowanie plików wejściowych zastępujących dane wprowadzane ręcznie Wczytywanie danych Praca z CSV Wczytywanie danych c.d. input() Plik input.txt ( " Chatka Puchatka " , " Alan Alexander Milne " , 1998)1 ( " Pan Tadeusz " , " Adam Mickiewicz " , 2003) 2 ( " Quo Vadis " , " Henryk Sienkiewicz " , 2010) 3 Plik jako dane wejściowe python3 moj_skrypt.py < input.txt Wczytywanie danych Praca z CSV Parsowanie argumentów import sys 1 2 for arg in sys . argv : print ( arg ) 3 4 argumenty linii poleceń przekazywane są do programu sys.argv jest listą elementów pierwszy element - nazwa uruchomionego skryptu Wczytywanie danych Praca z CSV Parsowanie argumentów c.d. getopt(arg, short, long) Funkcja przyjmuje trzy parametry: arg - listę argumentów short - ciąg znaków zawierający jedno-znakowe flagi long - listę dłuższych flag, będących odpowiednikami krótszych Wczytywanie danych Praca z CSV Parsowanie argumentów - przykład import getopt , sys 1 2 try : 3 opts , args = getopt . getopt ( sys . argv [1:] , " ho : " , [ " help " , " output = " ]) except getopt . GetoptError as err : print ( err ) 4 5 6 7 8 for op , ar in opts : if op in ( ’ -h ’ , ’ -- help ’ ): print ( help ()) elif op in ( ’ -o ’ , ’ -- output ’ ): print ( ar ) python3 moj_skrypt.py -h python3 moj_skrypt.py -o tekst Wczytywanie danych Praca z CSV 9 10 11 12 13 Moduł CSV moduł csv umożliwia odczyt oraz zapis do liku CSV CSV - pliki przechowujące tabele z danymi, zawierające rekordy podzielone na pola brak ogólnego standardu co do separatorów pól Wczytywanie danych Praca z CSV Odczyt pliku CSV import csv 1 2 plik_csv = open ( nazwa_pliku , tryb ) csv . reader ( plik_csv , dialect = ’ ’ , format_params ) open() otwiera plik nazwa_pliku - wskazuje nazwę pliku do otwarcia tryb - definiuje jak będzie używany plik (read mode, write mode, append mode) reader() tworzy nowy obiekt o podanych parametrach: plik_csv - wskazuje na plik dialect - określa format pliku CSV (opcjonalnie) format_params - określa specyficzne parametry formatowania Wczytywanie danych Praca z CSV 3 4 Praca z plikiem CSV import csv 1 2 plik_csv = open ( ’ sample . csv ’ , ’r ’) czytaj = csv . reader ( plik_csv ) 3 4 5 for i , rekord in enumerate ( czytaj ): if i == 0: naglowek = rekord else : for j , pole in enumerate ( rekord ): print ( naglowek [ j ] , ’: ’ , pole ) print ( ’ ’) 6 7 8 9 10 11 12 13 plik_csv . close () 14 Wczytywanie danych Praca z CSV Zapis do CSV import csv 1 2 plik_csv = open ( ’ output . csv ’ , ’w ’ , encoding = ’utf -8 ’) 3 zapisz = csv . writer ( plik_csv , dialect = ’ unix ’) 4 5 dane = [ ( ’ Imie ’ , ’ Nazwisko ’ , ’ Firma ’ , ’ Stanowisko ’) , ( ’ Bartek ’ , ’ Perkowski ’ , ’ UEP ’ , ’ Informatyk ’) , ( ’ Jan ’ , ’ Nowak ’ , ’ ABC ’ , ’ Sprzedawca ’) , ( ’ Jakub ’ , ’ Dzikowski ’ , ’ UEP ’ , ’ Administrator ’) , ( ’ Jacek ’ , ’ Malyszko ’ , ’ UEP ’ , ’ Administrator ’) , ( ’ Marek ’ , ’ Kowalski ’ , ’ ABC ’ , ’ Informatyk ’) ] 6 7 8 9 10 11 12 13 14 for element in dane : zapisz . writerow ( element ) 15 16 17 plik_csv . close () 18 Wczytywanie danych Praca z CSV Zapis do CSV c.d. zapisz = csv.writer(plik_csv,delimiter=’|’) zapisz = csv.writer(plik_csv,delimiter=’\t’) zapisz = csv.writer(plik_csv,dialect=’excel’) zapisz = csv.writer(plik_csv,dialect=’unix’) Wczytywanie danych Praca z CSV CSV - tworzenie dialektu import csv csv . register_dialect ( ’ mojDialekt ’ , delimiter = ’| ’ , quoting = csv . QUOTE_ALL ) 1 2 3 4 plik_csv = open ( ’ output . csv ’ , ’w ’) zapisz = csv . writer ( plik_csv , dialect = ’ mojDialekt ’) 5 6 7 dane = [ ( ’ Imie ’ , ’ Nazwisko ’ , ’ Firma ’ , ’ Stanowisko ’) , ( ’ Bartek ’ , ’ Perkowski ’ , ’ UEP ’ , ’ Informatyk ’) ] 8 9 10 11 12 for element in dane : zapisz . writerow ( element ) 13 14 15 plik_csv . close () 16 Wczytywanie danych Praca z CSV Wstęp do zadań W pliku CSV posiadamy dane dotyczące połączeń telefonicznych. Każdy wiersz opisuje jedno połączenie (pierwszy wiersz w pliku jest nagłówkiem). W każdym wierszu znajdują się kolejno: Nadawca (From) - unikalny identyfikator liczbowy Odbiorca (To) - unikalna identyfikator liczbowy Data i godzina (Datetime) - w postaci RRRRMMDD HHMM Czas trwania (Duration(seconds)) - liczba sekund Nadajnik (Cell Tower) - unikalny identyfikator liczbowy Nadawca i odbiorca jest reprezentowany przez ten sam identyfikator. Wczytywanie danych Praca z CSV Zadanie 1 - połączenia W pliku wejściowym podane są następujące informacje: w pierwszej linii znak oddzielający kolejne pola w rekordzie, np. ; w drugiej linii ścieżka dostępu do pliku zwierającego dane o połączeniach. Na wyjściu powinna znajdować się informacja: w pierwszym wierszu identyfikator użytkownika, który wykonał największą liczbę połączeń, oraz łączny czas tych połączeń w drugim wierszu identyfikator użytkownika, który odebrał największą liczbę połączeń, oraz łączny czas tych połączeń w przypadku równej liczby połączeń, powinien zostać wypisany użytkownik o niższym identyfikatorze Wczytywanie danych Praca z CSV Zadanie 1 - połączenia Przykładowe wejście: , ./ phoneCalls . csv 1 2 Przykładowe wyjście: 226: 5387 5: 16797 1 2 Na moodle przykładowy plik do testowania: phoneCalls.csv Wczytywanie danych Praca z CSV Zadanie 2 - statystyki Plik wejściowy taki sam jak w Zadaniu 1. Do Zadania 2. wykorzystaj skrypt z Zadania 1. Wynikiem zadania powinno być: w pierwszym wierszu lista 10 identyfikatorów najczęściej dzwoniących w drugim wierszu lista 10 identyfikatorów najczęściej odbierających w trzecim wierszu najczęściej używany nadajnik wraz łączną liczbą połączeń, do których został użyty w czwartym wierszu dla najczęściej dzwoniącego wypisać jego atrybuty: średni czas połączenia wychodzącego (zaokrąglony do 2 miejsc po przecinku) oraz średnia liczba połączeń wychodzących (zaokrąglona do 2 miejsca po przecinku) identyfikatory powinny być posortowane malejąco wg liczby połączeń, a w przypadku równej liczby połączeń od najniższego Wczytywanie danych Praca z CSV Zadanie 2 - statystyki Przykładowe wyjście: [ ’ 226 ’ , ’ 47 ’ , ’ 75 ’ , ’ 152 ’ , ’ 158 ’ , ’ 176 ’ , ’ 297 ’ , ’ 359 ’ , ’ 363 ’ , ’ 375 ’] [ ’5 ’ , ’0 ’ , ’2 ’ , ’ 13 ’ , ’ 172 ’ , ’1 ’ , ’ 15 ’ , ’ 32 ’ , ’ 23 ’ , ’ 42 ’] ( ’ 15 ’ , 54) 1077.4 0.71 Wczytywanie danych Praca z CSV 1 2 3 4 5 6 Biblioteka część II Uniwersytet Ekonomiczny w Poznaniu 25 kwietnia 2014 Bibliotekaczęść II Zadanie Dla podanej wcześniej definicji biblioteki, zaimplementuj 1 Dodawanie historii przeprowadzania akcji na egzemplarzach: dodania wypożyczenia oddania 2 Naliczanie kar bibliotecznych. Na Moodle dostępne jest rozwiązanie poprzedniego zadania z biblioteki, które można zmodyfikować zgodnie z instrukcjami do tego zadania. Bibliotekaczęść II Zadanie 1 Podczas dodawania egzemplarzy książki, podawana jest także data jego dodania do biblioteki, jako krotka, np. (2013, 12, 23). Wyświetl zestawienie egzemplarzy książek, które zostały dodane później, niż podana data (czyli zestawienie nowszych egzemplarzy). Wejście: W pierwszej linijce podawana liczba książek do dodania (n). W kolejnych n linijkach podane egzemplarze książki. W ostatniej linijce podana data (jako krotka). Wyjście: analogiczne zestawienie, jak w poprzednim zadaniu z biblioteki. Bibliotekaczęść II Zadanie 1 c.d. Przykładowe wejście: 5 1 ( " Chatka Puchatka " , " Alan A . Milne " , 2014 , (2014 , 4 , 10)) 2 ( " Quo Vadis " , " Henryk Sienkiewicz " , 2010 , (2014 , 1 , 15)) 3 ( " Chatka Puchatka " , " Alan A . Milne " , 1998 , (2013 , 12 , 31))4 ( " Pan Tadeusz " , " Adam Mickiewicz " , 2003 , (2012 , 1 , 1)) 5 ( " Quo Vadis " , " Henryk Sienkiewicz " , 2010 , (2014 , 1 , 15)) 6 (2013 , 12 , 31) 7 Przykładowe wyjście: ( ’ Chatka Puchatka ’ , ’ Alan A . Milne ’ , 1) ( ’ Quo Vadis ’ , ’ Henryk Sienkiewicz ’ , 2) Bibliotekaczęść II 1 2 Zadanie 2 Zaimplementuj naliczanie kar bibliotecznych. Reguły naliczania kar: Każdy egzemplarz ma limit wypożyczenia 7 dni. Za każdy dzień przekroczenia limitu naliczana jest kara w wysokości 50 groszy. Wszystkie kary sumują się. Na wejściu podane są akcje z datami ich wykonania; w ostatniej linijce bieżąca (końcowa) data. Akcje podane są chronologicznie. Na wyjściu: Najpierw wyświetlone są wartości logiczne, opisujące poprawność wykonania operacji (analogicznie do poprzedniego zadania z biblioteki). Następnie wyświetlone jest zestawienie kar wszystkich czytelników (czytelnicy sortowani są rosnąco po nazwiskach). Jeśli czytelnik nie ma kar, nie jest wyświetlany. Nie trzeba zaokrąglać kar, ani wyświetlać ich w specjalny sposób. Krotki z karami wyświetlane są jedna pod drugą, podobnie jak w przypadku wyświetlania zestawienia egzemplarzy. Bibliotekaczęść II Zadanie 2 c.d. Przykładowe wejście 11 ( " dodaj " ," Pan Tadeusz " ," A . Mickiewicz " ,2000 ,(2014 ,1 ,1)) ( " dodaj " ," Quo Vadis " ," H . Sienkiewicz " ,2010 ,(2014 ,1 ,1)) ( " dodaj " ," Chatka Puchatka " ," A . A . Milne " ,1998 ,(2014 ,1 ,1)) ( " dodaj " ," Pan Tadeusz " ," A . Mickiewicz " ,2000 ,(2014 ,1 ,1)) ( " dodaj " ," Chatka Puchatka " ," A . A . Milne " ,2014 ,(2014 ,1 ,1)) ( " wypozycz " ," Bartek Perkowski " ," Pan Tadeusz " ,(2014 ,1 ,25)) ( " wypozycz " ," Bartek Perkowski " ," Pan Tadeusz " ,(2014 ,2 ,2)) ( " wypozycz " ," Jacek Malyszko " ," Quo Vadis " ,(2014 ,2 ,12)) ( " oddaj " ," Jacek Malyszko " ," Quo Vadis " ,(2014 ,2 ,17)) ( " oddaj " ," Bartek Perkowski " ," Pan Tadeusz " ,(2014 ,2 ,25)) ( " wypozycz " ," Bartek Perkowski " ," Quo Vadis " ,(2014 ,3 ,5)) (2014 ,3 ,13) Bibliotekaczęść II 1 2 3 4 5 6 7 8 9 10 11 12 13 Zadanie 2 c.d. Przykładowe wyjście: True True True True True True False True True True True ( ’ Bartek Perkowski ’ , 12.5) 1 2 3 4 5 6 7 8 9 10 11 12 Bibliotekaczęść II Wskazówki Warto wykorzystać bibliotekę do obsługi dat. Dokumentacja: https://docs.python.org/3.0/library/datetime.html Tutorial: http://pymotw.com/2/datetime/ (tutorial jest dla Pythona 2, ale moduł działa podobnie dla Pythona 3) Przykład wykorzystania w konsoli Pythona 3: 1 >>> import datetime >>> d1 = datetime . date (2008 , 3 , 12) >>> print ( d1 ) 2008 -03 -12 >>> d2 = datetime . date (2009 , 1 , 21) >>> ( d1 - d2 ). days -315 Bibliotekaczęść II 2 3 4 5 6 7 8 Sposób rozwiązania zadania 1 Ponieważ w trzech grupach zadanie pierwsze rozwiązywane było podczas zajęć, na kilku kolejnych slajdach zaprezentowano krok po kroku przykładowy sposób rozwiązania tego zadania. Opis powinien być bardzo przydatny studentom, którzy nie mieli tych zajęć (godziny rektorskie) oraz dla tych, którzy nie zrobili tego podczas zajęć. Bibliotekaczęść II Krok 1. Wczytywanie danych W pliku z rozwiązaniem poprzedniego zadania, który znajduje się na Moodle, są następujące linijki: biblioteka = Biblioteka () 1 for i in range ( int ( input ())): 2 t = eval ( input ()) 3 if t [0] == " dodaj " : 4 print ( biblioteka . d o d a j _ e g z e m p l a r z _ k s i a z k i ( t [1] , t [2] 5 , t [3] elif t [0] == " wypozycz " : 6 print ( biblioteka . wypozycz ( t [1] , t [2])) 7 elif t [0] == " oddaj " : 8 print ( biblioteka . oddaj ( t [1] , t [2])) 9 Kod ten jest przystosowany do zadania nr. 2 z poprzedniej biblioteki. Najpierw tworzona jest instancja biblioteki, a następnie wczytywane są wszystkie krotki z opisywanymi akcjami, po czym określone akcje są wykonywane i wyświetlany jest ich rezultat (czy się powiodły, czy nie). Bibliotekaczęść II Krok 1. Wczytywanie danych Linie od 4 do 9 z poprzedniego slajdu najlepiej zakomentować. Przydadzą się później w zadaniu z naliczaniem kar bibliotecznych (najlepiej wykorzystać działający kod z zadania 1 w zadaniu 2 – tam też będzie ważne zapisywanie egzemplarzy z datą dodania). Natomiast po liniach 1 – 3 należy: 1 2 3 dodać egzemplarz książki z datą dodania, wczytać datę, dla której generowany będzie raport, wyświetlić raport nowszych egzemplarzy, niż podana data. Zostanie to szczegółowo omówione na kolejnych slajdach. Bibliotekaczęść II Krok 2. Dodawanie egzemplarza książki Za dodanie egzemplarza do biblioteki służy metoda: d o d a j _ e g z e m p l a r z _ k s i a z k i ( self , tytul , autor , rok_wydania ) 1 Najlepiej rozszerzyć tę metodę o nowy parametr z datą: d o d a j _ e g z e m p l a r z _ k s i a z k i ( self , tytul , autor , rok_wydania , 1data ) Zatem dodanie egzemplarza książki na podstawie krotki t mogłoby wyglądać w następujący sposób (podane są dwie alternatywne formy): biblioteka . d o d a j _ e g z e m p l a r z _ k s i a z k i ( t [0] , t [1] , t [2] , t [3]) 1 biblioteka . d o d a j _ e g z e m p l a r z _ k s i a z k i (* t ) 2 Gwiazdka przed krotką powoduje „rozpakowanie” krotki, czyli w przypadku powyższego wywołania, jeśli krotka t ma cztery elementy, to wywołanie *t w metodzie dodaj egzemplarz ksiazki spowoduje podanie tych czterech kolejnych elementów jako cztery kolejne argumenty w metodzie. Bibliotekaczęść II Krok 2a. Modyfikacja dodaj egzemplarz ksiazki Istniejąca metoda dodaj egzemplarz ksiazki działa w następujący sposób: 1 Do zmiennej ksiazka przypisywana jest książka, która wcześniej została dodana do „bazy” – słownika z książkami. 2 Jeśli ta instrukcja się nie powiedzie – czyli jeśli nie można odnaleźć książki o tym tytule w „bazie”, to znaczy, że należy dodać nową książkę. Zatem w kolejnych krokach tworzony jest nowy obiekt książki i przypisywany do zmiennej ksiazka. Następnie ten obiekt jest dodawany do „bazy”. 3 Każda książka posiada listę egzemplarzy. W kolejnej linijce do takiej listy dodawany jest nowy, utworzony obiekt egzemplarza książki. 4 Zwracane jest True, oznaczające, że akcja się powiodła. W tym wypadku modyfikacja powinna polegać na dodaniu parametru data do deklaracji metody oraz na przekazaniu tego parametru do konstruktora egzemplarza. Zatem utworzenie obiektu egzemplarza powinno wyglądać następująco: Egzemplarz ( rok_wydania , ksiazka , data ) Bibliotekaczęść II 1 Krok 2b. Modyfikacja konstruktora egzemplarza W konstruktorze egzemplarza należy dodać nowy parametr: data i przypisać go jako atrybut nowego obiektu. To jest też dobre miejsce, żeby skorzystać z rekomendowanej biblioteki do obsługi dat. Zatem na początku pliku należy zaimportować odpowiedni moduł: import datetime 1 Z kolei samo utworzenie atrybutu i przypisanie daty mogłoby wyglądać następująco: self . data_dodania = datetime . date (* data ) 1 Ponieważ data występuje jako krotka z trzema elementami, np. (2013, 4, 23), to użycie gwiazdki przed datą spowoduje, że zostanie wywołane coś podobnego do: datetime.date(2013, 4, 23). Czyli krotka zostanie „rozpakowana”. Po wykonaniu tych kroków nasza biblioteka będzie zapamiętywać daty dodania egzemplarza. Bibliotekaczęść II Krok 3. Wczytanie daty Aby wczytać datę, wystarczy wywołać np.: data = eval ( input ()) 1 Data ta następnie zostanie użyta przy wyświetleniu raportu nowszych książek. Bibliotekaczęść II Krok 4. Wyświetlenie raportu nowszych egzemplarzy Aktualnie w bibliotece znajduje się metoda raport ksiazek: def raport_ ksiazek ( self ): 1 lista = [] 2 for k in self . __ksiazki . values (): 3 lista . append (( k . tytul , k . autor , len ( k . egzemplarze ))) 4 return sorted ( lista , key = lambda t : t [0]) 5 W tej metodzie najpierw tworzona jest pusta lista, a następnie do tej listy dodawane są krotki zawierające tytuł książki, autora książki i liczbę egzemplarzy. Na końcu zwracana lest lista krotek posortowana po pierwszych elementach krotek (czyli po tytułach). Dobrym sposobem byłoby zmodyfikowanie tej metody, żeby zwrcała raport nie wszystkich egzemplarzy, ale raport egzemplarzy nowszych niż określona data. Bibliotekaczęść II Krok 4a. Modyfikacja metody raport ksiazek Aby zmodyfikować metodę raport ksiazek należy: 1 Dodać nowy argument do metody, reprezentujący datę o nazwie, przykładowo, data. 2 Zamiast liczby wszystkich egzemplarzy interesuje nas liczba wszystkich egzemplarzy nowszych niż określona data. Zatem najlepiej zamiast wywołania k.egzemplarze, wywołać nową metodę (którą oczywiście należy dopisać do klasy Ksiazka). Warto także wynik wywołania tej metody zapisać w nowej zmiennej, np.: nowsze = k . e g z e m p l a r z e _ n o w s z e _ n i z ( data ) 3 1 Dodatkowo, jeśli liczba egzemplarzy nowszych wyniesie 0, nie umieszczamy tej pozycji w raporcie, zatem do zmiennej lista krotki powinny być dodawane tylko wtedy, gdy len(nowsze) > 0 Bibliotekaczęść II Krok 4b. Dodanie metody egzemplarze nowsze niz Do klasy Ksiazka powinna zostać dodana metoda egzemplarze nowsze niz o następującej deklaracji: def e g z e m p l a r z e _ n o w s z e _ n i z ( self , data ): 1 Metoda powinna zwracać tylko te egzemplarze, które są nowsze niż podana data, co można osiągnąć w dwóch linijkach, stosując listy składane: data = datetime . date (* data ) 1 return [ e for e in self . egzemplarze if e . data_dodania > data 2 ] Tym samym metoda raport ksiazek jest już w stanie generować zestawienie egzemplarzy książek nowszych niż podana data. Ostatnim krokiem jest ich prawidłowe wyświetlenie. Bibliotekaczęść II Krok 4c. Wyświetlenie krotek z raportu Metoda raport ksiazek zwracała posortowaną listę krotek. Na wyjściu jednak nie jest oczekiwane wyświetlenie całej listy w jednej linijce, lecz wyświetlenie kolejnych krotek w nowych linijkach. Tym samym należy przeiterować wszystkie krotki z tej listy wyświetlić je w kolejnych wywołaniach funkcji print: for x in biblioteka . raport_ ksiazek ( data ): print ( x ) Po wykonaniu tych kroków zgodnie z instrukcjami pierwsze zadanie powinno przejść testy na sprawdzarce. Bibliotekaczęść II 1 2 Obiektowość cz. 3. Generatory Uniwersytet Ekonomiczny w Poznaniu 12 maja 2014 Obiektowość cz. 3. Generatory Uwagi o pamięci, wskaźnikach, referencjach i zmiennych Rzut okiem na pamięć (przykłady w języku C) Zmienna - nazwane miejsce w pamięci Wskaźnik - specyficzna zmienna, która przechowuje adres; adres do innych danych; w językach Pascal, C, C++ odróżnia się od zmiennych zachowaniem i wyglądem Referencja - prawie to samo co wskaźnik (robi to samo, ale wygląda tak samo jak zmienna), nie może być pusta (nie wskazywać na coś) Nazwa referencji to inaczej identyfikator Obiektowość cz. 3. Generatory Zmienne, referencje Python nie posiada zmiennych - tylko referencje Zmienna - nazwane miejsce w pamięci, komórka w której można zmieniać wartość Referencja - odniesienie do miejsca w pamięci, komórka w pamięci w której jest adres innego obszaru pamięci Referencje i zmienne mogą być zmieniane x = " niebieski " y = " zielony " z = x 1 2 3 Operator = łączy obiekt z referencją Obiektowość cz. 3. Generatory Atrybuty obiektów atrybuty obiektu znajdują się w specjalnym słowniku __dict__ atrybuty można dodawać do obiektu w dowolnym momencie class A : def __init__ ( self ): self . atr1 = 1 1 2 3 4 obiekt_a = A () obiekt_a . atr2 = 15 print ( obiekt_a . __dict__ ) obiekt_a . __dict__ [ ’ atr3 ’] = 8 print ( obiekt_a . atr3 ) ./atrybuty.py Obiektowość cz. 3. Generatory 5 6 7 8 9 Atrybuty obiektów 2 Aby uniemożliwić dodawanie / usuwanie atrybutów trzeba założyć klasę z krotką o nazwie __slots__ zawierającą nazwy wszystkich atrybutów >>> class P : ... __slots__ = ( " x " ) ... def __init__ ( self ): ... self . x =10 ... 1 2 3 4 5 słownik __dict__ nie jest wtedy tworzony i nie można dodawać ani usuwać atrybutów obiekty ze slots działają szybciej niż z dict (nieznacznie) Obiektowość cz. 3. Generatory Abstrakcyjne klasy bazowe AKB to klasa, która nie może być użyta do tworzenia obiektów AKB zawiera przynajmniej jedną właściwość lub metodę abstrakcyjną (bez implementacji) AKB używa się aby z nich dziedziczyć AKB zwykle “obiecują” wsparcie dla pewnych metod w klasach potomnych i grupują klasy potomne w abstrakcyjne koncepcje AKB musi mieć metaklasę abc.ABCMeta Obiektowość cz. 3. Generatory Metaklasy Metaklasa jest dla klasy tym czym klasa dla instancji Klasa służy jako szablon do tworzenia instancji Metaklasa służy jako szablon do tworzenia klas Metaklasa musi dziedziczyć po metaklasie bazowej (type) lub jednej z jej podklas Metaklasa może ingerować w skład klasy Zastosowania: wyjątkowe sytuacje, np. tworzenie frameworków (Django itd.) Do przeczytania dla chętnych http://stackoverflow.com/a/6581949 Obiektowość cz. 3. Generatory AKB – zdefiniowanie klasy abstrakcyjnej import abc 1 2 class PluginBase ( metaclass = abc . ABCMeta ): 3 4 @abc . abstractmethod def load ( self , input ): """ Pobiera dane . """ return 5 6 7 8 9 @abc . abstractmethod def save ( self , output , data ): """ Zapisuje dane . """ return ./akb1.py Źródło: http://pymotw.com/2/abc/ Obiektowość cz. 3. Generatory 10 11 12 13 AKB – klasa implementująca class S u b c l a s s I m p le men ta ti on ( PluginBase ): 1 2 def load ( self , input ): return input . read () 3 4 5 def save ( self , output , data ): return output . write ( data ) 6 7 8 if __name__ == ’ __main__ ’: 9 print ( ’ Podklasa : ’ , 10 issubclass ( SubclassImplementation , PluginBase 11 )) akb2.py Źródło: http://pymotw.com/2/abc/ Obiektowość cz. 3. Generatory Wartościowanie leniwe Definicja Wartościowanie leniwe (ang. lazy evaluation) to strategia wyznaczania wartości wyrażenia tylko wtedy, kiedy jest to potrzebne (na żądanie). Obiektowość cz. 3. Generatory Generatory Funkcja generatora to funkcja z wyrażeniem yield zamiast return Wartością zwrotną jest iterator Z iteratora pozyskiwane są kolejno wartości przy pomocy wywołania niejawnego funkcji __next__() na iteratorze podczas każdego wywołania __next__() zwracana jest wartość wygenerowana przez yield działanie generatora kończy użycie return lub normalne zakończenie funkcji przykład: chcemy przejść przez litery od podanej początkowej do końcowej. Można to zrobić albo tworząc ich listę albo używając generatora d = listaLiter ( ’a ’ , ’m ’) for litera in litery ( ’a ’ , ’m ’ ): print ( litera ) Obiektowość cz. 3. Generatory 1 2 3 Funkcja generatora a zwykła funkcja # buduje i zwraca liste def litery (a , z ): wynik = [] while ord ( a ) < ord ( z ): wynik . append ( a ) a = chr ( ord ( a ) + 1) return wynik 1 # zwraca kazda wartosc na zadanie def litery (a , z ): while ord ( a ) < ord ( z ): yield a a = chr ( ord ( a ) + 1) 1 2 3 4 5 6 7 Obiektowość cz. 3. Generatory 2 3 4 5 yield Jak zrozumieć funkcję z poleceniem yield? 1 dodaj linijkę result = [] na początku funkcji, 2 zamień yield expr na result.append(expr), 3 wstaw linię return result na końcu funkcji. Otrzymamy analogiczny wynik (choć nie w postaci generatora), jednak program w wielu przypadkach będzie wymagał więcej pamięci i będzie działał wolniej. Obiektowość cz. 3. Generatory Generatory Znane nam przykłady generatorów to: range csv.reader Obiektowość cz. 3. Generatory Generatory c.d. Jeżeli chcemy uzyskać wszystkie elementy z generatora to można przekazać go do funkcji list() lub tuple() wszystkie = list ( litery ( ’a ’ , ’m ’ )) 1 generator wykonuje działanie kiedy jest potrzebna następna wartość, a nie “z góry” generator może generować nieskończoną sekwencję wartości def cwiartki ( nastepna_cwiartka =0.0): while True : yield nastepna_cwiartka nas tepna_cwiartka += 0.25 wynik =[] for x in cw (): wynik . append ( x ) if x >=2.0: break Obiektowość cz. 3. Generatory 1 2 3 4 5 6 7 8 9 Korzyści z generatorów – funkcja range Porównanie pamięci zużytej do obliczenia sumy liczb. >>> >>> >>> >>> >>> >>> >>> >>> >>> import resource mem_usg = resource . getrusage m0 = mem_usg ( resource . RUSAGE_SELF ). ru_maxrss a = sum ( range (10000000)) m1 = mem_usg ( resource . RUSAGE_SELF ). ru_maxrss b = sum ( list ( range (10000000))) m2 = mem_usg ( resource . RUSAGE_SELF ). ru_maxrss print ( m1 / m0 ) print ( m2 / m1 ) Wnioski? Obiektowość cz. 3. Generatory 1 2 3 4 5 6 7 8 9 Wyrażenia generatora Zamiast funkcji generatora można użyć wyrażenia generatora Wyrażenie takie to pętla for, ujęta w nawias okrągły (podobne do list składanych, różni się nawiasem) Wyrażenie takie daje iterator, podobnie jak funkcja generatora def ele m e n t y _ p o s o rtowane ( d ): for klucz in sorted ( d ): yield klucz , d [ klucz ] 1 2 3 # wyrazenie generatora 1 def ele m e n t y _ p o s o rtowane ( d ): 2 return (( klucz , d [ klucz ]) for klucz in sorted ( d )) 3 Obiektowość cz. 3. Generatory Zadanie 1 Napisz własną implementację funkcji range (o innej nazwie, np. my_range). Funkcja ma otrzymywać na wejściu zawsze dokładnie dwa argumenty: początek sekwencji koniec sekwencji Krokiem jest zawsze 1. Uwaga Wykorzystanie wbudowanej funkcji range będzie traktowane jako plagiat. Przygotowanie rozwiązania bez wykorzystania generatora to 0 punktów. Obiektowość cz. 3. Generatory Zadanie 1 c.d. Na wejściu otrzymujemy: n – w pierwszej linijce liczbę mówiącą o tym ile wierszy będziemy przetwarzać n krotek, gdzie zerowym elementem jest początek sekwencji, a pierwszym koniec sekwencji Wyjściem jest n linijek, gdzie każda linijka ma być sumą liczb z odpowiedniej sekwencji. Obiektowość cz. 3. Generatory Zadanie 1 c.d. Przykładowe wejście: 2 (0 , 1000000) (717 , 18000) 1 2 3 Przykładowe wyjście: 499999500000 161734314 1 2 Uwaga! Test będzie sprawdzał pamięć wykorzystaną przez program. Jeśli program przekroczy zdefiniowany limit, sprawdzarka zwróci błąd. Obiektowość cz. 3. Generatory Zadanie 2 Napisz własną funkcję odpowiedzialną za przetwarzanie plików CSV korzystając z generatora i instrukcji yield. Uwaga! Wykorzystanie wbudowanego modułu csv będzie traktowane jako plagiat. Brak wykorzystania generatora i instrukcji yield – brak punktów za zadanie. Obiektowość cz. 3. Generatory Zadanie 2 c.d. Wejście jest analogiczne do zadań z Tematu 9 na moodle. Wyjściem ma być suma sekund wszystkich połączeń w pliku. Obiektowość cz. 3. Generatory Zadanie 2 Przykładowe wejście: | ./ phoneCalls . csv 1 2 ./zad1 in.txt Przykładowe wyjście: 449242 Plik CSV taki sam jak w zajęciach Temat 9 na moodle. Obiektowość cz. 3. Generatory Systemy kontroli wersji Git Uniwersytet Ekonomiczny w Poznaniu 13 maja 2014 Systemy kontroli wersji Git Wstęp System kontroli wersji pozwala na śledzenie zmian, np. w kodzie źródłowym umożliwia łączenie zmian dokonywanych w wielku plikach, przez wiele osób, w różnym czasie. Podział systemów kontroli wersji wg: architektury oprogramowania licencjonowania oprogramowania sposobu oceny zmian Systemy kontroli wersji Git Rodzaje systemów wg architektury lokalne - zapis danych jedynie na komputerze lokalnym (np. Revision Control System) scentralizowane - wykorzystujące architekturę klient-serwer (np. Subversion) rozproszone - wykorzystujące architekturę Peer-to-Peer (np. Git) Systemy kontroli wersji Git Git rozproszony system kontroli wersji twórca: Linus Torvalds po co Git? Umożliwia pracę wielu osób nad jednym projektem, niezależnie od siebie. Przechowuje wszystkie wersje modyfikowanych plików, wspiera proces scalania plików bez utraty danych oraz umożliwia przywracanie wcześniejszych wersji plików. wybrane projekty korzystające z Gita: jądro Linuksa, GNOME, KDE, GIMP, Wine... a także... Facebook Systemy kontroli wersji Git Git - podstawowe pojęcia Terminal (Command line) - program służący do wykonywania poleceń Gita. Repozytorium (Repository) - miejsce / katalog, w którym przechowywane są projekty (skrypty, pliki tekstowe, obrazki...). Może być umieszczone na komputerze lokalnym lub online, np. na GitHubie. Kontrola wersji (Version control) - podstawowy cel Gita. Przechowuje wszystkie wersje modyfikowanych plików (tzw. ”snapshot”), dzięki czemu żadne elementy nie zostają utracone ani nadpisane. Przekazanie (Commit) - podstawowe polecenie, które tworzy ”snapshot” wprowadzanych zmian. Przesłanie informacji o zmianach do lokalnego repozytorium. Gałąź (Branch) - praca wielu osób nad tym samym projektem jest możliwa dzięki tworzeniu gałęzi, w których znajdują się tylko zmiany dokonane przez daną osobę. Gałęzie są następnie scalane z głównym katalogiem projektu. Systemy kontroli wersji Git Schemat działań Gita Źródło: http: // pl. wikibooks. org/ wiki/ Plik: Git_ data_ flow_ simplified. svg Systemy kontroli wersji Git Git - polecenia Każde polecenie Git zaczynamy od wyrazu ”git” git init - inicjuje nowe repozytorium Gita git config - służy do konfiguracji git help - lista poleceń; można też wywołać dla wybranego polecenia, np. git help init git status - pozwala sprawdzić stan repozytorium, zawartych plików, wprowadzonych zmian git add - nie dodaje plików do repozytorium, wskazuje co ma zostać uwzględnione przy przekazaniu git commit - polecenie tworzące ”snapshot” w lokalnym repozytorium Systemy kontroli wersji Git Git - polecenia c.d. Każde polecenie Git zaczynamy od wyrazu ”git” git branch - przy pracy z wieloma osobami, tworzenie własnej gałęzi do wprowadzania tylko swoich zmian git checkout - umożliwia przejście w repozytorium do wybranej gałęzi git merge - scalenie zmian wprowadzanych w danej gałęzi z głównym repozytorium widocznym dla wszystkich git push - pracując na repozytorium lokalnym, ładuje wszystkie zmiany na repozytorium online git pull - pobiera aktualną wersję repozytorium online do lokalnego repozytorium Systemy kontroli wersji Git GitHub Jedno z największych miejsc w sieci, umożliwiające przechowywanie projektów i równoczesną pracę wielu użytkowników przy jednym projekcie. Działa podobnie jak sieć społecznościowa. W przeciwieństwie do wielu sieci społecznościowych / miejsc udostępnianych online: wszystkie załadowane dane pozostają własnością użytkownika. Dostarcza graficzny interfejs do zarządzania Gitem. https://github.com Systemy kontroli wersji Git Git - zadanie Zadanie obejmuje wszystkie polecenia wykonywane podczas zajęć. Maksymalna liczba punktów: 5. Link do własnego repozytorium GitHub proszę wprowadzić na Moodle w temacie 11, np. https://github.com/bartekperkowski/IOrepo Systemy kontroli wersji Git Początek pracy Założenie konta na https://github.com Instalacja Gita na komputerze lokalnym (dostępne pod Linux, Windows, MacOS) dla Windows i MacOS: http://git-scm.com/downloads dla Linux (np. Ubuntu): sudo apt-get install git Systemy kontroli wersji Git Początek pracy c.d. Polecenie 1 Utwórz konto na stronie GitHub: https://github.com Systemy kontroli wersji Git Wstępne ustawienia Ustawienie domyślnej nazwy użytkownika; dowolna nazwa informująca kto dokonywał zmian w projekcie: git config --global user.name "Twoje imię" Ustawienie domyślnego adresu e-mail: git config --global user.email "Twój adres e-mail" Uwaga: Powyższe kroki umożliwiają skonfigurowanie konta globalnego, niezależnego od repozytorium. W celu ustawienia innego użytkownika dla wybranego repozytorium, należy przejść do wybranego katalogu i wywołać te same polecenia bez argumentu ”–global”. Systemy kontroli wersji Git Wstępne ustawienia c.d. Polecenie 2 Z wykorzystaniem Terminala (Wiersza poleceń), ustaw w systemie konto globalne z wybraną nazwą użytkownika oraz adresem e-mail wykorzystanym przy zakładaniu konta na GitHub. Systemy kontroli wersji Git Zakładanie repozytorium https://github.com/new Systemy kontroli wersji Git Zakładanie repozytorium c.d. Polecenie 3 W systemie GitHub stwórz nowe repozytorium dla swojego projektu: https://github.com/new Systemy kontroli wersji Git Utworzenie lokalnego repozytorium Utworzenie katalogu: mkdir "Nazwa katalogu" Przejście do nowo utworzonego katalogu Zainicjowanie lokalnego repozytorium Git: git init Utworzenie pustego pliku README: touch README.txt lub cd. > README.txt Systemy kontroli wersji Git Utworzenie lokalnego repozytorium c.d. Polecenie 4 W Dokumentach utwórz nowy katalog o tej samej nazwie co repozytorium na GitHub. Zainicjuj nowy katalog jako repozytorium lokalne Git i stwórz pusty plik: README.txt. Systemy kontroli wersji Git Dodawanie i zatwierdzanie zmian Sprawdzenie stanu lokalnego repozytorium: git status Co możemy zaobserwować? Systemy kontroli wersji Git Dodawanie i zatwierdzanie zmian Sprawdzenie stanu lokalnego repozytorium: git status Co możemy zaobserwować? Aby plik był ”śledzony”: git add README.txt Aby utworzyć ”snapshot” działań, czyli przesłać plik do repozytorium lokalnego: git commit -m "Mój komentarz" Systemy kontroli wersji Git Dodawanie i zatwierdzanie zmian c.d. Polecenie 5 Przyjrzyj się aktualnemu statusowi repozytorium lokalnego i wprowadź odpowiednie zmiany, aby nowo utworzony plik znalazł się w repozytorium lokalnym. Systemy kontroli wersji Git Podłączanie repozytorium GitHub Ścieżka do repozytorium GitHub: https://github.com/bartekperkowski/IOrepo Dodanie zdalnego adresu: git remote add mojeRepo https://github.com/bartekperkowski/IOrepo.git mojeRepo - nazwa odnosząca się do repozytorium na GitHub remote - wskazuje, że mojeRepo znajduje się poza komputerem lokalnym Systemy kontroli wersji Git Podłączanie repozytorium GitHub c.d. Polecenie 6 Podłącz swoje repozytorium GitHub pod wybraną nazwą. Sprawdzenie czy do danego repozytorium lokalnego jest podłączone repozytorium online: git remote -v Systemy kontroli wersji Git Zatwierdzanie zmian w repozytorium GitHub Wysyłanie zmian do zdalnego repozytorium: git push lub git push mojeRepo master Polecenie 7 Przekaż wszystkie zmiany do zdalnego repozytorium utworzonego na GitHub. Systemy kontroli wersji Git Działanie na gałęziach - wstęp Polecenie 8 Utwórz plik kalkulator.py zawierający dowolną funkcję (można skopiować z wcześniejszych zajęć) oraz prześlij go do repozytorium na GitHub. Pracujesz nad plikiem kalkulator.py, w którym wprowadzasz własne zmiany. W trakcie pracy nad plikiem nastąpiła konieczność zmodyfikowania funkcji istniejącej w tym pliku. Utworzysz nową gałąź związaną tylko z wprowadzaną poprawką, dokonasz zmian i wrzucisz zmiany do repozytorium. Powrócisz do wcześniej wprowadzanych zmian. Systemy kontroli wersji Git Działanie na gałęziach Tworzenie i przechodzenie do nowej gałęzi: git checkout -b "Nowa gałąź" Wersja alternatywna: git branch "Nowa gałąź" git checkout "Nowa gałąź" Edycja pliku kalkulator.py Zatwierdzenie zmian w nowej gałęzi: git commit -a -m "Nowy komentarz" Parametr -a pomija polecenie git add Systemy kontroli wersji Git Działanie na gałęziach Polecenie 9 Napisz fragment nowej funkcji w pliku kalkulator.py i zatwierdź zmiany. Systemy kontroli wersji Git Działanie na gałęziach Przełączanie do głównej gałęzi: git checkout master Tworzenie nowej gałęzi na potrzeby wprowadzenia poprawki: git checkout -b "poprawka1" Edycja pliku kalkulator.py Zatwierdzenie zmian w nowej gałęzi: git commit -a -m "Poprawka funkcji" Systemy kontroli wersji Git Działanie na gałęziach Polecenie 10 Utwórz nową gałąź w repozytorium, dokonaj zmian w pliku kalkulator.py (dopisz nową, działającą funkcję) i zatwierdź zmiany. Systemy kontroli wersji Git Scalenie gałęzi Aby scalić nową gałąź z gałęzią master: git checkout master git merge poprawka1 Jaka wersja jest teraz w repozytorium na GitHub? Systemy kontroli wersji Git Scalenie gałęzi Aby scalić nową gałąź z gałęzią master: git checkout master git merge poprawka1 Jaka wersja jest teraz w repozytorium na GitHub? Konieczne przesłanie do repozytorium! Systemy kontroli wersji Git Usuwanie gałęzi Po scaleniu gałęzi, ”poprawka1” może zostać usunięta, jako że wskazuje na dokładnie to samo co ”master”. Aby usunąć gałąź z lokalnego repozytorium: git branch -d poprawka1 Systemy kontroli wersji Git Scalenie i usuwanie gałęzi Polecenie 11 Scal gałąź zawierającą poprawkę z gałęzią master, prześlij zmiany do repozytorium na GitHub i usuń gałąź z poprawką. Systemy kontroli wersji Git Scalanie gałęzi c.d. Po dokonaniu poprawek można powrócić do wcześniejszych zadań. Powrót do gałęzi wcześniej utworzonej. Edycja pliku kalkulator.py Zatwierdzenie zmian w nowej gałęzi. Scalenie gałęzi z gałęzią ”master”. Systemy kontroli wersji Git Scalenie całej pracy Polecenie 12 Dokonaj zmian w poprzedniej gałęzi, zatwierdź, scal z gałęzią ”master” i rezultat prześlij do repozytorium na GitHub. Systemy kontroli wersji Git Praca z gałęziami - przebieg procesu master V1 V2 Systemy kontroli wersji Git Praca z gałęziami - przebieg procesu master V1 V2 V3 nowa Systemy kontroli wersji Git Praca z gałęziami - przebieg procesu V1 master popr V2 V4 V3 nowa Systemy kontroli wersji Git Praca z gałęziami - przebieg procesu master popr V1 V2 V4 V3 nowa Systemy kontroli wersji Git Praca z gałęziami - przebieg procesu master V1 V2 V4 V3 V5 nowa Systemy kontroli wersji Git Praca z gałęziami - przebieg procesu master V1 V2 V4 V3 V6 V5 nowa Systemy kontroli wersji Git Usuwanie plików Usunięcie pliku z katalogu nie powoduje usunięcia z repozytorium! Aby wskazać plik do usunięcia: git rm "Przykładowy plik" Konieczne zatwierdzenie zmian w repozytorium lokalnym. Przesłanie informacji do repozytorium na GitHub Systemy kontroli wersji Git Usuwanie plików c.d. Polecenie 13 Usuń utworzony na początku zajęć plik README.txt i zatwierdź zmiany w repozytorium na GitHub. Systemy kontroli wersji Git Konflikty przy scalaniu Co to są konflikty? <<<<<<< HEAD : README . txt cos ======= cos nowego przykladowy tekst >>>>>>> nowa_galaz : README . txt 1 2 3 4 5 6 Należy dokonać zmiany poprzez usunięcie niewłaściwych elementów ręcznie. Po dokonany zmianach: git add README.txt Można wykorzystać narzędzie graficzne do rozwiązywania konfliktów: git mergetool Systemy kontroli wersji Git Praca z gałęziami - ciekawostki Wypisanie wszystkich istniejących gałęzi: git branch * oznacza aktywną gałąź Ostatni zatwierdzony zestaw zmian: git branch -v Wyświetlanie gałęzi, które zostały lub nie zostały scalone: git branch --merged oraz git branch --no-merged Usuwanie gałęzi (nie pozwoli na usunięcie jeśli zmiany nie zostały scalone): git branch -d "gałąź" Systemy kontroli wersji Git Wielowątkowość Uniwersytet Ekonomiczny w Poznaniu 20 maja 2014 Wielowątkowość Pobieranie treści URL Problem: pod określonym adresem URL znajduje się treść, którą chcemy pobrać. Rozwiązanie: korzystamy z modułu urllib.request i funkcji urlopen Przykład: from urllib . request import urlopen content = urlopen ( ’ http :// example . com ’ ). read () print ( content . decode ( ’utf -8 ’ )) Wielowątkowość 1 2 3 Pobieranie treści URL c.d. execute typical instruction fetch from L1 cache memory branch misprediction fetch from L2 cache memory Mutex lock/unlock fetch from main memory send 2K bytes over 1Gbps network read 1MB sequentially from memory fetch from new disk location (seek) read 1MB sequentially from disk send packet US to Europe and back 1/1,000,000,000 sec = 1 0.5 5 7 25 100 20,000 250,000 8,000,000 20,000,000 150 ms = 150,000,000 Źródło: http://norvig.com/21-days.html#answers Wielowątkowość ns ns ns ns ns ns ns ns ns ns ns Pobieranie treści URL c.d. Pobieranie treści przez HTTP zazwyczaj zajmuje sporo czasu... Może nie ma to dużego znaczenia przy pobieraniu jednego linka, ale jeśli jest ich kilka: from urllib . request import urlopen for i in range (10): content = urlopen ( ’ http :// example . com ’ ). read () print ( ’ Pobrano URL nr ’ , i ) Wielowątkowość 1 2 3 4 Pobieranie treści URL c.d. Limit czasu wywołania: from urllib . request import urlopen 1 2 linki = [ 3 ’ http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / a ’ , 4 ’ http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / b ’ , 5 ’ http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / c ’ , 6 ’ http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / d ’ , 7 ] 8 for link in linki : 9 try : 10 x = urlopen ( link , timeout =0.8). read () 11 print ( ’ Pobrano ’ , x . decode ( ’utf -8 ’) , ’z ’ , link 12 ) except Exception as e : 13 print ( ’ Nie udalo sie pobrac ’ , link ) 14 Wielowątkowość Konstrukcja with ... as ... plik1 = open ( ’ ala . txt ’ , ’w ’ , encoding = ’utf -8 ’) plik1 . write ( ’ Ala ma kota ’) 1 2 3 plik2 = open ( ’ ala . txt ’ , ’r ’) print ( plik2 . readlines ()) 4 5 Gdzie w tym przykładzie jest błąd? Wielowątkowość Konstrukcja with ... as ... (c.d.) with open ( ’ ala . txt ’ , ’w ’ , encoding = ’utf -8 ’) as plik1 : plik1 . write ( ’ Ala ma kota ’) 1 2 3 with open ( ’ ala . txt ’ , ’r ’) as plik2 : print ( plik2 . readlines ()) Wielowątkowość 4 5 Konstrukcja with ... as ... (c.d.) Domyślnie „zamyka” różnego rodzaju zasoby. Dzięki niej kod może być bardziej czytelny. Przydatne w korzystaniu z plików, połączeń z bazą danych, korzystaniem z wielowątkowości... Wielowątkowość Obliczenia wielowątkowe Co to są wątki? Kiedy wielowątkowe wykonywanie programu jest użyteczne? Wielowątkowość Przykład na rozgrzewkę – sleepsort Na wejściu podane w jednej linii liczby, np.: 3 2 6 4 1 8 1 Na wyjściu podane jedna pod drugą posortowane liczby, np.: 1 2 3 4 6 8 1 2 3 4 5 6 Wykorzystaj funkcję time.sleep oraz wielowątkowość Wielowątkowość Przykład na rozgrzewkę – sleepsort import threading import time 1 2 3 def wyswietl ( x ): time . sleep ( x ) print ( x ) 4 5 6 7 liczby = [ int ( x ) for x in input (). split ()] 8 9 for x in liczby : t = threading . Thread ( target = wyswietl , args =[ x ]) t . start () Wielowątkowość 10 11 12 Zadanie na rozgrzewkę Rozszerz sleepsort tak, aby na końcu wyświetlała się suma wszystkich liczb. Wielowątkowość Problemy w tym podejściu Trzeba w jakiś sposób przechwycić rezultat wywołania. Czy wyswietl może zwracać rezultat? A może zapisywać liczby w jakimś słowniku? Trzeba wprost napisać kod, który „poczeka”, aż wątki zakończą pracę. Wątek ma metodę join, która powoduje czekanie, aż wątek skończy pracę, ale czy powinniśmy się tym zajmować? Czy powinny nas interesować takie niskopoziomowe rzeczy? Te problemy są na tyle złożone w przedstawionym podejściu do wielowątkowości, że nie będziemy ich rozwiązywać. Zamiast tego pokażemy, jak je obejść, bo od Pythona 3.2 jest na to prosty sposób: moduł concurrent.futures. https://docs.python.org/3/library/concurrent.futures.html Wielowątkowość Sleepsort 2 from concurrent . futures import T h r e a d P o o l E x e c u t o r import time 1 2 3 def wyswietl ( x ): time . sleep ( x ) print ( x ) 4 5 6 7 liczby = [ int ( x ) for x in input (). split ()] 8 9 with T hr e a d P o o l E x e c u t o r ( max_workers = len ( liczby )) as e : for x in liczby : e . submit ( wyswietl , x ) Wielowątkowość 10 11 12 Rozwiązanie zadania na rozgrzewkę from concurrent . futures import T h r e a d P o o l E x e c u t o r from concurrent . futures import as_completed import time 1 2 3 4 def wyswietl ( x ): time . sleep ( x ) return x 5 6 7 8 liczby = [ int ( x ) for x in input (). split ()] 9 10 with T hr e a d P o o l E x e c u t o r ( max_workers = len ( liczby )) as e : futures = { e . submit ( wyswietl , x ) for x in liczby } suma = 0 for f in as_completed ( futures ): print ( f . result ()) suma += f . result () print ( suma ) Wielowątkowość 11 12 13 14 15 16 17 Zadanie 1 Na wejściu w pierwszej linijce znajduje się liczba (n), a w kolejnych n linijkach podane są adresy URL. Na wyjściu powinny być wyświetlone wszystkie adresy URL zgodnie z kolejnością ich wczytania. Adresy URL, których wczytywanie zajęło zbyt dużo czasu powinny zostać pominięte (przyjmij timeout jako 1.5 sekundy). Jeśli zadanie nie zostanie wykonane wielowątkowo, przekroczony zostanie dopuszczalny czas na sprawdzarce. Wielowątkowość Zadanie 1 (c.d.) Przykładowe wejście: 8 http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / a http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / b http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / c http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / d http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / e http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / f http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / g http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / h 1 2 3 4 5 6 7 8 9 Przykładowe wyjście: http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / b http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / h http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / g http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / a http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / d http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / e http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / c Wielowątkowość 1 2 3 4 5 6 7 Zadanie 2 Na wejściu w pierwszej linijce znajduje się liczba (n), a w kolejnych n linijkach podane są adresy URL. Na wyjściu powinna być wyświetlona suma wszystkich liczb, które znajdują się pod podanymi adresami URL. Adresy URL, których wczytywanie zajęło zbyt dużo czasu powinny zostać pominięte (przyjmij timeout jako 1.5 sekundy). Jeśli zadanie nie zostanie wykonane wielowątkowo, przekroczony zostanie dopuszczalny czas na sprawdzarce. Wielowątkowość Zadanie 2 (c.d.) Przykładowe wejście: 8 http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / a http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / b http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / c http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / d http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / e http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / f http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / g http : / / 1 5 0 . 2 5 4 . 3 6 . 7 8 / inzynieria / h 1 2 3 4 5 6 7 8 9 Przykładowe wyjście: 74 1 Wielowątkowość Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika (Tkinter) Uniwersytet Ekonomiczny w Poznaniu 28 maja 2014 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Python i graficzny interfejs użytkownika Programowanie GUI może odbywać się za pomocą różnych bibliotek: GTK Qt wxWidgets TkInter Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( TkInter – Prosty program from tkinter import * from tkinter import ttk 1 2 3 def pressed (): print ( ’ Wykonuje funkcje ... ’) 4 5 6 root = Tk () button = Button ( root , text = ’ Kliknij na mnie ! ’ , command = pressed ) button . pack ( pady =20 , padx = 20) root . mainloop () 7 8 9 10 11 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Prosty program 2 from tkinter import * from tkinter import ttk 1 2 3 def pressed (): print ( z a w a r t o s c _ p o l a _ t e k s t o w e g o . get ()) 4 5 6 root = Tk () 7 8 z a w a r t o s c _ p o l a _ t e k s t o w e g o = StringVar () pole_tekstowe = ttk . Entry ( root , width =7 , textvariable = z a w a r t o s c _ p o l a _ t e k s t o w e g o ) button = Button ( root , text = ’ Kliknij na mnie ! ’ , command = pressed ) pole_tekstowe . pack ( pady =20 , padx = 20) button . pack ( pady =20 , padx = 20) root . mainloop () 9 10 11 12 13 14 15 16 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( TkInter – Przechowywanie wartości Wartości, które są pobierane lub wyświetlane w widgetach TkInter mają specjalne typy, np.: IntVar StringVar Powód: domyślne proste typy w Pythonie są niemutowalne. Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Praktyczny przykład Patrz plik jednostki.py na moodle W pliku znajduje się dużo dokumentacji, dokładnie wyjaśniającej działanie programu. Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie na rozgrzewkę Zmień program jednostki.py tak, aby : otrzymane cale były zaokrąglane do jedności w zależności od tego, jaki wyszedł wynik, ma się zmieniać etykieta przy wyniku (ta, która teraz zawsze ma wartość ”cali”), czyli: jeśli cyfra dziesiątek jest inna niż 1, a cyfra jedności to 2,3 lub 4, etykietą ma być ”cale” w przeciwnym wypadku, etykieta ma mieć wartość ”cali” Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Komunikacja z bazami danych Python Database API Specification v2.0 http://legacy.python.org/dev/peps/pep-0249/ specyfikacja API, zgodnie z którą powinny być przygotowywane biblioteki do komunikacji z bazami danych łatwe przejście pomiędzy różnymi bibliotekami i różnymi bazami danych Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( MySQL relacyjny system zarządzania bazami danych (RDBMS), dostępny na licencji wolnego oprogramowania GNU General Public Licence, rozwijany przez firmę Oracle, Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( PhpMyAdmin http://ego.kie.ue.poznan.pl/mysql-admin/ user: inz opr hasło: inz opr Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Biblioteki do komunikacji z MySQL Mysql Connector MySQLdb (na razie tylko Python 2) pymysql Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( pymysql - prosty przykład import pymysql 1 2 connection = pymysql . connect ( host = ’ ego . kie . ue . poznan . pl ’ , port = 8080 , user = ’ inz_opr ’ , passwd = ’ inz_opr ’ , database = ’ i n z y n i e r i a _ o p r o g r a m o w a n i a ’) cursor = connection . cursor () cursor . execute ( ’ select * from polaczenia ; ’) for i in cursor : print ( i ) 3 4 5 6 7 8 9 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Kursor Kursor jest to kontrolna struktura pośrednicząca w wykonywaniu zapytań i pozwalająca na iterowanie po ich wynikach. dla jednego połączenia z bazą możemy stworzyć wiele kursorów dzięki temu do jednego połączenia z bazą możemy wysyłać wiele różnych zapytań i łatwo operować na różnych kolekcjach otrzymanych wyników Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Dłuższy przykład – ładowanie danych do bazy Patrz plik data_upload.py za pomocą tego skryptu załadowano do bazy dane do zadania domowego UWAGA: ze względu na ustawienia bazy danych skrypt zwróci błąd (brak uprawnień użytkownika do zapisu) Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zmiany w bazie i zatwierdzanie wyników podobnie jak w przypadku zapisywania do pliku, wprowadzanie danych do bazy powinno być zakończone faktycznym potwierdzeniem wprowadzenia zmian aby to zrobić: na obiekcie połączenia używamy funkcji commit używamy menedżera kontekstu with... as... Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Wstęp do zadań w bazie danych przechowywane są analogiczne dane co w zajęciach z CSV zadanie polega na odpytywaniu bazy zgodnie z zadanymi kryteriami Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie 1 Wejściem są linijki odpowiedzialne za podłączenie się do bazy danych: 1 2 3 4 5 host port użytkownik hasło baza danych Baza danych ma strukturę analogiczną do bazy inzynieria_oprogramowania, dostępną na serwerze ego.kie.ue.poznan.pl Wyjściem ma być suma czasów trwania wszystkich połączeń (w sekundach) Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie 1 Przykładowe wejście ego . kie . ue . poznan . pl 8080 inz_opr inz_opr inzynieria_oprogramowania 1 2 3 4 5 Przykładowe wyjście 104956 1 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie 2 wejście analogiczne do zadania 1 + dodatkowe dwie krotki: krotka z identyfikatorami nadawców krotka z identyfikatorami odbiorców na wyjściu mają być zwrócone dwie krotki, gdzie pierwsza to suma sekund połączeń dla poszczególnych nadawców podanych w krotce wyjściowej, a druga to czas ostatniego połączenia odebranego przez odbiorców z drugiej krotki (w formacie ISO, skorzystaj z metody datetime.isoformat()) Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie 2 Przykładowe wejście ego . kie . ue . poznan . pl 8080 inz_opr inz_opr inzynieria_oprogramowania (47 , 209 , 392) (5 , 42) 1 2 3 4 5 6 7 Przykładowe wyjście (2099 , 2073 , 2058) ( ’ 2006 -06 -01 T05 :16:00 ’ , ’ 2006 -06 -01 T07 :34:00 ’) 1 2 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Testy jednostkowe Uniwersytet Ekonomiczny w Poznaniu 3 czerwca 2014 Testy jednostkowe Testowanie W praktyce oznacza napisanie kodu (niezależnie od kodu aplikacji), który uruchamia testy umożliwiające wykrycie ewentualnych błędów. Przykładowe rodzaje błędów wykrywanych podczas testowania: Syntax errors - niezamierzone błędy językowe. Logical errors - błędy w implementowanych algorytmach, np. pobieranie niewłaściwego indeksu z listy. Większe, czy systematycznie występujące błędy - np. zawieszanie się aplikacji przy konkretnych danych wejściowych. Testy jednostkowe Testowanie jednostkowe Wychwycenie każdego z błędów jest możliwe poprzez właściwe przygotowanie procedur testowych. Testowanie jednostkowe polega na sprawdzeniu wybranego fragmentu kodu w wyizolowanym środowisku. Dzięki temu inne operacje w kodzie aplikacji nie mają wpływu na testowany fragment. Testy jednostkowy pozwalają sprawdzać: całe moduły pojedyncze klasy funkcje Testy jednostkowe Moduł unittest Do przeprowadzania testów jednostkowych wykorzystywany jest moduł unittest. Moduł ten dostarcza zestaw narzędzi wspomagających budowę i przeprowadzanie testów. Nazwa każdej metody w teście poprzedzona test_ Metoda setUp() wywoływana jest przed każdym testem i pozwala na wykonanie określonych operacji przed uruchomieniem testu, np. ustawienie zmiennych unittest.main() uruchamia testy Testy jednostkowe Przykładowy plik def czy_pierwsza ( liczba ): for element in range ( liczba ): if liczba % element == 0: return False return True 1 2 3 4 5 6 def n a s t e p n a _ p i e r w s z a ( liczba ): index = liczba while True : index += 1 if czy_pierwsza ( index ): print ( index ) 7 8 9 10 11 12 Testy jednostkowe Przykładowy test import unittest from pierwsze import czy_pierwsza 1 2 3 class Tes tPierws zych ( unittest . TestCase ): 4 5 def test_czy_piec ( self ): self . assertTrue ( czy_pierwsza (5)) 6 7 8 if __name__ == ’ __main__ ’: unittest . main () 9 10 Testy jednostkowe Przykładowy test Dlaczego test wyrzuca taki błąd? Testy jednostkowe Przykładowy plik poprawiony def czy_pierwsza ( liczba ): for element in range (2 , liczba ): if liczba % element == 0: return False 1 2 3 4 5 return True 6 7 def n a s t e p n a _ p i e r w s z a ( liczba ): index = liczba while True : index += 1 if czy_pierwsza ( index ): print ( index ) 8 9 10 11 12 13 Testy jednostkowe Przykładowy test 2 import unittest from pierwsze import czy_pierwsza 1 2 3 class Tes tPierws zych ( unittest . TestCase ): 4 5 def test_czy_piec ( self ): self . assertTrue ( czy_pierwsza (5)) 6 7 8 def t es t_ c zy _c zt e ry ( self ): self . assertFalse ( czy_pierwsza (4) , msg = ’4 nie jest liczba pierwsza ! ’) 9 10 11 12 if __name__ == ’ __main__ ’: unittest . main () 13 14 Testy jednostkowe Metody weryfikujące wartości assertEqual(a,b) - porównanie assertEqual(1+1,2) assertTrue() wartości ’a’ z oczekiwaną ’b’, np. - sprawdzenie czy prawda assertFalse() - sprawdzenie czy fałsz Więcej: https://docs.python.org/3.3/library/unittest.html Testy jednostkowe Zadanie Na Moodle znajduje się plik z metodami, które mają testować poprawność Biblioteki (wypożyczanie książek - biblioteka 1). Należy zaimplementować te metody zgodnie z komentarzami w pliku. Przygotowany plik testowy należy wykorzystać przy zadaniach dostępnych w quizie na Moodle: W pytaniach zawarte są pliki, na których mają zostać przeprowadzone testy. Dla każdego pliku (pytania) należy zaznaczyć te odpowiedzi, dla których testy zakończyły się pozytywnie. Za poprawnie rozwiązane zadania jest do zdobycia maksymalnie 6 punktów. Testy jednostkowe http://www.tutorialspoint.com/python/python_classes_objects.htm PROGRAMY: 1. Nawiasy a=str(input()) alista=list(a) o='(' c=')' ileo=alista.count(o) ilec=alista.count(c) 2. 3. if ileo==ilec: po=alista.index(o) pc=alista.index(c) if po<pc: alista.reverse() ko=alista.index(o) kc=alista.index(c) if kc<ko: print("True") else: print("False") else: print("False") else: print("False") Pesel pesel=input() sk=(pesel[0]*1)+(pesel[1]*3)+(pesel[2]*7)+(pesel[3]*9)+(pesel[4]*1)+(pesel[5]*3)+(pesel[6]*7)+(pesel[7 ]*9)+(pesel[8]*1)+(pesel[9]*3) dm=sk%10 kontrolna=(10-dm)%10 if kontrolna==pesel[10]: check="1" else: check="0" print(check) 2.1 anagram wyraz_wzorcowy=input() wyraz1=input() wyraz2=input() wyraz3=input() wyraz4=input() wyraz5=input() w_w=sorted(wyraz_wzorcowy) l=[wyraz1,wyraz2,wyraz3,wyraz4,wyraz5] l2=[] for i in l: if w_w == sorted(i): l2.append(i) print(sorted(l2)) 4. 3.1 silnia/newton from math import factorial nk=input().split() n=int(nk[0]) k=int(nk[1]) newton=int((factorial(n)/(factorial(k)*factorial(n-k)))) print(newton) 5. 3.2 monety kwota = int(input()) n = input().split() nominaly=[] for i in n: z=int(i) nominaly.append(z) p=[1] j=kwota*[0] sposoby = p+j for i in nominaly: for j in range(i,kwota+1): sposoby[j]=sposoby[j]+sposoby[j-i] d=sposoby[kwota] print(d) 6. 4.1 pączki a. Kasi osoby = input().split() imiona = input().split() n=[] for i in osoby: a=(imiona.count(i)) print(a) n.append((i,a)) n.sort(key=lambda x:x[1],reverse=True) print(n) b. Moje names=input() doughnuts=input() names=names.split() doughnuts=doughnuts.split() count=[] z=[] for i in range(0,len(names)): count.append(doughnuts.count(names[i])) z.append([count[i],names[i]]) z.sort() z.reverse() result=[] for j in range(0,len(z)): z[j].reverse() z[j]=tuple(z[j]) result.append(z[j]) print(result) 7. 5.1 figury import math class Kolo: suma1=0 def __init__(self,promien): self.promien=promien def polekola(self): pole1=round(math.pi*self.promien**2,2) self.suma1=self.suma1+pole1 class Prostokat: suma2=0 def __init__(self,dlugosc,szerokosc): self.dlugosc=dlugosc self.szerokosc=szerokosc def poleprostokata(self): pole2=round(self.dlugosc*self.szerokosc,2) self.suma2=self.suma2+pole2 class Trojkat: suma3=0 def __init__(self,ramie1,ramie2,ramie3): self.ramie1=ramie1 self.ramie2=ramie2 self.ramie3=ramie3 def poletrojkata(self): p=(self.ramie1+self.ramie2+self.ramie3)/2 pole3=round(math.sqrt((p*(p-self.ramie1)*(p-self.ramie2)*(p-self.ramie3))),2) self.suma3=self.suma3+pole3 iloscfigur=float(input()) listafigur = [] a=0 b=0 c=0 for i in range(int(iloscfigur)): figura = input().split() if len(figura)is 1: liczba1=Kolo(float(figura[0])) liczba1.polekola() a=round(a+liczba1.suma1,2) elif len(figura)is 2: liczba2=Prostokat(float(figura[0]),float(figura[1])) liczba2.poleprostokata() b=round(b+liczba2.suma2,2) elif len(figura) is 3: liczba3=Trojkat(float(figura[0]),float(figura[1]),float(figura[2])) liczba3.poletrojkata() c=round(c+liczba3.suma3,2) 8. suma=round((a+b+c),2) print(suma) 5.2 wynagrodzenie class Wynagrodzenie: suma=0 def __init__(self,imie,brutto): self.imie=imie self.brutto=int(brutto) def wynagrodzenienetto(self): if self.brutto > 1599: sus=round(round(self.brutto*0.0976,2)+round(self.brutto*0.015,2)+round(self.brutto*0.0245,2),2) podswymskl=round(self.brutto-sus,2) sklubezzdr=round(podswymskl*0.09,2) dop=round(podswymskl*0.0775,2) poz=round(self.brutto-139.25-sus,0) zpdpo=round((poz*0.18)-46.33,2) zpddp=round(zpdpo-dop,0) n=round(self.brutto-sus-sklubezzdr-zpddp,2) netto='%.2f' %n skp=round(self.brutto*0.0976,2)+round(self.brutto*0.065,2)+round(self.brutto*0.0193,2)+round(self.br utto*0.0245,2)+round(self.brutto*0.001,2) kp=round(self.brutto+skp,2) sklobciazprac='%.2f' %skp kosztypracodawcy='%.2f' %kp self.suma=self.suma+kp print(self.imie,netto,sklobciazprac,kosztypracodawcy) else: print(self.imie,0) 9. iloscpracownikow=int(input()) k=[] for i in range(iloscpracownikow): pracownik=input().split() k.append(pracownik) s=0 for j in k: liczba1=Wynagrodzenie(j[0],int(j[1])) liczba1.wynagrodzenienetto() s=(s+liczba1.suma) su='%.2f' %s print(su) 6.1 dodawanie książki class Ksiazka: def __init__(self,lista): self.lista=lista def dodaj_egzemplarz_ksiazki(self): pojedynczalista=set(self.lista) informacjaoksiazce=[] for i in pojedynczalista: tytul=i[0] autor=i[1] liczbaegzemplarzy=self.lista.count(i) informacjaoksiazce.append((tytul,autor,liczbaegzemplarzy)) informacjaoksiazce.sort(key=lambda x:x[0],reverse=False) for j in informacjaoksiazce: print (j) liczbaksiazek=int(input()) listaksiazek=[] for a in range(liczbaksiazek): ksiazka=eval(input()) tytulksiazki=ksiazka[0] autorksiazki=ksiazka[1] listaksiazek.append((tytulksiazki,autorksiazki)) ksiazka1=Ksiazka(listaksiazek) ksiazka1.dodaj_egzemplarz_ksiazki() 10. 6.2 Biblioteka """class Ksiazka: def __init__(self, tytul, autor): pass class Egzemplarz: def __init__(self, rok_wydania, ksiazka): pass""" class Biblioteka: dostepne_ksiazki=[] def __init__(self): self.ksiazka=dict() def dodaj_egzemplarz_ksiazki(self, tytul, autor, rok_wydania): self.dostepne_ksiazki.append(tytul) return True def __pobierz_czytelnika(self, nazwisko): czytelnik=Czytelnik() def wypozycz(self, nazwisko, tytul): czytelnik=Czytelnik() return czytelnik.wypozycz(nazwisko,tytul) def oddaj(self, nazwisko, tytul): czytelnik=Czytelnik() return czytelnik.oddaj(nazwisko,tytul) class Czytelnik(Biblioteka): limit = 3 wypozyczone_ksiazki=[] lista_wypozyczonych_ksiazek=[] oddane=[] def __init__(self): self.nazwisko=dict() def wypozycz(self, nazwisko,tytul): self.wypozyczone_ksiazki.append(nazwisko) self.lista_wypozyczonych_ksiazek.append((nazwisko,tytul)) lista_nazwisk=set(self.wypozyczone_ksiazki) lista_nazwiska_tytul=set(self.lista_wypozyczonych_ksiazek) if tytul in self.dostepne_ksiazki: for l in lista_nazwisk: if (self.wypozyczone_ksiazki.count(l) <= self.limit): for m in lista_nazwiska_tytul: if self.lista_wypozyczonych_ksiazek.count(m)<2: self.dostepne_ksiazki.remove(tytul) return True else: self.wypozyczone_ksiazki.remove(l) self.lista_wypozyczonych_ksiazek.remove(m) return False else: self.wypozyczone_ksiazki.remove(l) self.lista_wypozyczonych_ksiazek.pop() return False else: self.wypozyczone_ksiazki.pop() self.lista_wypozyczonych_ksiazek.pop() return False def oddaj(self, nazwisko, tytul): self.oddane.append((nazwisko,tytul)) for n in self.oddane: if n in self.lista_wypozyczonych_ksiazek: self.wypozyczone_ksiazki.remove(nazwisko) self.lista_wypozyczonych_ksiazek.remove(n) self.oddane.remove(n) self.dostepne_ksiazki.append(tytul) return True else: return False biblioteka = Biblioteka() czytelnik = Czytelnik() for i in range(int(input())): t = eval(input()) if t[0] == "dodaj": print(biblioteka.dodaj_egzemplarz_ksiazki(t[1], t[2], t[3])) elif t[0] == "wypozycz": print(biblioteka.wypozycz(t[1], t[2])) elif t[0] == "oddaj": print(biblioteka.oddaj(t[1], t[2])) 11. 7.1 drzewo class Drzewo: lista_wynikow=[] lista_usuwanych=[] def __init__(self, lista_krotek: list): self.lista_krotek=lista_krotek def pobierz_nadkoncepty(self, wierzcholek: str) -> list: for i in wierzcholek: self.lista_wynikow.append(i) for j in self.lista_krotek: if i==j[1]: self.lista_wynikow.append(j[0]) self.lista_usuwanych.append(j[0]) drzewo.petla_nieskonczona(i) print(self.lista_wynikow,self.lista_usuwanych) self.lista_wynikow=[] self.lista_usuwanych=[] def petla_nieskonczona(self,wierzcholek): for m in self.lista_krotek: if m[1] in self.lista_usuwanych: self.lista_wynikow.append(m[0]) self.lista_usuwanych.pop() self.lista_usuwanych.append(m[0]) drzewo.petla_nieskonczona(wierzcholek) else: pass drzewo_input = eval(input()) drzewo = Drzewo(drzewo_input) zapytania = drzewo.pobierz_nadkoncepty(eval(input())) 12. 7.2 odleglosc drzewo class Drzewo: lista_wynikow=[] lista_usuwanych=[] nadwezly1=[] nadwezly2=[] lista_miar=[] lista_miar_prostych=[] lista_miar_potegowych=[] def __init__(self, lista_krotek: list): self.lista_krotek=lista_krotek def pobierz_nadkoncepty1(self, wierzcholek1:str)->list: self.nadwezly1=[] self.nadwezly1.append(wierzcholek1) for j in self.lista_krotek: if wierzcholek1==j[1]: self.nadwezly1.append(j[0]) self.lista_usuwanych.append(j[0]) drzewo.petla_nieskonczona1(wierzcholek1) self.lista_usuwanych=[] def pobierz_nadkoncepty2(self, wierzcholek2:str)->list: self.nadwezly2=[] self.nadwezly2.append(wierzcholek2) for l in self.lista_krotek: if wierzcholek2==l[1]: self.nadwezly2.append(l[0]) self.lista_usuwanych.append(l[0]) drzewo.petla_nieskonczona2(wierzcholek2) self.lista_usuwanych=[] def petla_nieskonczona1(self,wierzcholek): for m in self.lista_krotek: if m[1] in self.lista_usuwanych: self.nadwezly1.append(m[0]) self.lista_usuwanych.pop() self.lista_usuwanych.append(m[0]) drzewo.petla_nieskonczona1(wierzcholek) else: pass def petla_nieskonczona2(self,wierzcholek: list)->list: for m in self.lista_krotek: if m[1] in self.lista_usuwanych: self.nadwezly2.append(m[0]) self.lista_usuwanych.pop() self.lista_usuwanych.append(m[0]) drzewo.petla_nieskonczona2(wierzcholek) else: pass def oblicz_odleglosc(self, lista_zapytan: list) -> list: for k in lista_zapytan: miara=k[0] wierzcholek1=k[1] wierzcholek2=k[2] drzewo.pobierz_nadkoncepty1(wierzcholek1) drzewo.pobierz_nadkoncepty2(wierzcholek2) if miara=='prosta': drzewo.miara_prosta_licz_odleglosc(self.nadwezly1,self.nadwezly2) elif miara=='potegowa': drzewo.miara_potegowa_licz_odleglosc(self.nadwezly1,self.nadwezly2) else: pass return self.lista_miar def miara_prosta_licz_odleglosc(self, nadwezly1:list, nadwezly2:list) -> int: miara_prosta=0 self.lista_miar_prostych=[] for o in nadwezly1: for p in nadwezly2: if o == p: odleglosc1_mpr=nadwezly1.index(o) odleglosc2_mpr=nadwezly2.index(p) miara_prosta=int(odleglosc1_mpr+odleglosc2_mpr) self.lista_miar_prostych.append(miara_prosta) if len(self.lista_miar_prostych)==1: self.lista_miar.append(miara_prosta) else: pass else: pass def miara_potegowa_licz_odleglosc(self, nadwezly1:list, nadwezly2:list) -> int: miara_potegowa=0 self.lista_miar_potegowych=[] for q in nadwezly1: for r in nadwezly2: if q == r: odleglosc1_mpg=((2**nadwezly1.index(q))-1) odleglosc2_mpg=((2**nadwezly2.index(r))-1) miara_potegowa=int(odleglosc1_mpg+odleglosc2_mpg) self.lista_miar_potegowych.append(miara_potegowa) if len(self.lista_miar_potegowych)==1: self.lista_miar.append(miara_potegowa) else: pass else: pass drzewo_input = eval(input()) drzewo = Drzewo(drzewo_input) zapytania =print(drzewo.oblicz_odleglosc(eval(input()))) 13. 8.1 biblioteka 1 import datetime class Ksiazka: lista_nowych=[] informacjaoksiazce=[] def __init__(self,lista,data_graniczna): self.lista=lista self.data_graniczna=data_graniczna def dodaj_egzemplarz_ksiazki(self): format_daty_granicznej=datetime.date(data_graniczna[0],data_graniczna[1],data_graniczna[2]) for i in self.lista: tytul=i[0] autor=i[1] data_wprowadzenia=i[3] data_dodania=datetime.date(data_wprowadzenia[0],data_wprowadzenia[1],data_wprowadzenia[2]) if data_dodania>format_daty_granicznej: self.lista_nowych.append((i[0],i[1])) else: pass bez_powtorzen=set(self.lista_nowych) for j in bez_powtorzen: tyt=j[0] aut=j[1] liczbaegzemplarzy=self.lista_nowych.count(j) self.informacjaoksiazce.append((tyt,aut,liczbaegzemplarzy)) for k in self.informacjaoksiazce: print(k) liczbaksiazek=int(input()) listaksiazek=[] for a in range(liczbaksiazek): ksiazka=eval(input()) listaksiazek.append(ksiazka) data_graniczna=eval(input()) ksiazka1=Ksiazka(listaksiazek,data_graniczna) ksiazka1.dodaj_egzemplarz_ksiazki() 14. 8.2 biblioteka 2 import datetime class Ksiazka: def __init__(self, tytul, autor): self.tytul = tytul self.autor = autor self.egzemplarze = [] class Egzemplarz: def __init__(self, rok_wydania, ksiazka,data_dodania): self.rok_wydania = rok_wydania self.ksiazka = ksiazka self.data_dodania=data_dodania self.wypozyczony = False class Czytelnik: limit = 3 kara_za_nieoddanie=0 kara_za_przetrzymanie=0 lista_dat=[] def __init__(self, nazwisko,data_wypozyczenia,data_zapytania): self.nazwisko = nazwisko self.data_wypozyczenia=data_wypozyczenia self.data_zapytania=data_zapytania self.wypozyczone = {} def wypozycz(self, egzemplarz,data_wypozyczenia,data_zapytania): tytul = egzemplarz.ksiazka.tytul kara_za_nieoddanie=0 if Czytelnik.limit > len(self.wypozyczone) and tytul not in self.wypozyczone.keys(): egzemplarz.wypozyczony = True self.wypozyczone[tytul] = egzemplarz self.lista_dat.append((self.nazwisko,tytul,data_wypozyczenia)) self.kara_za_nieoddanie=0.5*((self.data_zapytania-data_wypozyczenia).days-7) return True else: return False def oddaj(self, tytul,data_oddania): try: kara_za_przetrzymanie=0 self.wypozyczone.pop(tytul).wypozyczony = False for x in self.lista_dat: if (x[0],x[1])==(self.nazwisko,tytul): self.kara_za_przetrzymanie=0.5*((data_oddania-x[2]).days-7) return True except KeyError: return False class Biblioteka: def __init__(self): self.__ksiazki = {} self.__czytelnicy = {} self.lista_kar_za_przetrzymanie=[] self.lista_kar_za_nieoddanie=[] def dodaj_egzemplarz_ksiazki(self, tytul, autor, rok_wydania,data_dodania): try: ksiazka = self.__ksiazki[tytul] except KeyError: ksiazka = Ksiazka(tytul, autor) self.__ksiazki[tytul] = ksiazka ksiazka.egzemplarze.append(Egzemplarz(rok_wydania, ksiazka,data_dodania)) return True def raport_ksiazek(self): lista = [] for k in self.__ksiazki.values(): lista.append((k.tytul, k.autor, len(k.egzemplarze))) return sorted(lista, key = lambda t: t[0]) def dostepne_egz(self, tytul): try: return [ egz for egz in self.__ksiazki[tytul].egzemplarze if not egz.wypozyczony ] except KeyError: return [] def __pobierz_czytelnika(self, nazwisko,data_wypozyczenia,data_zapytania): try: return self.__czytelnicy[nazwisko] except KeyError: nowy = Czytelnik(nazwisko,data_wypozyczenia,data_zapytania) self.__czytelnicy[nazwisko] = nowy return nowy def wypozycz(self, nazwisko, tytul,data_wypozyczenia,data_zapytania): try: egzemplarz = self.dostepne_egz(tytul)[0] czytelnik = self.__pobierz_czytelnika(nazwisko,data_wypozyczenia,data_zapytania) a= (czytelnik.wypozycz(egzemplarz,data_wypozyczenia,data_zapytania)) print(a) if (czytelnik.kara_za_nieoddanie>0) and (a==True): self.lista_kar_za_nieoddanie.append((nazwisko,tytul,czytelnik.kara_za_nieoddanie)) except IndexError: return False def oddaj(self, nazwisko, tytul,data_oddania,data_zapytania): czytelnik = self.__pobierz_czytelnika(nazwisko,data_oddania,data_zapytania) b=czytelnik.oddaj(tytul,data_oddania) print(b) if (b==True): self.lista_kar_za_przetrzymanie.append((nazwisko,tytul,czytelnik.kara_za_przetrzymanie)) def kary(self): lista=[] lista_kar_n=[] lista_kar_p=[] for n in self.lista_kar_za_przetrzymanie: for m in self.lista_kar_za_nieoddanie: if (m[0],m[1]) == (n[0],n[1]): self.lista_kar_za_nieoddanie.remove(m) for o in self.lista_kar_za_nieoddanie: if o[2] > 0: lista_kar_n.append((o[0],o[2])) for p in self.lista_kar_za_przetrzymanie: if p[2] > 0: lista_kar_p.append((p[0],p[2])) lista=lista_kar_n+lista_kar_p lista_nazwisk=[] for z in lista: lista_nazwisk.append(z[0]) pojedyncza_lista_nazwisk=set(lista_nazwisk) ostatczna_lista=[] for d in pojedyncza_lista_nazwisk: kara=0 for e in lista: if d ==e[0]: kara+=e[1] ostatczna_lista.append((d,(kara))) ostatczna_lista.sort() for r in ostatczna_lista: print(r) biblioteka = Biblioteka() lista_czynnosci=[] for t in range(int(input())): lista_czynnosci.append(eval(input())) data_zapytania_krotka=eval(input()) data_zapytania = datetime.date(data_zapytania_krotka[0],data_zapytania_krotka[1],data_zapytania_krotka[2]) for i in lista_czynnosci: if i[0] == "dodaj": print(biblioteka.dodaj_egzemplarz_ksiazki(i[1], i[2], i[3],i[4])) elif i[0] == "wypozycz": datawyp = datetime.date(i[3][0],i[3][1],i[3][2]) biblioteka.wypozycz(i[1], i[2],datawyp,data_zapytania) elif i[0] == "oddaj": dataoddaj=datetime.date(i[3][0],i[3][1],i[3][2]) biblioteka.oddaj(i[1], i[2],dataoddaj,data_zapytania) biblioteka.kary() 15. 9.1 import csv import operator separator=input() wejscie=input() plik_csv = open(wejscie, 'r') czytaj = csv.reader(plik_csv, delimiter=separator) liczba_polaczen_nadawca=dict() liczba_polaczen_odbiorca=dict() for i, rekord in enumerate(czytaj): if i==0: naglowek=rekord else: if rekord[0] in liczba_polaczen_nadawca.keys(): liczba_polaczen_nadawca[rekord[0]]+=1 else: liczba_polaczen_nadawca[rekord[0]]=1 if rekord[1] in liczba_polaczen_odbiorca.keys(): liczba_polaczen_odbiorca[rekord[1]]+=1 else: liczba_polaczen_odbiorca[rekord[1]]=1 lista_krotek_nadawca= [(int(i[0]),i[1]) for i in liczba_polaczen_nadawca.items()] lista_krotek_odbiorca= [(int(i[0]),i[1]) for i in liczba_polaczen_odbiorca.items()] posortowana_liczba_nadawcow_po_kluczach=sorted(lista_krotek_nadawca, key=operator.itemgetter(0)) posortowana_liczba_nadawcow_po_wartosciach=sorted(posortowana_liczba_nadawcow_po_kluczach, key=operator.itemgetter(1),reverse=True) posortowana_liczba_odbiorcow_po_kluczach=sorted(lista_krotek_odbiorca, key=operator.itemgetter(0)) posortowana_liczba_odbiorcow_po_wartosciach=sorted(posortowana_liczba_odbiorcow_po_kluczach, key=operator.itemgetter(1),reverse=True) max_nadawca=str(posortowana_liczba_nadawcow_po_wartosciach[0][0]) max_nadawca_sekund=0 max_odbiorca=str(posortowana_liczba_odbiorcow_po_wartosciach[0][0]) max_odbiorca_sekund=0 plik_csv=open(wejscie,'r') czytaj = csv.reader(plik_csv, delimiter=separator) for rekord in czytaj: if rekord[0]==max_nadawca: max_nadawca_sekund +=int(rekord[3]) if rekord[1]==max_odbiorca: max_odbiorca_sekund +=int(rekord[3]) print(max_nadawca+":", max_nadawca_sekund) print(max_odbiorca+":", max_odbiorca_sekund) 16. 9.2 import csv import operator import datetime separator=input() wejscie=input() plik_csv = open(wejscie, 'r') czytaj = csv.reader(plik_csv, delimiter=separator) liczba_polaczen_nadawca=dict() liczba_polaczen_odbiorca=dict() liczba_nadajnikow=dict() liczba_dni=dict() for i, rekord in enumerate(czytaj): if i==0: naglowek=rekord else: if rekord[0] in liczba_polaczen_nadawca.keys(): liczba_polaczen_nadawca[rekord[0]]+=1 else: liczba_polaczen_nadawca[rekord[0]]=1 if rekord[1] in liczba_polaczen_odbiorca.keys(): liczba_polaczen_odbiorca[rekord[1]]+=1 else: liczba_polaczen_odbiorca[rekord[1]]=1 if rekord[4] in liczba_nadajnikow.keys(): liczba_nadajnikow[rekord[4]]+=1 else: liczba_nadajnikow[rekord[4]]=1 if rekord[2] in liczba_dni.keys(): liczba_dni[rekord[2]]+=1 else: liczba_dni[rekord[2]]=1 lista_krotek_nadawca= [(int(i[0]),i[1]) for i in liczba_polaczen_nadawca.items()] lista_krotek_odbiorca= [(int(i[0]),i[1]) for i in liczba_polaczen_odbiorca.items()] lista_krotek_nadajniki= [(int(i[0]),i[1]) for i in liczba_nadajnikow.items()] lista_krotek_dni= [(i[0]) for i in liczba_dni.items()] day=[] for k in lista_krotek_dni: data=(datetime.datetime(int(k[0:4]),int(k[4:6]),int(k[6:9]),int(k[9:11]),int(k[11:13]))) day.append(data) posortowana_liczba_nadawcow_po_kluczach=sorted(lista_krotek_nadawca, key=operator.itemgetter(0)) posortowana_liczba_nadawcow_po_wartosciach=sorted(posortowana_liczba_nadawcow_po_kluczach, key=operator.itemgetter(1),reverse=True) posortowana_liczba_odbiorcow_po_kluczach=sorted(lista_krotek_odbiorca, key=operator.itemgetter(0)) posortowana_liczba_odbiorcow_po_wartosciach=sorted(posortowana_liczba_odbiorcow_po_kluczach, key=operator.itemgetter(1),reverse=True) posortowana_liczba_nadajnikow_po_kluczach=sorted(lista_krotek_nadajniki, key=operator.itemgetter(0)) posortowana_liczba_nadajnikow_po_wartosciach=sorted(posortowana_liczba_nadajnikow_po_kluczac h, key=operator.itemgetter(1),reverse=True) posortowana_liczba_dni=sorted(day) max_nadawcy=[] for a in posortowana_liczba_nadawcow_po_wartosciach: max_nadawcy.append(str(a[0])) if len(max_nadawcy)>9: break max_odbiorcy=[] for b in posortowana_liczba_odbiorcow_po_wartosciach: max_odbiorcy.append(str(b[0])) if len(max_odbiorcy)>9: break max_nadajnik=str(posortowana_liczba_nadajnikow_po_wartosciach[0][0]) max_nadajnik_ilosc=(posortowana_liczba_nadajnikow_po_wartosciach[0][1]) plik_csv=open(wejscie,'r') czytaj = csv.reader(plik_csv, delimiter=separator) max_nadawca=str(posortowana_liczba_nadawcow_po_wartosciach[0][0]) max_nadawc=int(posortowana_liczba_nadawcow_po_wartosciach[0][1]) max_nadawca_sekund=0 lista_nadawcow=[] for rekord in czytaj: if rekord[0]==max_nadawca: max_nadawca_sekund +=int(rekord[3]) srednie_polaczenia_wychodzace=round(max_nadawca_sekund/(posortowana_liczba_nadawcow_po_w artosciach[0][1]),2) ostatnia_wartosc=posortowana_liczba_dni.pop() pierwsze=posortowana_liczba_dni[0] dni=round((ostatnia_wartosc.day-pierwsze.day)+1,2) srednia_liczba_polaczen=round((posortowana_liczba_nadawcow_po_wartosciach[0][1])/dni,2) print(max_nadawcy) print(max_odbiorcy) print((max_nadajnik, max_nadajnik_ilosc)) print(srednie_polaczenia_wychodzace,srednia_liczba_polaczen) 17. 10.1 def my_range(poczatek,koniec): while poczatek < koniec: yield poczatek poczatek+=1 wynik=[] for i in range(int(input())): poczatek_koniec=eval(input()) wejscie = my_range(poczatek_koniec[0],poczatek_koniec[1]) wynik.append(sum(wejscie)) for j in wynik: print(j) 18. 10.2 import operator separator=input() wejscie=input() plik = open(wejscie, 'r') def csv(plik,separator): for i in plik: wiersz = i.split(separator)[3] yield wiersz wynik=[] suma=0 zadanie=csv(plik,separator) for j in zadanie: wynik.append(j) for k in(wynik[1:]): suma+=int(k) print(suma) 19. 12.1 from concurrent.futures import ThreadPoolExecutor from concurrent.futures import as_completed import time from urllib.request import urlopen ile_liczb=int(input()) lista_adresow=[] for adres in range(ile_liczb): adres=input() lista_adresow.append(adres) def wyswietl(x): a = urlopen(x, timeout=1.5).read() a.decode('utf-8') return x with ThreadPoolExecutor(max_workers = len(lista_adresow)) as e: futures = {e.submit(wyswietl, x) for x in lista_adresow} for f in as_completed(futures): try: print(f.result()) except: pass 20. 12.2 from concurrent.futures import ThreadPoolExecutor from concurrent.futures import as_completed from urllib.request import urlopen ile_liczb=int(input()) lista_adresow=[] for adres in range(ile_liczb): adres=input() lista_adresow.append(adres) def wyswietl(x): a = urlopen(x, timeout=1.5).read() return a.decode('utf-8') suma=0 with ThreadPoolExecutor(max_workers = len(lista_adresow)) as e: futures = {e.submit(wyswietl, x) for x in lista_adresow} for f in as_completed(futures): try: suma+=int(f.result()) except: pass print(suma) 21. 13.1 import pymysql connection = pymysql.connect(host=input(), port = int(input()), user=input(), passwd=input(), database=input()) cursor = connection.cursor() cursor.execute('select * from polaczenia;') suma=0 for i in cursor: suma+=i[3] print(suma) 22. 13.2 import pymysql import datetime connection = pymysql.connect(host=input(), port = int(input()), user=input(), passwd=input(), database=input()) id_nadawcy=eval(input()) id_odbiorcy=eval(input()) lista_nad=[] max_odb=[] cursor = connection.cursor() for nadawca in id_nadawcy: cursor.execute('select * from polaczenia;') suma=0 for i in cursor: if i[0]==nadawca: suma+=i[3] lista_nad.append(suma) for odbiorca in id_odbiorcy: cursor.execute('select * from polaczenia;') lista_odb=[] for i in cursor: if i[1]==odbiorca: lista_odb.append(i[2].isoformat()) max_odb.append(max(lista_odb)) suma_polaczen=tuple(lista_nad) ostatnie_pol=tuple(max_odb) print(suma_polaczen) print(ostatnie_pol) 23. Zajecia zad1 import random class Bank: def __init__(self): self.konta =dict() def __pobierzkonto(self, nr_konta): return self.konta[nr_konta] def zaloz_konto(self, roczna_stopa, kapitalizacja): numer = random.randint(10000000000000000000000000,99999999999999999999999999) if kapitalizacja == 'dzienna': konto = KontoKapDzienna(numer,0,roczna_stopa) elif kapitalizacja == 'miesieczna': konto = KontoKapMiesieczna(numer,0,roczna_stopa) pass else: print('Jakas literowka') return False self.konta[numer]=konto return numer def wplac (self, nr_konta, kwota): konto=self.__pobierzkonto(nr_konta) konto.wplac(kwota) def przelej (self, nr_konta_nad, nr_konta_odb, kwota): konto_nad = self.__pobierzkonto(nr_konta_nad) konto_nad.wplac(-kwota) konto_odb = self.__pobierzkonto(nr_konta_odb) konto_odb.wplac(kwota) def nastepny_miesiac(self): for nr_konta in self.konta: self.konta[nr_konta].nastepny_miesiac() def wypisz_stan_kont(self): for nr_konta in self.konta: print ('Konto o numerze',nr_konta, 'ma stan', self.konta[nr_konta].kwota) print ('--------------') class Konto: def __init__(self, numer, kwota, roczna_stopa): self.numer=numer self.kwota=kwota self.roczna_stopa=roczna_stopa def nastepny_miesiac(self): pass def wplac (self,kwota): self.kwota +=kwota #te poniżej dziedziczą od KONTO !!! class KontoKapDzienna(Konto): def nastepny_miesiac(self): for i in range(30): self.kwota= round((1+self.roczna_stopa/360)*self.kwota,2) class KontoKapMiesieczna(Konto): def nastepny_miesiac(self): self.kwota= round((1+self.roczna_stopa/12)*self.kwota,2) bank = Bank () k1 = bank.zaloz_konto (0.02, "dzienna") k2 = bank.zaloz_konto (0.02, "miesieczna") bank.wypisz_stan_kont() bank.wplac (k1, 1000) bank.wplac (k2, 1000) bank.wypisz_stan_kont() bank.nastepny_miesiac () bank.wypisz_stan_kont() bank.przelej (k1 , k2 , 100) bank.wypisz_stan_kont() ## zad dom ##a = "("Quo vadis", "Henryk Sienkiewicz", 2011) ##krotka = eval(a) # krotki przekształcamy na obiekty # 24. Zajecia zad2 a. def wypisz(arg1:str) -> str: return "wypisany str to " + arg1 b. 2 def mnozenie (a: int , b: int ) -> int : """ print( mnozenie.__annotations__ ) anns = mnozenie.__annotations__ if type (a) != anns ['a'] or type (b) != anns ['b']: raise Exception (' Bledne typy parametrow ! ') else: """ return a*b try: print( mnozenie ( 6 ,2)) except Exception as ex: print(ex) try: print( mnozenie ( ' ojej ' ,2)) except Exception as ex: pass try: print( mnozenie ( 6.0,2.0)) except Exception as ex: pass c. 3 import math def heron(a ,b ,c ): """ Oblicza pole trojkata wg wzoru Herona a ,b ,c dlugosci bokow trojkata >> heron (3 ,4 ,5) 6.0 """ s = (a+b+c )/2 return math.sqrt (s*(s-a)*(s-b)*(s-c)) if __name__ == '__main__': print(heron.__doc__ ) print(heron (3 ,4 ,5)) Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika (Tkinter) Uniwersytet Ekonomiczny w Poznaniu 28 maja 2014 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Python i graficzny interfejs użytkownika Programowanie GUI może odbywać się za pomocą różnych bibliotek: GTK Qt wxWidgets TkInter Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( TkInter – Prosty program from tkinter import * from tkinter import ttk 1 2 3 def pressed (): print ( ’ Wykonuje funkcje ... ’) 4 5 6 root = Tk () button = Button ( root , text = ’ Kliknij na mnie ! ’ , command = pressed ) button . pack ( pady =20 , padx = 20) root . mainloop () 7 8 9 10 11 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Prosty program 2 from tkinter import * from tkinter import ttk 1 2 3 def pressed (): print ( z a w a r t o s c _ p o l a _ t e k s t o w e g o . get ()) 4 5 6 root = Tk () 7 8 z a w a r t o s c _ p o l a _ t e k s t o w e g o = StringVar () pole_tekstowe = ttk . Entry ( root , width =7 , textvariable = z a w a r t o s c _ p o l a _ t e k s t o w e g o ) button = Button ( root , text = ’ Kliknij na mnie ! ’ , command = pressed ) pole_tekstowe . pack ( pady =20 , padx = 20) button . pack ( pady =20 , padx = 20) root . mainloop () 9 10 11 12 13 14 15 16 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( TkInter – Przechowywanie wartości Wartości, które są pobierane lub wyświetlane w widgetach TkInter mają specjalne typy, np.: IntVar StringVar Powód: domyślne proste typy w Pythonie są niemutowalne. Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Praktyczny przykład Patrz plik jednostki.py na moodle W pliku znajduje się dużo dokumentacji, dokładnie wyjaśniającej działanie programu. Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie na rozgrzewkę Zmień program jednostki.py tak, aby : otrzymane cale były zaokrąglane do jedności w zależności od tego, jaki wyszedł wynik, ma się zmieniać etykieta przy wyniku (ta, która teraz zawsze ma wartość ”cali”), czyli: jeśli cyfra dziesiątek jest inna niż 1, a cyfra jedności to 2,3 lub 4, etykietą ma być ”cale” w przeciwnym wypadku, etykieta ma mieć wartość ”cali” Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Komunikacja z bazami danych Python Database API Specification v2.0 http://legacy.python.org/dev/peps/pep-0249/ specyfikacja API, zgodnie z którą powinny być przygotowywane biblioteki do komunikacji z bazami danych łatwe przejście pomiędzy różnymi bibliotekami i różnymi bazami danych Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( MySQL relacyjny system zarządzania bazami danych (RDBMS), dostępny na licencji wolnego oprogramowania GNU General Public Licence, rozwijany przez firmę Oracle, Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( PhpMyAdmin http://ego.kie.ue.poznan.pl/mysql-admin/ user: inz opr hasło: inz opr Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Biblioteki do komunikacji z MySQL Mysql Connector MySQLdb (na razie tylko Python 2) pymysql Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( pymysql - prosty przykład import pymysql 1 2 connection = pymysql . connect ( host = ’ ego . kie . ue . poznan . pl ’ , port = 8080 , user = ’ inz_opr ’ , passwd = ’ inz_opr ’ , database = ’ i n z y n i e r i a _ o p r o g r a m o w a n i a ’) cursor = connection . cursor () cursor . execute ( ’ select * from polaczenia ; ’) for i in cursor : print ( i ) 3 4 5 6 7 8 9 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Kursor Kursor jest to kontrolna struktura pośrednicząca w wykonywaniu zapytań i pozwalająca na iterowanie po ich wynikach. dla jednego połączenia z bazą możemy stworzyć wiele kursorów dzięki temu do jednego połączenia z bazą możemy wysyłać wiele różnych zapytań i łatwo operować na różnych kolekcjach otrzymanych wyników Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Dłuższy przykład – ładowanie danych do bazy Patrz plik data_upload.py za pomocą tego skryptu załadowano do bazy dane do zadania domowego UWAGA: ze względu na ustawienia bazy danych skrypt zwróci błąd (brak uprawnień użytkownika do zapisu) Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zmiany w bazie i zatwierdzanie wyników podobnie jak w przypadku zapisywania do pliku, wprowadzanie danych do bazy powinno być zakończone faktycznym potwierdzeniem wprowadzenia zmian aby to zrobić: na obiekcie połączenia używamy funkcji commit używamy menedżera kontekstu with... as... Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Wstęp do zadań w bazie danych przechowywane są analogiczne dane co w zajęciach z CSV zadanie polega na odpytywaniu bazy zgodnie z zadanymi kryteriami Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie 1 Wejściem są linijki odpowiedzialne za podłączenie się do bazy danych: 1 2 3 4 5 host port użytkownik hasło baza danych Baza danych ma strukturę analogiczną do bazy inzynieria_oprogramowania, dostępną na serwerze ego.kie.ue.poznan.pl Wyjściem ma być suma czasów trwania wszystkich połączeń (w sekundach) Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie 1 Przykładowe wejście ego . kie . ue . poznan . pl 8080 inz_opr inz_opr inzynieria_oprogramowania 1 2 3 4 5 Przykładowe wyjście 104956 1 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie 2 wejście analogiczne do zadania 1 + dodatkowe dwie krotki: krotka z identyfikatorami nadawców krotka z identyfikatorami odbiorców na wyjściu mają być zwrócone dwie krotki, gdzie pierwsza to suma sekund połączeń dla poszczególnych nadawców podanych w krotce wyjściowej, a druga to czas ostatniego połączenia odebranego przez odbiorców z drugiej krotki (w formacie ISO, skorzystaj z metody datetime.isoformat()) Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika ( Zadanie 2 Przykładowe wejście ego . kie . ue . poznan . pl 8080 inz_opr inz_opr inzynieria_oprogramowania (47 , 209 , 392) (5 , 42) 1 2 3 4 5 6 7 Przykładowe wyjście (2099 , 2073 , 2058) ( ’ 2006 -06 -01 T05 :16:00 ’ , ’ 2006 -06 -01 T07 :34:00 ’) 1 2 Komunikacja z bazami danych (MySQL) Graficzne interfejsy użytkownika (