# Table of Contents - [Laboratorium 2 | Języki Skryptowe](#laboratorium-2-j-zyki-skryptowe) - [Laboratorium 3 | Języki Skryptowe](#laboratorium-3-j-zyki-skryptowe) - [Laboratorium 9 | Języki Skryptowe](#laboratorium-9-j-zyki-skryptowe) - [Laboratorium 12 | Języki Skryptowe](#laboratorium-12-j-zyki-skryptowe) - [Języki Skryptowe | Języki Skryptowe](#j-zyki-skryptowe-j-zyki-skryptowe) - [Laboratorium 4 | Języki Skryptowe](#laboratorium-4-j-zyki-skryptowe) - [Laboratorium 7 | Języki Skryptowe](#laboratorium-7-j-zyki-skryptowe) - [Laboratorium 8 | Języki Skryptowe](#laboratorium-8-j-zyki-skryptowe) - [Laboratorium 1 | Języki Skryptowe](#laboratorium-1-j-zyki-skryptowe) - [Laboratorium 5 | Języki Skryptowe](#laboratorium-5-j-zyki-skryptowe) - [Laboratorium 10 | Języki Skryptowe](#laboratorium-10-j-zyki-skryptowe) - [Laboratorium 6 | Języki Skryptowe](#laboratorium-6-j-zyki-skryptowe) - [Laboratorium 11 | Języki Skryptowe](#laboratorium-11-j-zyki-skryptowe) --- # Laboratorium 2 | Języki Skryptowe [](#funkcja-id) Funkcja id() --------------------------------- funkcja `id()` pobiera obiekt i zwraca jego tożsamość, czyli adres pamięci wyrażony jako liczba całkowita Copy imie = "Tobiasz" print(id(imie)) # 1584889644528 liczby = [1, 2, 3] print(id(liczby)) # 1584889642496 [](#list) list ------------------- Listy w Pythonie to dynamiczne struktury danych, które pozwalają na przechowywanie wielu elementów w jednej zmiennej. Są one **mutowalne**, co oznacza, że można dodawać, usuwać i modyfikować elementy w liście. Definiuje się je, umieszczając elementy w nawiasach kwadratowych `[]`, oddzielając przecinkami. Copy # tworzenie listy lista = [1, 2, 3, 4, 5, 1, 1] print(lista) mix = [1, 2, "Python", 3.14, True, True] print(mix) indeksowanie i wycinanie (slicing) Copy # dostęp do pierwszego elementu (indeks 0) element = lista[0] print(element) # nadpisz wartość elementu na indeksie 2 lista[2] = 9 # wypisz trzeci element listy print(f"trzeci element to {mix[2]}") # wypisz elementy od indeksu 2 do indeksu 4 print(lista[2:4]) dodawanie i usuwanie Copy # dodaj element na końcu listy lista.append(7) # dodaj element w określonej pozycji na liście (indeks 2) lista.insert(2, "element") # usuwa i zwraca element (indeks 2) element = lista.pop(2) # usuń trzeci element listy (indeks 2) del lista[2] # usuń element o wartości 3 lista.remove(3) inne operacje Copy # zwraca liczbę elementów w liście dlugosc = len(lista) # liczba wystąpień określonego elementu lista.count(element) # sortowanie w kolejności rosnącej, oryginalna lista zostaje zmodyfikowana, zwraca None lista.sort() [](#tuple) tuple --------------------- Tuple _(pl krotka)_ są podobne do list, ale są **niemutowalne**, co oznacza, że **nie można zmieniać ich zawartości** po ich utworzeniu. Definiuje się je, umieszczając elementy w nawiasach okrągłych `()`, oddzielając przecinkami. Copy # tworzenie tuple krotka = ("jeden", "dwa", "trzy") mix_krotka = (1, 2, "Python", 3.14) print(f"wypisuje {krotka} oraz {mix_krotka}") indeksowanie i wycinanie (slicing) Copy # dostęp do drugiego elementu (indeks 1) element = krotka[1] print(element) # dodanie elementów jest możliwe poprzez stworzenie nowej zmiennej nowa_struktura = krotka + (1, 2) print(nowa_struktura) # utwórz nową tuple na podstawie istniejącej nowa = mix_krotka[1:3] niemutowalność oznacza, że nie można zmieniać ich zawartości Copy # błąd mix_krotka[1] = "nowy element" możemy rozpakować tuple bezpośrednio do zmiennych Copy a, b, c = krotka print(f"a: {a}, b: {b}, c: {c}") porównywanie leksykograficzne - każdy element jest porównywany w kolejności od pierwszego do ostatniego, możliwe jest porównywanie różnych typów danych o ile znajdują się na tych samych indeksach, krotka z większą ilością elementów jest traktowana jako większa Copy krotka_1 = (1, 2, 3) krotka_2 = (1, 2, 4) print(krotka_1 < krotka_2) # True [](#set) set ----------------- set _(pl zbiór)_ to struktura danych, która **reprezentuje nieuporządkowany zbiór unikalnych elementów** (nie ma duplikatów). Jest również mutowalny, a definiuje się go umieszczając elementy w nawiasach klamrowych `{}`, lub za pomocą funkcji `set()` Copy # tworzenie zbioru zbior_1 = {1, 2, 3, 4, 5} zbior_2 = set([3, 4, 5, 6, 7]) # nie może istnieć więcej niż jedna kopia tego samego elementu zbior_3 = {1, 2, 2, 3, 4, 4, 5} print(zbior_3) # {1, 2, 3, 4, 5} dodawanie i usuwanie elementów Copy # dodaj element do zbioru zbior_1.add(6) # sortowanie zwraca listę posortowana_lista = sorted(zbior_1) # usuń element ze zbioru zbior_1.remove(3) obsługują różne operacje matematyczne Copy A = {1, 2, 3, 4, 5} B = {5, 4, 3, 6, 7} # wszystkie unikalne elementy z obu zbiorów suma_logiczna = A | B # .union(), {1, 2, 3, 4, 5, 6, 7} # elementy wspólne dla obu zbiorów iloczyn = A & B # .intersection() {3, 4, 5} # elementy, które są w zbiorze A, ale nie ma ich w zbiorze B roznica_niesymetryczna = A - B # .difference() {1, 2} # elementy, które są w jednym ze zbiorów, ale nie w obu jednocześnie roznica_symetryczna = A ^ B # .symmetric_difference() {1, 2, 6, 7} # zbiory nie zachowują kolejności elementów print(B) # sprawdzenie przynależności elementu do zbioru print(2 in A) # True [](#warto-zapamietac) Warto zapamiętać ------------------------------------------- 1. _Czym się różni lista od tuple?_ Tuple są niemutowalneco oznacza, że nie możemy modyfikować ani usuwać danych wprowadzonych przy inicjalizacji, a listy są mutable czyli możemy edytować, usuwać i dodawać elementy. 2. _Jakie są korzyści stosowania tuple?_ Są efektywne pod względem pamięci, dane są odporne na przypadkową zmianę oraz można ich używać jako kluczy w słownikach, ponieważ są haszowalne 3. _Jakie jest zastosowanie zbiorów?_ Zbiory są przydatne do usuwania duplikatów z innych sekwencji takich jak listy, przechowywania unikalnych elementów oraz do wykonywania operacji matematycznych [](#zadania) Zadania ------------------------- _Uwaga: przy wykonywaniu zadań nie należy korzystać z pętli i instrukcji warunkowych_ 1. Napisz program, który tworzy listę zawierającą trzy kolory, a następnie za pomocą funkcji `append` dodaj dwa elementy i wypisz dwa pierwsze w konsoli używając `pop()` Ile elementów ma teraz lista? 2. Stwórz tuple zawierający nazwy dowolnych czterech zespołów. Następnie użyj funkcji `len`, aby sprawdzić, ile elementów znajduje się w tuple, i wyświetl tę liczbę. Wypisz strukturę posortowaną od Z do A. 3. Utwórz listę wielowymiarową reprezentującą macierz jednostkową _(posiada na przekątnej jedynki i poza przekątną same zera)_ o wymiarze 3x3, a następnie wypisz dowolny niezerowy jej element 4. Dla `"ala ma kota a kot ma ale"` wyświetl na ekranie **posortowane** znaki bez powtórzeń 5. Napisz program, który tworzy listę zawierającą temperatury w ciągu tygodnia, zakładając, że jeden dzień to jedna temperatura. Następnie użyj funkcji `sum` i `len`, aby obliczyć średnią temperaturę i wyświetl ją 6. Mając trzy listy liczb całkowitych `grupa_1, grupa_2, grupa_3 = [3, 5, 6, 7, 8], [5, 7, 9, 10], [7, 10, 11, 12]`, należy **nie używając pętli**: * wypisać elementy, które są wspólne we wszystkich zbiorach * wypisać wszystkie unikalne elementy ze zbiorów * wypisać elementy obecne w przynajmniej dwóch zbiorach 7. Napisz program, który zlicza liczbę unikalnych słów w wpisanym przez użytkownika tekście bez użycia pętli. Powinien ignorować wielkość liter (czyli słowa "Python" i "python" liczyć jako to samo słowo) oraz znaki interpunkcyjne. Należy wypisać wynik w porządku alfabetycznym. **input:** `"Python to dobry wybór języka programowania, python jest przyjemny do nauki"` **output:** `['do', 'dobry', 'jest', 'języka', 'nauki', 'przyjemny', 'programowania', 'python', 'to', 'wybór']` 8. \*\* Napisz program, który przyjmie dwa zdania jako dane wejściowe. Program powinien znaleźć wszystkie litery (bez uwzględniania wielkości liter), które występują w obu zdaniach, i wypisać je w porządku alfabetycznym, bez powtórzeń. **input:** `zdanie_1, zdanie_2 = "Ala ma kota", "Czy kota ma Ala czy nie ma?"` **output:** `['a', 'k', 'l', 'm', 'o', 't']` [PreviousLaboratorium 1](/jezyki-skryptowe/laboratorium-1) [NextLaboratorium 3](/jezyki-skryptowe/laboratorium-3) Last updated 4 months ago --- # Laboratorium 3 | Języki Skryptowe [](#instrukcje-warunkowe) Instrukcje warunkowe --------------------------------------------------- Instrukcja warunkowa `if` pozwala na wykonanie określonego bloku kodu, jeśli warunek jest spełniony i opcjonalnie innego bloku, jeśli warunek nie jest spełniony Copy if warunek: # kod do wykonania else: # kod do wykonania Copy wiek = 18 if wiek >= 18: print("Jesteś pełnoletni") if 18 <= wiek <= 25: print("Jesteś osobą dorosłą, mającą co najwyżej 25 lat") else: # kod do wykonania # wersja uproszczona wynik = "Pełnoletni" if wiek >= 18 else "Niepełnoletni" print(wynik) Instrukcja warunkowa `if`...`elif`...`else` pozwala na przetestowanie wielu warunków i wykonywanie odpowiedniego bloku kodu w zależności od pierwszego spełnionego warunku. Copy if warunek1: # kod do wykonania elif warunek2: # kod do wykonania else: # kod do wykonania Copy ocena = 85 if ocena >= 90: print("Ocena: A") elif ocena >= 80: print("Ocena: B") elif ocena == 70: print("Ocena: C") else: print("Ocena: D") Operatory logiczne, takie jak `and`, `or`, `not`, pozwalają na łączenie warunków w bardziej zaawansowane wyrażenia warunkowe. Copy if warunek1 and warunek2: # kod do wykonania, jeśli oba warunki są spełnione if warunek1 or warunek2: # kod do wykonania, jeśli przynajmniej jeden z warunków jest spełniony if not warunek: # kod do wykonania, jeśli warunek nie jest spełniony Wyrażenia warunkowe mają zwięzłą formę której można użyć w jednej linii. Copy wartosc_jezeli_prawda if warunek else wartosc_jezeli_falsz wynik = "Tak" if punkty >= 50 else "Nie" [](#petle) Pętle --------------------- Pętla `for` jest używana do iterowania przez sekwencje lub iterowalne obiekty. Copy for element in sekwencja: # kod do wykonania owoce = ["jabłko", "banan", "gruszka"] for owoc in owoce: print(owoc) Pętla `while` wykonuje blok kodu, dopóki warunek jest spełniony. Pozwala na powtarzanie operacji, dopóki określony warunek jest prawdziwy. Copy while warunek: # kod do wykonania licznik = 0 while licznik < 5: print(licznik) licznik += 1 Możemy korzystać z dodatkowych instrukcji do kontroli przepływu programu: * `break` jest używana do całkowitego przerwania pętli * `continue` pomija bieżącą iterację pętli i przechodzi do następnej iteracji Copy owoce = ["jabłko", "banan", "gruszka"] for owoc in owoce: if owoc == "banan": break print(owoc) [](#dict) dict ------------------- Słownik w Pythonie to struktura, która reprezentuje _kolekcję par klucz - wartość_. Jest to dynamiczna i mutowalna struktura, w której **każdy element jest identyfikowany za pomocą unikalnego klucza**. Definiuje się go, umieszczając pary klucz-wartość w nawiasach klamrowych `{}` Copy # tworzenie słownika panstwa = { 'Polska': 'Warszawa', 'Niemcy': 'Berlin', 'Francja': 'Paryż' } # są elastyczne i pozwalają na przechowywanie # różnych typów danych jako kluczy i wartości slownik = { 'imie': 'Tadeusz', 42: 'Nauka', (1, 2): [1, 2, 3], True: {'matematyka': 95, 'historia': 80} } istnieją dwa sposoby na dostęp do wartości w słowniku po kluczu Copy # dostęp bezpośrednio za pomocą klucza stolica = panstwa['Polska'] # dostęp za pomocą metody get() stolica = panstwa.get('Polska') dodawanie, modyfikowanie i usuwanie **Wartości w słownikach są unikalne pod względem kluczy, więc przypisanie do istniejącego klucza spowoduje nadpisanie starej wartości nową** Copy # dodanie pary do słownika ['klucz'] = wartość panstwa['Anglia'] = 'Londyn' # zmiana wartości panstwa['Niemcy'] = 'Monachium' # usunięcie pary del panstwa['Francja'] iterowanie po słownikach Copy panstwa = {'Polska': 'Warszawa', 'Niemcy': 'Berlin', 'Francja': 'Paryż'} # iterowanie po kluczach for kraj in panstwa: print(kraj) # iterowanie po wartościach for stolica in panstwa.values(): print(stolica) # iterowanie po parach klucz-wartość for kraj, stolica in panstwa.items(): print(f"{kraj}: {stolica}") wartości domyślne Copy # używanie wartości domyślnych w słowniku pozwala uniknąć błędów # w przypadku próby dostępu do nieistniejącego klucza klucz = 'Grecja' # jeśli klucz nie istnieje zwrócona zostanie wartość domyślna wartosc = panstwa.get(klucz, 'Nie znaleziono') print(f"Stolica państwa {klucz} to {wartosc}") # można też sprawdzić czy klucz istnieje wcześniej if 'Grecja' in panstwa: # wykonaj kod inne operacje Copy # zwraca liczbę par w słowniku dlugosc = len(panstwa) # lista kluczy panstwa.keys() # lista wartości panstwa.values() # wyczyść słownik panstwa.clear() [](#warto-zapamietac) Warto zapamiętać ------------------------------------------- list tuple set dictionary ordered ordered unordered unordered mutable immutable mutable mutable duplicates allowed duplicates allowed no duplicates no duplicate keys \[ value \] ( value ) { value } { key : value } 1. _Jakie są różnice między słownikami (_`_dict_`_) a zbiorami (_`_set_`_) w Pythonie?_ **Słowniki** przechowują dane w postaci par klucz-wartość. Klucze muszą być unikalne, podczas gdy wartości mogą być dowolne. **Zbiory** przechowują tylko unikalne elementy, bez przypisanych wartości. Są przydatne do przechowywania elementów, gdzie ważna jest unikalność. 2. _Jak działa metoda_ `_get()_` _w słownikach i kiedy należy ją stosować zamiast bezpośredniego dostępu do wartości?_ Metoda `get()` zwraca wartość przypisaną do danego klucza, jeśli klucz istnieje, lub wartość domyślną. Zapobiega błędom typu `KeyError`, które mogą wystąpić, gdy próbujemy uzyskać dostęp do nieistniejącego klucza. [](#zadania) Zadania ------------------------- 1. Napisz program, który tworzy zmienną `liczba: int` na podstawie inputu użytkownika i sprawdza, czy jest ona parzysta czy nieparzysta, a następnie: * jeżeli `liczba` jest parzysta wypisz wszystkie parzyste liczby od 0 do `liczba` * jeżeli `liczba` jest nieparzysta wypisz wszystkie nieparzyste liczby od 0 do `liczba` 2. Używając funkcji `random()` z zaimportowanego modułu `random` wygeneruj **liczbę całkowitą z przedziału 0 do 10**. Poinformuj użytkownika, że ma 3 próby na zgadnięcie liczby, po każdej próbie należy wyświetlić odpowiednią instrukcję "Za duża", "Za mała", "Zgadłeś!" 3. Napisz program, który przyjmuje od użytkownika ciąg znaków (string) i odwraca go za pomocą pętli. Na przykład dla słowa "Python" wynikiem będzie "nohtyP". 4. Napisz skrypt który pobierze od użytkownika listę 3 wyrazów, a następnie sprawdzi czy lista zawiera duplikat (czy zostały wpisane dwa takie same wyrazy) oraz czy jakieś słowo ma więcej niż 5 znaków. Wypisz odpowiednią wiadomość. 5. Stwórz słownik przechowujący konfigurację Copy konfiguracja = { 'rozmiar_czcionki': 12, 'jezyk': 'pl', 'tryb_nocny': True, } * zmień język na angielski i wyłącz tryb nocny * dodaj klucz `'wersja_systemu'` z wartością typu _float_ * za pomocą funkcji `values()` wypisz wszystkie wartości konfiguracji 6. Utwórz dwa słowniki Copy studenci_uken = { '12345': 'Jan Jesienny', '67890': 'Anna Angielska', } studenci_ur = { '09876': 'Piotr Poranny', '54321': 'Mariusz Murowany', } * wykorzystaj **jedną funkcję** która pozwoli na połączenie danych w jeden słownik o nazwie `studenci` * za pomoca `get()` wyświetl studenta o numerze indeksu _09876_ oraz _43210_, zabezpiecz się przed sytuacją gdzie w słowniku nie będzie danego klucza * poproś użytkownika aby podał numer indeksu, a następnie imię i nazwisko studenta, którego dodasz do struktury `studenci` * używając `print` i `f-string` wypisz wszystkich studentów wraz z ich sumaryczną liczbą 7. Stwórz słownik w którym kluczami będą trzy ostatnie daty w formacie 'YYYY-MM-DD', a wartościami wyniki dużego lotka w formie krotki. Sprawdź działanie`.keys()` i `.values()` dla tej struktury, następnie ją wyczyść i sprawdź ponownie 8. \*\* Napisz program kalkulatora, który działa w nieskończonej pętli, umożliwiając użytkownikowi wykonywanie wielu operacji matematycznych. Użytkownik powinien mieć możliwość wprowadzenia dwóch liczb i wyboru operatora (+, -, \*, /) do wykonania operacji. Wynik operacji powinien być wyświetlany, a użytkownik powinien mieć opcję kontynuowania obliczeń lub zakończenia programu. [PreviousLaboratorium 2](/jezyki-skryptowe/laboratorium-2) [NextLaboratorium 4](/jezyki-skryptowe/laboratorium-4) Last updated 4 months ago --- # Laboratorium 9 | Języki Skryptowe [](#uruchamianie-skryptu) Uruchamianie skryptu --------------------------------------------------- 1. W terminalu przejdź do folderu, w którym znajduje się plik `skrypt.py` 2. Wpisz polecenie `python3 skrypt.py` lub `python skrypt.py` Kiedy uruchamiamy skrypt, interpreter wykonuje kod w tym skrypcie. Jednak w przypadku, gdy skrypt jest importowany do innego skryptu jako moduł, nie chcemy, aby cały kod został natychmiastowo wykonany do czego służy nam struktura `if __name__ == "__main__"` Copy def powitanie(imie): print(f"Witaj, {imie}!") def main(): imie = input("Podaj imię: ") powitanie(imie) # kod w main() zostanie uruchomiony tylko # gdy skrypt jest uruchamiany bezpośrednio if __name__ == "__main__": main() * uruchomienie bezpośrednie np. python witaj.py lub Run w PyCharm -> warunek `if __name__ == "__main__":` zostanie spełniony, a funkcja `main()` zostanie wywołana * `__name__` to specjalna zmienna w Pythonie, która w przypadku bezpośredniego uruchomienia skryptu ma wartość `"__main__"` * jeśli w innym skrypcie zaimportujemy `witaj.py` poprzez `import witaj` to kod wewnątrz nie uruchomi się automatycznie, ponieważ warunek `__name__ == "__main__"` nie będzie spełniony, będzie trzeba jawnie wywołać funkcję `powitanie(imie)` * kiedy skrypt jest importowany jako moduł, `__name__` ma wartość równą nazwie tego modułu np. `skrypt.py` [](#argparse) argparse --------------------------- Moduł `argparse` jest przydatnym narzędziem do obsługi argumentów podawanych wierszem poleceń w skryptach. Pozwala to na bardziej interaktywne korzystanie z programów, umożliwiając użytkownikom dostarczanie danych bezpośrednio z linii poleceń, zamiast wprowadzania ich bezpośrednio w kodzie. Copy import argparse def main(): parser = argparse.ArgumentParser(description="Witaj") parser.add_argument("imie", type=str, help="Imię użytkownika") args = parser.parse_args() imie = args.imie print(f"Hello {imie}!") if __name__ == "__main__": main() Zapisz plik jako `witaj.py`, a następnie uruchom skrypt przekazując swoje imię jako argument Copy python3 witaj.py Janusz Copy import argparse def main(): parser = argparse.ArgumentParser(description="Samochody") parser.add_argument("--marka", type=str, required=True, help="Marka samochodu") parser.add_argument("--konie", type=int, required=True, help="Liczba koni mechanicznych") args = parser.parse_args() marka = args.marka konie = args.konie print(f"Samochód marki {marka} ma {konie} koni mechanicznych.") if __name__ == "__main__": main() Zapisz plik jako `samochod.py`, a następnie uruchom skrypt przekazując argumenty Copy python3 samochod.py --marka Ford --konie 150 **Argumenty pozycyjne vs. opcjonalne** * przekazywane są bezpośrednio po nazwie skryptu, `Jan` jest argumentem pozycyjnym * są poprzedzone znakiem `--` lub `-`, w przykładzie `--marka` i `--konie` to argument opcjonalny inne przykładowe operacje Copy parser.add_argument("liczba", type=float, help="Liczba") parser.add_argument("--operacja", type=str, choices=["dodaj", "odejmij", "mnoz", "dziel"], default="dodaj", help="Rodzaj operacji matematycznej (domyślnie: dodaj)") [](#getenv-i-environ) getenv i environ ------------------------------------------- Są używane do dostępu do zmiennych środowiskowych, ustawionych na poziomie systemu operacyjnego. `os.getenv` - ta funkcja pozwala na odczytanie wartości zmiennej środowiskowej o podanej nazwie. Jeśli zmienna o danej nazwie nie istnieje, funkcja zwraca wartość domyślną (lub `None`, jeśli nie podano wartości domyślnej). Copy import os username = os.getenv('USERNAME', 'Brak użytkownika') print(f'Użytkownik: {username}') `os.environ` - to słownik reprezentujący wszystkie zmienne środowiskowe dostępne dla danego procesu Pythona. Działa jak standardowy słownik, pozwala na odczyt i ustawianie wartości zmiennych środowiskowych w nim. Copy import os for key, value in os.environ.items(): print(f'{key}: {value}') os.environ['MY_VARIABLE'] = 'Hello, World!' print('MY_VARIABLE:', os.environ['MY_VARIABLE']) [](#exit) exit ------------------- `sys.exit()` pozwala na zakończenie działania programu z określonym kodem wyjścia **0** \- oznacza sukces, program zakończył się pomyślnie bez żadnych błędów Copy sys.exit(0) **1** \- wartości większe oznaczają błędy i sytuacje wyjątkowe, popularna 1 wskazuje, że program zakończył się ze względu na ogólny błąd Copy sys.exit(1) **inne** \- w zależności od sytuacji możemy stosować inne wartości aby reprezentować różne błędy Copy import sys import getpass def main(): try: username = getpass.getuser() if username == "guest": print("Gość nie ma dostępu") sys.exit(2) else: print(f"Witaj, {username}! Program działa poprawnie") sys.exit(0) except Exception as e: print(f"Błąd: {e}") sys.exit(1) if __name__ == "__main__": main() [](#zadania) Zadania ------------------------- 1. Napisz program, który przyjmuje dwa argumenty z linii poleceń: `--name` (imię) i `--age` (wiek). Program powinien wyświetlić komunikat powitalny, zawierający podane imię i wiek. 2. Napisz program, który sprawdza, czy istnieje zmienna środowiskowa o nazwie `USER_NAME`. Jeśli taka zmienna istnieje to ją wyświetlić, w przeciwnym razie wyświetlić komunikat o błędzie. 3. Napisz program, który sprawdza dostęp do zasobu na podstawie zmiennej środowiskowej `ACCESS_LEVEL`. Należy sprawdzić poziom dostępu z puli `user`, `admin`, `guest`. Program powinien wyświetlić komunikat z odpowiednim poziomem dostępu oraz zwracać zaproponowany dla różnych sytuacji kod wyjścia używając `sys.exit()` 4. Napisz skrypt w Pythonie, który zbiera informacje o systemie operacyjnym i zmiennych środowiskowych, a następnie zapisuje te dane do pliku: 1. zaproponuj pięć zmiennych systemowych, np. `OS, USERNAME`, więcej [https://github.com/putridparrot/EnvironmentVariableCheatsheet](https://github.com/putridparrot/EnvironmentVariableCheatsheet) 2. dane o systemie operacyjnym za pomocą modułu`platform`, więcej [https://docs.python.org/3/library/platform.html](https://docs.python.org/3/library/platform.html) 3. pamiętaj o dodaniu daty i godziny do raportu, moduł datetime, więcej [https://docs.python.org/3/library/datetime.html](https://docs.python.org/3/library/datetime.html) 4. każde ponowne uruchomienie skryptu doda kolejny wpis do pliku z raportem 5. \* zaimportuj moduł csv i zapisz dane do pliku CSV używając kodowania utf-8 i funkcji `csv.writer()`, więcej [https://cwsi.pl/python/tutorial/pliki-csv-i-python-odczyt-i-zapis/](https://cwsi.pl/python/tutorial/pliki-csv-i-python-odczyt-i-zapis/) CSV to strukturalny format, który przechowuje dane w postaci tabeli, gdzie wiersze reprezentują rekordy, a kolumny są oddzielone separatorem którym najczęściej jest przecinek. Umożliwia przechowywanie danych w sposób zorganizowany. [PreviousLaboratorium 8](/jezyki-skryptowe/laboratorium-8) [NextLaboratorium 10](/jezyki-skryptowe/laboratorium-10) Last updated 2 months ago --- # Laboratorium 12 | Języki Skryptowe [PreviousLaboratorium 11](/jezyki-skryptowe/laboratorium-11) Last updated 1 month ago ![](https://patrykmieczkowski.gitbook.io/~gitbook/image?url=https%3A%2F%2F2543652666-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FaqxQY9YT9dvCIjrjMDzZ%252Fuploads%252FQCUqiZ4Ku9WW4XGqC5fv%252Fgiphy.gif%3Falt%3Dmedia%26token%3D513e071e-698b-481d-95b9-b33d1e0ca75f&width=768&dpr=4&quality=100&sign=6417a1bc&sv=2) --- # Języki Skryptowe | Języki Skryptowe ![Page cover image](https://static.gitbook.com/_next/static/media/default-page-cover.a2ccd7e9.svg) Python to popularny, wieloparadygmatowy język programowania, który został stworzony przez Guido van Rossuma i po raz pierwszy wydany w 1991 roku. Jest powszechnie używany w różnych dziedzinach, w tym w tworzeniu aplikacji internetowych, analizie danych, sztucznej inteligencji i wielu innych. Python wyróżnia się swoją czytelnością i prostotą składni, co czyni go doskonałym językiem zarówno dla początkujących, jak i doświadczonych programistów. [NextLaboratorium 1](/jezyki-skryptowe/laboratorium-1) Last updated 4 months ago --- # Laboratorium 4 | Języki Skryptowe [](#funkcje) Funkcje ------------------------- Funkcje są definiowane za pomocą słowa kluczowego `def`, po którym podajemy nazwę funkcji i nawiasy okrągłe, w których znajdują się nazwy argumentów. Copy def say_hello(): print(f"Hello") def say_hello_to(name): print(f"Hello {name}") Po zdefiniowaniu funkcji, możemy ją wywołać, używając jej nazwy i nawiasów okrągłych. Copy say_hello() # wywołanie funkcji bez argumentów say_hello_to("Jack") # wywołanie funkcji z jednym argumentem Funkcje mogą również zwracać wartość za pomocą słowa kluczowego `return`. To pozwala na przechwytywanie wyniku funkcji i korzystanie z niego w innych częściach programu. Copy def razy_dwa(liczba): return liczba * 2 wynik = razy_dwa(5) print(wynik) # 10 def funkcja_zwracajaca_liste(): return [1, 2, 3] wynik = funkcja_zwracajaca_liste() print(wynik) # [1, 2, 3] Mogą występować z wieloma argumentami umieszczonymi po przecinku, za pomocą `*args` (dla argumentów pozycyjnych) lub `**kwargs` (dla argumentów klucz-wartość). Copy # przyjmuje cztery argumenty w określonej kolejności def pomnoz(a, b, c, d): return a * b * c * d wynik = pomnoz(5, 5, 5, 5) print(wynik) # 625 # przyjmuje dowolną ilość argumentów def suma(*args): wynik = 0 for liczba in args: wynik += liczba return wynik wynik = suma(1, 2, 3, 4, 5) print(wynik) # 15 # przyjmuje dowolną ilość nazwanych argumentów def informacje_o_mieszkancach(**kwargs): for kraj, liczba_mieszkancow in kwargs.items(): print(f"{kraj}: {liczba_mieszkancow} mln mieszkańców") informacje_o_mieszkancach(Polska=38, Niemcy=83, USA=331, Chiny=1440) Możemy nadać argumentom domyślne wartości, co sprawia, że są one opcjonalne podczas wywoływania funkcji. **Argumenty z domyślną wartością muszą znajdować się na końcu.** Copy def witaj(imie="Nieznajomy"): print("Witaj, " + imie + "!") witaj("Orfeuszu") # Witaj, Orfeuszu! witaj() # Witaj, Nieznajomy! def witaj(imie, miasto="Nieznane"): print(f"Witaj {imie} z miasta: {miasto}") witaj("Herkules") witaj("Herkules", "Rzym") Argumenty są przekazywane przez referencję, jeśli są to mutowalne obiekty (np. listy), a przez wartość w przypadku typów niemutowalnych (np. liczby, krotki, łańcuchy). Dlatego zmiana obiektu wewnątrz funkcji może wpłynąć na dane w kodzie wywołującym Copy def zmien_lista(wew_lista): wew_lista.append(4) moja_lista = [1, 2, 3] zmien_lista(moja_lista) print(moja_lista) # [1, 2, 3, 4] - moja_lista została zmodyfikowana [](#zakres) Zakres ----------------------- **Zmienna zdefiniowana wewnątrz funkcji ma lokalny zakres i nie jest dostępna poza nią.** Jest to scope (zakres) globalny lub lokalny. Copy x = 1 # global scope def moja_funkcja(): x = 1 # global scope def moja_funkcja(): y = 2 # local scope print(f"x = {x}, y = {y}") print(f"x = {x}, nie ma dostępu do zmiennej y spoza funkcji") def funkcja_z_globalna_zmienna(): global z z = 3 funkcja_z_globalna_zmienna() print(f"mam dostęp do globalnej zmiennej z = {z}") [](#losowe-wartosci) Losowe wartości ----------------------------------------- Moduł `random` w Pythonie dostarcza narzędzi do generowania pseudolosowych danych. Copy # zaczynamy od wprowadzenia modułu random do naszego programu import random losowa_liczba = random.random() print(losowa_liczba) # zakres 0.0 - 1.0 losowa_liczba = random.randint(1, 10) print(losowa_liczba) # wprowadzony zakres 1 - 10 lista = [1, 2, 3, 4, 5] losowy_element = random.choice(lista) print(losowy_element) # losowy element z wprowadzonego zakresu lista = [1, 2, 3, 4, 5] random.shuffle(lista) print(lista) # wypisuje listę z przetasowaną kolejnością [](#warto-zapamietac) Warto zapamiętać ------------------------------------------- 1. _Zalecenia i dobre praktyki podczas definiowana funkcji_ * nazewnictwo funkcji `snake_case` * unikanie zbyt długich funkcji * staranność przy wyborze nazw argumentów, czytelność 2. _Zakres lokalny vs globalny_ Zmienna lokalna jest dostępna tylko wewnątrz funkcji, a zmienna globalna jest dostępna w całym programie. Instrukcja `global` służy do wskazania z poziomu funkcji, że wybrana zmienna jest zmienną globalną 3. _W jaki sposób można dostosować funkcję do obsługi różnej ilości danych wejściowych?_ `*args` pozwala na przekazywanie nieograniczonej liczby argumentów pozycyjnych, a `**kwargs` pozwala na przekazywanie argumentów w formie par klucz-wartość [](#zadania) Zadania ------------------------- 1. Napisz funkcję która przyjmie dwie wartości liczbowe i zwróci większą z nich (należy użyć `max`) 2. Napisz funkcję która przyjmie listę liczb jako jeden argument i zwróci ich sumę 3. Napisz funkcję która przyjmie dowolnie długą listę liczb (użyj `*args`) i zwróci najmniejszą z nich (należy użyć `min`) 4. Napisz funkcję która poprosi użytkownika o podanie jego imienia, a następnie doda je do globalnej listy imion i wypisze w konsoli 5. Napisz grę papier, kamień, nożyce używając minimum trzech funkcji * w pierwszym kroku zostanie pobrana figura od użytkownika * następnie system wylosuje wybór przeciwnika za pomocą modułu _random_ * za pomocą instrukcji warunkowej zdecyduje i wypisze kto jest zwycięzcą * \*\*dodanie możliwości ponownej rozgrywki w ramach jednego uruchomienia programu * \*\*dodanie tablicy wyników [PreviousLaboratorium 3](/jezyki-skryptowe/laboratorium-3) [NextLaboratorium 5](/jezyki-skryptowe/laboratorium-5) Last updated 3 months ago --- # Laboratorium 7 | Języki Skryptowe Stwórz program, który wczytuje dane o książkach z pliku tekstowego, a następnie przetwarza je za pomocą _lambda function_ lub _list comprehension:_ 1. należy wczytać plik tekstowy _books.txt_ pamiętając o obsłudze błędów zawierający min. 6 książek z danymi:`Tytuł książki, Autor, Rok wydania, Liczba stron`, np. Władca Pierścieni, Tolkien, 1954, 1216 Harry Potter, Rowling, 1997, 309 2. i zapisać je w formie listy zawierającej słowniki, np. `[{"tytul": "Władca Pierścieni", "autor": "Tolkien", "rok": 1954, "strony": 1216}, ...]` _\* aby dostać do się do konkretnego pola można użyć notacji_ `book["tytul"]` _lub_ `book["autor"]` 3. a następnie w osobnych funkcjach: 1. obliczyć średnią liczbę stron w książkach 2. posortować książki alfabetycznie po tytule 3. znaleźć autorów, którzy mają więcej niż jedną książkę w spisie 4. **\[do zrobienia\]** wyfiltrować książki wydane po 2000 roku, mające więcej niż 500 stron 5. **\[do zrobienia\]** wyfiltrować tytuły, które składają się z dwóch lub więcej słów Copy def wczytaj_ksiazki(nazwa_pliku): try: with open(nazwa_pliku, 'r') as plik: linie = plik.readlines() ksiazki = [\ {\ "tytul": linia.split(',')[0].strip(),\ "autor": linia.split(',')[1].strip(),\ "rok": int(linia.split(',')[2].strip()),\ "strony": int(linia.split(',')[3].strip())\ }\ for linia in linie\ ] return ksiazki except FileNotFoundError: print(f"{nazwa_pliku} nie został znaleziony") return None except Exception as e: print(f"Błąd: {e}") return None def srednia_stron(ksiazki): suma_lambda = sum(map(lambda ksiazka: ksiazka["strony"], ksiazki)) # opcja 1 suma_skladana = sum([ksiazka["strony"] for ksiazka in ksiazki]) # opcja 2 return suma_lambda / len(ksiazki) def sortowanie_po_tytule(ksiazki): sortowanie_lambda = sorted(ksiazki, key=lambda ksiazka: ksiazka["tytul"]) # opcja 1 sortowanie_skladana = [ksiazka for ksiazka in sorted(ksiazki, key=lambda ksiazka: ksiazka["tytul"])] # opcja 2 return sortowanie_skladana def autorzy(ksiazki): # opcja 1 lista_autorow_lambda = list(map(lambda ksiazka: ksiazka["autor"], ksiazki)) unikalni_autorzy = set(lista_autorow_lambda) wystapienia = filter(lambda autor: lista_autorow_lambda.count(autor) > 1, unikalni_autorzy) # dla każdego unikalnego autora sprawdzamy czy pojawia się więcej niż raz return list(wystapienia) # opcja 2 # lista_autorow = [ksiazka["autor"] for ksiazka in ksiazki] # return [autor for autor in set(lista_autorow) if autorzy.lista_autorow(autor) > 1] # Znalezienie autorów, którzy mają więcej niż jedną książkę z użyciem list comprehension def autorzy_wiecej_niz_jedna_lista(ksiazki): autorzy = [ksiazka["autor"] for ksiazka in ksiazki] return [autor for autor in set(autorzy) if autorzy.count(autor) > 1] def biblioteka(): books = wczytaj_ksiazki("books.txt") if books is not None and len(books) > 0: print(f"Poprawnie wczytano {len(books)} książek: {books}") print(f"Średnia liczba stron: {int(round(srednia_stron(books), 0))}") print(f"Sortowanie alfabetyczne: {sortowanie_po_tytule(books)}") print(f"Autorzy występujący więcej niż raz: {autorzy(books)}") autorzy(books) else: print("Brak danych do przetworzenia") biblioteka() [](#zadanie-zgadnij-liczbe) Zadanie "Zgadnij liczbę" --------------------------------------------------------- każdy logiczny moduł gry to osobna funkcja proszę pamiętać o obsłudze błędów i kontroli typów 1. Program pyta gracza o nick 2. Program losuje liczbę z zakresu od 1 do 100 3. Po zakończonej rozgrywce są dostępne ustawienia w których można zmienić zakres na łatwy (20), normalny (100) oraz trudny (500) 4. Użytkownik ma za zadanie zgadnąć liczbę, podając swoje propozycje, program udziela podpowiedzi, czy wprowadzona liczba jest większa, mniejsza lub równa wylosowanej 5. Gra kończy się, gdy użytkownik odgadnie liczbę lub osiągnie maksymalną liczbę 10 prób 6. Po zakończeniu gry program podaje informację po jakim czasie licząc od wylosowania i po ilu próbach nastąpił koniec 7. Gra pyta, czy użytkownik chce zagrać ponownie 8. \*\* po każdej rozgrywce wyniki w formacie `nick, poziom trudności, czas, ilość prób, czy wygrana` zapisywane są do pliku `highscores.txt`, po zakończeniu programu i uruchomieniu ponownie nie należy czyścić pliku tylko kontynuować dopisywanie wyników 9. \*\* w ustawieniach można sprawdzić jaki średni czas był potrzebny na zwycięstwo na różnych poziomach trudności [PreviousLaboratorium 6](/jezyki-skryptowe/laboratorium-6) [NextLaboratorium 8](/jezyki-skryptowe/laboratorium-8) Last updated 3 months ago --- # Laboratorium 8 | Języki Skryptowe [](#zakres-zmiennych) Zakres zmiennych ------------------------------------------- ### [](#zakres-lokalny-local) Zakres lokalny (local) Zmienna zdefiniowana wewnątrz funkcji jest dedykowana tylko dla tej funkcji, nie jest widoczna poza nią. Copy def moja_funkcja(): zmienna_lokalna = 11 print(zmienna_lokalna) moja_funkcja() # print(zmienna_lokalna) # błąd ### [](#zakres-globalny-global) Zakres globalny (global) Zmienna zdefiniowana poza funkcją lub blokiem kodu jest globalna jeżeli chcemy ją odczytywać wewnątrz funkcji. Copy zmienna_globalna = 11 def funkcja(): print(zmienna_globalna) funkcja() _nadmierne używanie zmiennych globalnych może prowadzić do trudności w utrzymaniu kodu_ Nie mamy możliwości zmiany wartości zmiennej `zmienna_globalna`. Jeżeli to zrobimy to utworzona zostanie nowa lokalna zmienna o takiej samej nazwie, żeby edytować wartość istniejącej należy użyć słowa kluczowego `global`. Copy zmienna_globalna = 11 def moja_funkcja(): global zmienna_globalna zmienna_globalna += 1 moja_funkcja() print(zmienna_globalna) # Wynik: 12 ### [](#zakres-nielokalny-nonlocal) Zakres nielokalny (nonlocal) Zmienna jest zagnieżdżona w funkcji, ale nie jest w niej zdefiniowana, możemy użyć słowa kluczowego `nonlocal`, aby wskazać, że chcemy odwoływać się do zmiennej spoza zakresu lokalnego, ale nie jest to zmienna globalna. Copy def zewnetrzna_funkcja(): zmienna_nielokalna = 11 def wewnetrzna_funkcja(): nonlocal zmienna_nielokalna zmienna_nielokalna += 1 print(zmienna_nielokalna) wewnetrzna_funkcja() zewnetrzna_funkcja() [](#funkcje) Funkcje ------------------------- ### [](#funkcje-zagniezdzone) Funkcje zagnieżdżone Jest to funkcja zdefiniowana wewnątrz innej funkcji, ma dostęp do jej zmiennych lokalnych. Copy def zewnetrzna(value): def wewnetrzna(): print(value) return wewnetrzna zewnetrzna("Hello")() def funkcja_zewnetrzna(x): def funkcja_wewnetrzna(y): return x + y return funkcja_wewnetrzna wynik = funkcja_zewnetrzna(1)(2) print(wynik) # wynik: 3 Copy def oblicz_podatek(cena, stawka_podatku): # funkcja zagnieżdzona, implementacja ukryta, a kod czytelny def oblicz_podatek_ze_stawka(cena): return cena * stawka_podatku podatek = oblicz_podatek_ze_stawka(cena) cena_z_podatkiem = cena + podatek return cena_z_podatkiem # Przykładowe użycie cena = 100 stawka_podatku = 0.23 cena_z_podatkiem = oblicz_podatek(cena, stawka_podatku) print(f"Cena z podatkiem: {cena_z_podatkiem}") # 123.0 ### [](#domkniecia-closures) Domknięcia (closures) To sytuacja w której dane spoza zakresu lokalnego funkcji są trwale dołączane do maszynowego kodu funkcji. W skrócie, funkcja zagnieżdżona "zapamiętuje" stan zmiennych z czasu swojego utworzenia. * musi istnieć funkcja zagnieżdżona * funkcja zagnieżdżona musi odnosić się do zmiennych zdefiniowanych poza jej zakresem lokalnym - w funkcji zamykającej * funkcja zamykająca musi zwracać funkcję zagnieżdżoną Copy def funkcja_zewnetrzna(x): def funkcja_wewnetrzna(y): return x + y return funkcja_wewnetrzna domkniecie = funkcja_zewnetrzna(1) wynik = domkniecie(2) print(wynik) # wynik: 3 W powyższym przykładzie `funkcja_wewnetrzna` jest funkcją zagnieżdżoną, a `funkcja_zewnetrzna` zwraca tę funkcję. Gdy wywołujemy `funkcja_zewnetrzna(1)`, tworzymy domknięcie funkcji, które pamięta wartość `x` (równą 1). Później możemy wywołać to domknięcie z argumentem `2` co skutkuje wynikiem `3`. Copy def stawka_podatku(stawka): def oblicz_podatek(cena): return cena * stawka return oblicz_podatek # obliczenie podatku przy różnych stawkach oblicz_podatek_23 = stawka_podatku(0.23) oblicz_podatek_5 = stawka_podatku(0.05) cena = 100 print(f"Podatek 23%: {oblicz_podatek_23(cena)}") # 23.0 print(f"Podatek 5%: {oblicz_podatek_5(cena)}") # 5.0 **Domknięcie to funkcja zagnieżdżona, która "zapamiętuje" i ma dostęp do zmiennych ze swojego zewnętrznego zakresu, nawet po zakończeniu działania funkcji, w której została zdefiniowana.** ### [](#dekoratory) Dekoratory Dekoratorem funkcji nazywamy funkcję która "owija" (_ang. wrapper_) inną funkcję i pozwala na modyfikację jej zachowania bez zmiany samego kodu źródłowego funkcji. Są przydatne w sytuacjach, gdy chcemy dodać dodatkowe funkcjonalności do istniejących funkcji, np. logowanie, monitorowanie wydajności, czy walidację danych. Przyjmują one inną funkcję jako argument i zwracają nową funkcję. **Są one używane poprzez umieszczenie znaku "@" przed definicją funkcji**, do której mają być zastosowane. Copy def moj_dekorator(funkcja): def opakowujaca_funkcja(): print("Zanim zostanie wykonana funkcja.") funkcja() print("Po wykonaniu funkcji.") return opakowujaca_funkcja @moj_dekorator def przykladowa_funkcja(): print("To jest przykładowa funkcja.") # przykladowa_funkcja = moj_dekorator(przykladowa_funkcja) przykladowa_funkcja() def dekorator_informacji_o_samochodzie(funkcja): def opakowujaca_funkcja(marka, model): funkcja(marka, model) print(f"Marka: {marka}") print(f"Model: {model}") return opakowujaca_funkcja @dekorator_informacji_o_samochodzie def samochod(marka, model): print("Informacje o samochodzie:") samochod("Toyota", "Celica") [](#zadania) Zadania ------------------------- 1. Napisz funkcję `inkrementuj`, która inkrementuje globalną zmienną o 1. Wywołaj tę funkcję trzy razy i sprawdź, czy wartość zmiennej globalnej została poprawnie zaktualizowana. 2. Napisz funkcję zewnątrzną `zlicz`, która zlicza, ile razy została wywołana (korzystając z funkcji wewnętrznej `inkrementuj`), korzystając z modyfikatora `nonlocal`. Sprawdź, czy funkcja poprawnie zlicza ilość wywołań. 3. Stwórz dekorator dla poniższej funkcji który będzie sprawdzał czy liczba jest większa od 0, jeżeli tak to zwróci jej pierwiastek, a jeżeli nie to wypisze tekst _"Liczba musi być większa o 0"_ Copy def zwroc_liczbe(liczba): return liczba 1. Stwórz dekorator który dla poniższych funkcji będzie wyświetlał przed jej wywołaniem wartości argumentów jakie zostały do niej przekazane Copy def funkcja_nr1(a, b): return a + b def funkcja_nr2(a, b, c=5, d=6): return a + b + c + d 1. W Krainie Liczb odkryto tajemniczą funkcję, która filtruje (_przepuszcza tylko parzyste_) i mapuje (_podnosi do kwadratu_) liczby. Należy stworzyć dekorator `magiczny_filtr`, który zasymuluje jego działanie używając funkcji `filter` oraz `map`, a następnie przetestować jego działanie na poniższych przykładach: Copy def pierwsza_funkcja(): return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def druga_funkcja(): return [0, 3, 6, 9, 10, 12, 15, 18, 20] 1. Stwórz "System logowania, analizy wydajności i walidacji danych za pomocą dekoratorów", w którym znajdą się trzy dekoratory: 1. `time_tracker` - który mierzy czas działania funkcji 2. `validate_inputs` - który sprawdza poprawność argumentów funkcji, wszystkie mają być typu liczbowego 3. `logger(enabled=False)` - który loguje i zapisuje wszystkie dane dotyczące argumentów i wyniku działania funkcji, parametr enabled pozwala na włączanie / wyłączanie Copy # przykładowe funkcje do testów def potega(liczba, n): return liczba ** n def wolna_suma(*args): time.sleep(2) return sum(args) def symulacja_czasu(czas): time.sleep(czas) return f"Symulacja trwała {czas} sekund." [PreviousLaboratorium 7](/jezyki-skryptowe/laboratorium-7) [NextLaboratorium 9](/jezyki-skryptowe/laboratorium-9) Last updated 2 months ago --- # Laboratorium 1 | Języki Skryptowe [](#typy-zmiennych) Typy zmiennych --------------------------------------- Zmienne służą do przechowywania danych. W Pythonie możemy wyróżnić następujące wbudowane typy: * liczby całkowite **(int)**, np. `5, 10, 42, 50` * liczby zmiennoprzecinkowe **(float)**, np. `3.14, 12.54, 100.5` * liczby zespolone **(complex)**, np. `3 + 4j, 1j` * ciągi znaków **(str)**, np. `"Hello World!", "Uniwersytet"` * wartości logiczne **(bool)**, np. `True, False` * bajty **(bytes)**, np. `b'Hello'` [](#funkcja-print) Funkcja print() --------------------------------------- Używana do wyświetlania tekstu lub wartości na ekranie, przydatne narzędzie do komunikacji z użytkownikiem lub do wyświetlania wyników obliczeń, każdy output domyślnie kończy się znakiem nowej linii `\n`, możemy to zmienić za pomocą dodatkowego argumentu `end=""` W parametrze możemy przekazać ciąg znaków lub zmienną: Copy print("Hello World!") a wynikiem będzie wypisany w konsoli tekst: Copy Hello World! [](#komentarze) Komentarze ------------------------------- **Jednolinijkowe komentarze** rozpoczynają się od znaku `#` i trwają do końca linii Copy # jednolinijkowy komentarz **Wielolinijkowe komentarze** (dokumentacja): Rozpoczynają się i kończą potrójnymi cudzysłowami (lub potrójnymi apostrofami) `'''` lub `"""`. Copy ''' wielolinijkowy komentarz zawiera dodatkowe informacje, stosowany przy opisach i dokumentacji ''' Komentarze są obecne w kodzie źródłowym, ale są przez interpreter całkowicie ignorowane. Oznacza to, że nie mają wpływu na działanie programu ani na wyniki jego działania. [](#przypisywanie-wartosci) Przypisywanie wartości ------------------------------------------------------- Przy tworzeniu zmiennej nie trzeba podawać jaki typ danych będzie w niej przechowywany. Po prostu podajemy nazwę i przypisujemy jej wartość. Z tego powodu mówi się, że **Python jest językiem typowanym dynamicznie**. Copy zmienna = 3 # int print(zmienna) liczba_pi = 3.14 # float print(liczba_pi) # string może być inicjowany za pomocą pojedyńczego lub podwójnego cudzysłowu imie = "Adam" # str nazwisko = 'Nowak' # str print(imie, nazwisko) Możemy również wykonywać proste operacje oraz robić konwersje typów (rzutowanie): Copy imie = "Adam" nazwisko = 'Nowak' imie_i_nazwisko = imie + " " + nazwisko print(imie_i_nazwisko) # funkcja format() wstawia określone wartości do symbolu zastępczego definiowanego jako {} print("Imię: {}, nazwisko: {}".format(imie, nazwisko)) liczba_pi = 3.14 liczba = float(5) # liczba calkowita zostaje zamieniona na zmiennoprzecinkową wynik = liczba_pi + liczba print(wynik) czy_prawda = True print(czy_prawda) print("slowo" != "slowo") jawne **rzutowanie** jest to konwersja danych na zadany przez nas typ Copy tekst = "123" liczba = int(tekst) # konwersja z typu str na int liczba = 10 tekst = str(liczba) # konwersja z typu int na str **multiple assignment** \- jest to jednoczesne przypisanie wartości kilku zmiennym w tej samej linijce Copy drzewo, wiek, czy_najstarsze = "dab", 400, True print("Drzewo {} ma {} lat, czy jest najstarsze? {}".format(drzewo, wiek, czy_najstarsze)) przykład zmiany typu zmiennej podczas działania programu Copy x = 1 print(f"x = {x}, typ {type(x)}") x = "Dwa" print(f"x = {x}, typ {type(x)}") x = False print(f"x = {x}, typ {type(x)}") [](#formatowanie-lancuchow-znakowych) Formatowanie łańcuchów znakowych --------------------------------------------------------------------------- Istnieje kilka metod które można wykorzystać do formatowania łańcuchów znakowych, więcej o nich [można przeczytać tutaj](https://chyla.org/artykuly/python/python-tutorial/formatowanie-napisow.html) : * %-formatting * str.format() * **f-string - najnowsza, zalecana metoda dostępna od wersji 3.6** Copy imie = "Adam" nazwisko = "Nowak" liczba = 5 # % print("%s %s nr %d" % (imie, nazwisko, liczba)) # .format() print("{} {} nr {}".format(imie, nazwisko, liczba)) # f-string print(f"{imie} {nazwisko} nr {liczba}") [](#operacje-na-liczbach) Operacje na liczbach --------------------------------------------------- Operacja Symbol Przykład Dodawanie + `x + 1`, `"a" + "b"` Odejmowanie \- `x - 1` Mnożenie \* `x * 5`, `x * y` Dzielenie / `x / y`, `y / 3` Dzielenie całkowite // `x // y`, `y // 7` Potęgowanie \*\* `x ** 2` Reszta z dzielenia % `x % 2` [](#funkcja-input) Funkcja input() --------------------------------------- Pozwala na interakcję z użytkownikiem pozwalając na wprowadzenie danych z klawiatury. Zwraca wprowadzone dane w postaci typu tekstowego _(str)_, parametr z podpowiedzią jest opcjonalny. Copy imie = input("Podaj swoje imię: ") print(f"Witaj {imie}") [](#import) Import ----------------------- Importowanie jest procesem pozwalającym na dostęp do funkcji, zmiennych i modułów dostępnych w innych plikach lub bibliotekach. Importowanie jest używane, gdy chcemy wykorzystać kod z innych źródeł w naszym programie. Moduł `math` jest jednym z modułów biblioteki standardowej co oznacza, że nie wymaga dodatkowej instalacji. Copy import math # aby zaimportować moduł używamy słowa kluczowego import r = 10 # promień koła obwod = 2 * math.pi * r # obwód koła [](#warto-zapamietac) Warto zapamiętać ------------------------------------------- 1. _Co oznacza to, że Python jest językiem typowanym dynamicznie?_ Typowanie dynamiczne jest to przypisywanie typów do zmiennych dopiero w trakcie działania programu. Typ wynika z wartości jaką dana zmienna przechowuje i może się zmieniać w różnych momentach wykonywania. Zastanowić się nad wadą i zaletą. 2. _Kiedy należy używać "double quotes", a kiedy 'single quotes'?_ Zgodnie z dokumentacją PEP8 są one w zasadzie wymienne. Zaleca wybrać jedno podejście i trzymać się go lub dostosować do istniejących zasad w projekcie. Najczęściej używamy " " przy stringach, a ' ' przy kluczach i symbolach. 3. _Konwencje nazewnictwa_ **lower\_case\_with\_underscores** \- nazwy funkcji, zmiennych, modułów **CAPS\_WITH\_UNDERSCORES** \- zmienne globalne, stałe zdefiniowane w klasie [więcej o nazewnictwie zmiennych](https://www.w3schools.com/python/gloss_python_variable_names.asp) [](#zadania) Zadania ------------------------- 1. Napisz program w którym dokonasz konwersji zmiennej typu `int` na typ `float` oraz z typu `int` na `str`, podczas działania programu sprawdzaj typy 2. Stwórz 3 zmienne o 3 różnych typach i wypisz je w jednej linijce używając tylko jednego wywołania funkcji _print()_ 3. Mając zmienną `imie = "Kleopatra"` wypisz ją małymi i wielkimi literami używając f-string oraz [_metod domyślnych dla typu string_](https://www.w3schools.com/python/python_ref_string.asp) 4. Napisz program, który oblicza wskaźnik masy ciała (BMI) na podstawie podanej przez użytkownika wagi i wzrostu za pomocą wzoru `BMI = masa_ciała / (wzrost^2)` 5. Wypisz liczbę PI z dokładnością do 10 miejsc po przecinku korzystając z Pythonowej stałej 6. Napisz program, który oblicza pierwiastek kwadratowy z liczby wprowadzonej przez użytkownika, a następnie wyświetla wynik używając f-string [PreviousJęzyki Skryptowe](/jezyki-skryptowe) [NextLaboratorium 2](/jezyki-skryptowe/laboratorium-2) Last updated 4 months ago --- # Laboratorium 5 | Języki Skryptowe [](#wyjatki) Wyjątki ------------------------- kiedy w trakcie wykonywania kodu występuje błąd, interpreter podnosi wyjątek, co prowadzi do przerwania standardowego przepływu wykonania programu. Wyjątki pozwalają na kontrolowanie tych sytuacji i wprowadzenie odpowiednich działań awaryjnych Copy try: x = int(input("Podaj liczbę: ")) wynik = 10 / x print(f"Rozwiązanie to {wynik}") except Exception as e: print(f"Wystąpił błąd {e}") jest możliwość przechwytywania różnych wyjątków w osobnych blokach Copy try: x = int(input("Podaj liczbę: ")) wynik = 10 / x print(f"Rozwiązanie to {wynik}") except ZeroDivisionError: print("Nie można dzielić przez zero!") except ValueError: print("To nie jest liczba!") except Exception as e: print(f"Wystąpił inny, nieznany błąd {e}") else: print("Brak błędów!") finally: print("Ten blok kodu zawsze wykona się na końcu") * blok `try` zawiera kod, który może spowodować wyjątek * bloki `except` definiują, jakie działania podejmować dla określonych typów wyjątków * blok `else` jest opcjonalny i wykonuje się tylko wtedy, gdy w bloku `try` nie wystąpił żaden wyjątek * blok `finally` jest opcjonalny i niezależnie od tego czy wystąpił wyjątek czy nie wykonuje się * dokumentacja [https://docs.python.org/pl/3/tutorial/errors.html](https://docs.python.org/pl/3/tutorial/errors.html) [](#pliki) Pliki --------------------- ### [](#sprawdzenie-czy-sciezka-istnieje) Sprawdzenie czy ścieżka istnieje `os.path.exists` to funkcja w module `os`, która służy do sprawdzania, czy dana ścieżka istnieje w systemie. Jeśli ścieżka istnieje, funkcja zwraca `True`, w przeciwnym razie zwraca `False`. Jest to przydatne narzędzie do sprawdzania istnienia plików przed ich otwarciem czy przetwarzaniem. Copy import os sciezka_do_pliku = "plik.txt" if os.path.exists(sciezka_do_pliku): print(f"Plik '{sciezka_do_pliku}' istnieje") else: print(f"Plik '{sciezka_do_pliku}' nie istnieje") ### [](#operacje) Operacje do operacji na plikach w Pythonie najczęściej używane są funkcje `open()`, `read()`, `write()` oraz `close()` Copy try: plik = open("nazwa_pliku.txt", 'r') zawartosc = plik.read() print(f "Zawartość pliku {zawartosc}") finally: plik.close() Tradycyjne podejście w którym otwieramy plik za pomocą funkcji `open()`, przetwarzamy jego zawartość, a następnie zamykamy plik za pomocą funkcji `close()`. Jednak to podejście wymaga ręcznego obsługiwania błędów i może prowadzić do problemów, gdy wystąpią wyjątki w trakcie operacji na pliku. Copy try: with open("nazwa_pliku.txt", 'r') as plik: zawartosc = plik.read() print(f"Zawartość pliku {zawartosc}") except FileNotFoundError: print("Plik nie istnieje") Podejście z blokiem `with open()` jest bardziej zalecane, ponieważ zapewnia automatyczne zamknięcie pliku po opuszczeniu bloku `with`, nawet jeśli wystąpi błąd oraz jest bardziej czytelne niż tradycyjne podejście. Copy try: with open("nowy_plik.txt", 'w') as plik: plik.write("Studiuje na Uniwersytecie\n") plik.write("A to kolejna linia tekstu\n") print("Plik został zapisany pomyślnie.") except Exception as e: print(f"Wystąpił błąd {e}") Po wykonaniu tego kodu, w bieżącym katalogu powinien pojawić się plik o nazwie `nowy_plik.txt` zawierający tekst. W tym przykładzie używamy bloku `with open()` do otwarcia pliku `nowy_plik.txt` w trybie zapisu `'w'`. Następnie używamy metody `write()` do zapisania dwóch linii tekstu do pliku. Poprzez użycie bloku `with` nie musimy zajmować się zamknięciem pliku ponieważ wydarzy się to automatycznie. * `plik.read()` - odczytuje cały tekst * `plik.read(100)` - odczytuje określoną liczbę bajtów, tutaj 100 pierwszych * `plik.readline()` - zwraca jedną linie, kolejne wywołania zwracają kolejne * `plik.write()` - zapisuje ciąg znaków do pliku * `plik.flush()` - zapisuje bufor na dysku, Python robi to automatycznie ale bywają sytuacje kiedy należy tą operacje wykonać ręcznie * `plik.seek(offset, whence)` - przesuwa kursor w obiekcie pliku, domyślna wartość `whence` to 0 czyli początek pliku ### [](#tryby-otwarcia-pliku) Tryby otwarcia pliku mode działanie `'r'` otwiera plik do odczytu**, tryb domyślny** `'w'` otwiera plik do zapisu i nadpisuje dane `'x'` tworzy plik do zapisu, zwraca błąd `FileExistsError` jeżeli już istnieje `'a'` otwiera plik do zapisu danych nie usuwając istniejących `'b'` tryb binarny, do czytania i zapisywania plików binarnych `'+'` otwiera plik do odczytu i zapisu ### [](#usuwanie) Usuwanie Copy import os sciezka_do_pliku = "nazwa_pliku.txt" try: os.remove(sciezka_do_pliku) print(f"Plik {sciezka_do_pliku} został usunięty") except FileNotFoundError: print(f"Plik {sciezka_do_pliku} nie istnieje") except Exception as e: print(f"Wystąpił błąd {e}") Przed wykonaniem operacji usuwania pliku, zawsze warto sprawdzić, czy plik istnieje, aby uniknąć błędów związanych z próbą usunięcia nieistniejącego pliku. W tym przykładzie używamy funkcji `os.remove()` do usuwania pliku o podanej ścieżce. Należy pamiętać, że operacja ta jest trwała, a usunięte pliki nie trafiają do kosza. [](#warto-zapamietac) Warto zapamiętać ------------------------------------------- 1. _Jak w bezpieczny sposób uzyskać dostęp do pliku?_ Operacje na plikach powinny być wykonywane z zachowaniem ostrożności. Stosowanie bloku `with open()` zapewnia automatyczne zamykanie plików, co zapobiega wyciekom zasobów. 2. Zamiast używać ogólnego `except Exception` warto obsługiwać specyficzne typy, takie jak `FileNotFoundError`, `ValueError`, czy `ZeroDivisionError`. Umożliwia to dokładniejsze kontrolowanie błędów i lepsze debugowanie aplikacji. [](#zadania) Zadania ------------------------- 1. Z listy dostępnych wyjątków [https://docs.python.org/3.9/library/exceptions.html](https://docs.python.org/3.9/library/exceptions.html) wybierz jeden, a następnie napisz skrypt który najpierw go rzuci, a później przechwyci i obsłuży 2. Utwórz manualnie pusty plik tekstowy, a następnie otwórz go w swoim programie przy użyciu podejścia tradycyjnego oraz bloku `with open()` 3. Za pomocą funkcji `create_dataset()` utwórz plik `integer_dataset.txt`, zapełnij go 50 losowymi liczbami z przedziału (0; 200) oddzielonych spacjami, a następnie każdorazowo otwierając plik w osobnych funkcjach: * znajdź największą i najmniejszą liczbę * wyznacz średnią arytmetyczną liczb * policz wszystkie liczby mniejsze lub równe 100 4. Napisz program, który wczyta wcześniej manualnie utworzony plik tekstowy o nazwie `dane.txt` zawierający losowe zdania z generatora [https://www.lipsum.com/](https://www.lipsum.com/) , a następnie: * wypisz wszystkie pobrane znaki w konsoli * stwórz histogram wystąpienia pojedynczych znaków w tekście w formie słownika ignorując interpunkcję * przygotuj funkcję która zresetuje zawartość pliku i ponownie wypisze znaki i stworzy histogram * \*\* znajdź palindromy (zakładając, że spacja to separator) * \*\* wypisz najdłuższe słowo lub słowa jeśli jest więcej o tej samej długości [PreviousLaboratorium 4](/jezyki-skryptowe/laboratorium-4) [NextLaboratorium 6](/jezyki-skryptowe/laboratorium-6) Last updated 3 months ago --- # Laboratorium 10 | Języki Skryptowe [](#podzial) Podział ------------------------- * **testy jednostkowe** (unit tests) — testujemy pojedynczą jednostkową część taką jak funkcje, metody czy klasy * **testy integracyjne** (integration tests) — testujemy wiele komponentów systemu za jednym razem * **testy end-to-end (E2E) / systemowe** — testujemy działanie całego systemu (od interfejsu użytkownika po bazę danych i usługi zewnętrzne) w warunkach zbliżonych do produkcyjnych [](#frameworki) Frameworki ------------------------------- W środowisku Python istnieje kilka popularnych frameworków do testowania jednostkowego * **unitest** \- dostarczany razem z biblioteką standardową Copy import unittest def dodaj(a, b): return a + b class TestDodawania(unittest.TestCase): def test_dodawania(self): self.assertEqual(dodaj(2, 3), 5) if __name__ == '__main__': unittest.main() * **pytest** * prostota i czytelność składni * automatyczne znajdowanie funkcji testowych poprzez nazwę _test..._ * parametryzowane testy * dużo wbudowanych asercji, pluginów i rozszerzeń Copy import pytest def dodaj(a, b): return a + b def test_dodawania(): assert dodaj(2, 3) == 5 * **nose2** - oparty na `unittest` oferujący dodatkowe funkcje, ułatwia testowanie i raportowanie * **doctest** \- pozwala na umieszczanie testów bezpośrednio w docstringach funkcji lub modułów * **Hypothesis** \- generuje przypadki testowe automatycznie, pomaga odkryć edge case **Wybór zależy od preferencji, potrzeb projektu oraz struktury testów** [](#assert) assert ----------------------- Funkcja `assert` jest używana do wprowadzania warunków, które powinny być prawdziwe, sprawdzenie jest dokonywane w trakcie pracy programu. * jeśli warunek jest spełniony **True**, to nic się nie dzieje, program kontynuuje swoje wykonanie * jeśli warunek nie jest spełniony **False**, to zostanie zgłoszony wyjątek `AssertionError` z opcjonalnym komunikatem błędu przykłady Copy # 1 x = 5 assert x > 0 # 2 lista = [1, 2, 3] assert len(lista) == 5, "Lista powinna mieć 5 elementów" możemy również sprawdzać całe funkcje Copy def dodaj(a, b): return a + b def test_dodawania(): assert dodaj(2, 3) == 5, "Błąd: dodaj(2, 3) powinno być równe 5" assert dodaj(-1, 1) == 0, "Błąd: dodaj(-1, 1) powinno być równe 0" assert dodaj(0, 0) == 0, "Błąd: dodaj(0, 0) powinno być równe 0" albo zastosować asercję w celu ograniczenia typu Copy def bar(n): assert isinstance(n, int) return n + 1 [](#pytest) pytest ----------------------- Aby `pytest` rozpoznał i uruchomił testy, należy utrzymać określoną strukturę katalogów. W standardowej konwencji, testy umieszcza się w plikach, których nazwy zaczynają się od `test_`, a same testy to funkcje, które również zaczynają się od `test_`. Trzymanie testów w osobnym pliku `test_` to dobra praktyka, a nazwa funkcji `test_` jest obligatoryjna `pip install pytest` Copy projekt/ |-- kalkulator.py |-- test_kalkulator.py przykład Copy def dodaj(a, b): return a + b def test_dodawania(): assert dodaj(2, 3) == 5 assert dodaj(-1, 1) == 0 assert dodaj(0, 0) == 0 a następnie w terminalu należy przejść do katalogu zawierającego pliki `projekt/` i uruchomić wszystkie testy Copy pytest lub tylko te znajdujące się w określonym pliku Copy pytest test_kalkulator.py **test parametryzowany** Copy import pytest def dodaj(a, b): return a + b @pytest.mark.parametrize("x,y,oczekiwane", [(2, 3, 5), (-1, 1, 0), (0, 0, 0)]) def test_dodawania(x, y, oczekiwane): wynik = dodaj(x, y) assert wynik == oczekiwane **test z użyciem fixture -** specjalny mechanizm udostępniany do **inicjalizacji** środowiska testowego Copy import pytest class Kalkulator: def dodaj(self, a, b): return a + b @pytest.fixture def kalkulator(): return Kalkulator() def test_dodawania(kalkulator): wynik = kalkulator.dodaj(2, 3) assert wynik == 5, "Błąd: 2 + 3 = 5" [](#sortowanie-babelkowe) Sortowanie bąbelkowe --------------------------------------------------- Sortowanie bąbelkowe to algorytm sortowania, który porównuje kolejne pary elementów w tablicy i zamienia je, jeśli są w złej kolejności aż do momentu gdy nie będą wymagane żadne zmiany. Rozważmy tablicę `[5, 2, 9, 1, 5]` i zastosujmy sortowanie bąbelkowe: 1. Pierwsze przejście: * Zamiana miejscami: `[2, 5, 1, 5, 9]` * Zamiana miejscami: `[2, 1, 5, 5, 9]` 2. Drugie przejście: * Zamiana miejscami: `[1, 2, 5, 5, 9]` 3. Tablica jest teraz posortowana [](#zadania) Zadania ------------------------- 1. Napisz funkcję `czy_rok_przestepny(rok)`, która zwróci True jeżeli rok jest przestępny. Rok przestępny to taki, który jest podzielny przez 4, dodatkowo przestępnymi nie są lata, które dzielą się przez 100, chyba że dzielą się również przez 400 (np. 1600 lub 2000). Przetestuj kilka wybranych dat używając `assert` 2. Napisz funkcję `podziel(a, b)`, która przyjmie dwie liczby całkowite i zwróci wartość z ich dzielenia. Napisz testy jednostkowe, które zweryfikują wywołanie dla danych `(6, 2), (1, 0), (0, 1), (10, -2)` 3. Napisz funkcję `czy_palindrom(s)`, która sprawdzi, czy podany string `s` jest palindromem (jest to wyraz czytany tak samo od przodu i od tyłu). Napisz testy jednostkowe, które zweryfikują wywołanie dla danych `"kajak", "klawiatura", "mecz", "madam"` 4. Napisz funkcję o nazwie `suma_parzystych`, która przyjmuje listę liczb całkowitych jako argument i zwraca sumę wszystkich liczb parzystych z tej listy. Następnie napisz testy jednostkowe z użyciem **pytest i oznaczenia @parametrize** sprawdzające poprawność działania tej funkcji dla czterech przypadków. 5. Napisz funkcję `sortowanie_babelkowe(lista)`, która przyjmuje listę liczb całkowitych i zwraca ją posortowaną rosnąco samodzielnym algorytmem. Napisz testy jednostkowe z użyciem **pytest i oznaczenia @parametrize** dla trzech przykładowych list. 6. **\*\_Rozpoznaj** co robi poniższa funkcja i sprawdź jej działanie testem jednostkowym z czterema przypadkami testowymi: Copy def secret(data: str) -> int: x = set("aei") return sum(1 for c in data if c in x) [PreviousLaboratorium 9](/jezyki-skryptowe/laboratorium-9) [NextLaboratorium 11](/jezyki-skryptowe/laboratorium-11) Last updated 1 month ago --- # Laboratorium 6 | Języki Skryptowe [](#programowanie-funkcyjne) Programowanie funkcyjne --------------------------------------------------------- Opiera się na korzystaniu z pewnych konceptów charakterystycznych dla tego paradygmatu. ### [](#funkcje-wyzszego-rzedu) Funkcje wyższego rzędu ang. _higher order function_ to koncepcja, która zakłada, że funkcje mogą przyjmować inne funkcje jako argumenty lub zwracać funkcje jako wyniki. Dodatkowo w Pythonie **funkcje są obiektami pierwszej klasy, co oznacza, że mogą być traktowane tak samo jak inne obiekty, takie jak liczby czy napisy**. Copy def poteguj(x): return x ** 2 funkcja = poteguj # traktujemy funkcję jak obiekt print(funkcja(5)) Copy def krzyk(text):      return text.upper()       def szept(text):      return text.lower()       def wyswietl(func):  text = func("Hello Higher Order Function")      print(text)      wyswietl(krzyk) wyswietl(szept) mogą też zwracać inną funkcję Copy def dzielenie(x): def podziel(y): return y / x return podziel funkcja = dzielenie(2) print(funkcja(10)) ### [](#czyste-funkcje-i-bezstanowosc) Czyste funkcje i bezstanowość * czysta funkcja to taka, która zawsze zwraca tę samą wartość dla tych samych argumentów i nie ma efektów ubocznych * unikanie efektów ubocznych jest jednym z głównych założeń funkcyjnego programowania * funkcyjne podejście często zachęca do unikania zmiennych globalnych i stanu * funkcje powinny być bezstanowe, co oznacza, że wynik zależy tylko od argumentów wejściowych Copy def dodaj(a, b): return a + b ### [](#funkcje-anonimowe-lambda) Funkcje anonimowe (lambda) są nazywane funkcjami lambda i są to krótkie funkcje bez nazwy, które mogą przyjmować dowolną liczbę argumentów, ale mogą zawierać tylko jedno wyrażenie. Są one definiowane za pomocą słowa kluczowego `lambda` składnia: `lambda parameters:expression` Copy dodaj = lambda x, y: x + y print(dodaj(3, 4)) Copy # podejście klasyczne def podwoj(x): return x * 2 print(podwoj(5)) # podejście lambda podwoj = lambda x:x * 2 pomnoz = lambda x, y: x * y print(podwoj(5)) print(pomnoz(2, 3)) _Funkcje lambda są bardziej ograniczone niż pełne funkcje zdefiniowane przy użyciu_ `_def_`_. Nie obsługują wielu instrukcji, a ich użycie powinno być ograniczone do prostych przypadków._ ### [](#funkcje-wbudowane) **Funkcje wbudowane** * `iterable` - dane przekazane jako argument do funkcji * `key` - określenie dodatkowej funkcji (np. sortującej) * `function` - stosowanie zadanej funkcji dla elementów `iterable` * **nie modyfikują danych, tylko zwracają nowe** **sorted** - sortuje według zadanej funkcji `sorted(iterable,key=function)` `lambda data:data[1]` Copy lista = [3, 1, 4, 1, 5, 9] posortowana = sorted(lista) print(posortowana) # [1, 1, 3, 4, 5, 9] # wersja z lambdą posortowana = sorted(lista, key=lambda x: x) print(posortowana) # [1, 1, 3, 4, 5, 9] **map** - stosuje funkcję mapującą dla każdego elementu `map(function, iterable)` `lambda data: (data[0],data[1]/2)` Copy liczby = [1, 2, 3, 4] def podwoj(x): return x * 2 podwojone = map(podwoj, liczby) print(list(podwojone)) # [2, 4, 6, 8] # wersja z lambdą podwojone = map(lambda x: x * 2, liczby) print(list(podwojone)) # [2, 4, 6, 8] **filter** - filtruje na podstawie warunku logicznego `filter(function, iterable)` `lambda data:data[0] != 1` Copy liczby = [1, 2, 3, 4, 5, 6] def jest_parzysta(x): return x % 2 == 0 parzyste = filter(jest_parzysta, liczby) print(list(parzyste)) # [2, 4, 6] # wersja z lambdą parzyste = filter(lambda x: x % 2 == 0, liczby) print(list(parzyste)) # [2, 4, 6] **reduce** - redukuje dane wejściowe do pojedynczej wartości skumulowanej, powtarza proces aż pozostanie jedna wartość `functools.reduce(function, iterable)` `lambda x, y,:x + y, string_array` Copy from functools import reduce liczby = [1, 2, 3, 4, 5] def dodaj(x, y): return x + y suma = reduce(dodaj, liczby) print(suma) # 15 # wersja z lambdą suma = reduce(lambda x, y: x + y, liczby) print(suma) # 15 ### [](#listy-skladane) Listy składane ang. _list comprehensions,_ pozwalają na bardziej zwięzłe i czytelne tworzenie list na podstawie istniejących danych `list = [expression for item in iterable]` `list = [expression for item in iterable if conditional]` `list = [expression if/else for item in iterable]` Copy liczby = [1, 2, 3, 4] podwojone = [x * 2 for x in liczby] print(podwojone) # [2, 4, 6, 8] # podejście tradycyjne parzyste = [] for x in range(10): if x % 2 == 0: parzyste.append(x) print(parzyste) # list comprehension parzyste = [x for x in liczby if x % 2 == 0] print(parzyste) # [2, 4] slowo = "python" wielkie_litery = [litera.upper() for litera in slowo] print(wielkie_litery) # ['P', 'Y', 'T', 'H', 'O', 'N'] parzyste_nieparzyste = ['parzysta' if x % 2 == 0 else 'nieparzysta' for x in range(5)] print(parzyste_nieparzyste) # ['parzysta', 'nieparzysta', 'parzysta', 'nieparzysta', 'parzysta'] [](#zadania) Zadania ------------------------- 1. Przygotuj _lambda function_ lub _list comprehension_, która w osobnych funkcjach: 1. za pomocą listy składanej wyświetli tylko liczby podzielne przez 2 dla danych `liczby = [100, 95, 80, 75, 60, 55, 40, 35, 20, 15, 0]` 2. przyjmuje wiek i zwróci _bool_ informujący czy osobna jest pełnoletnia 3. posortuje listę czterech dowolnych miast po ilości znaków 4. posortuje mapę po wartościach `gazy = {'hel': 1, 'neon': 2, 'argon': 6, 'ksenon': 8}` 5. sprawdzi czy wszystkie liczby są typu zmiennoprzeciwnkowego `liczby = [1.5, 5.1, 6.3, 2.2, 8.4]` 6. znajdzie część wspólną dwóch list `l1 = [1, 2, 3, 5, 7, 8, 9, 10]` oraz `l2 = [1, 2, 4, 8, 9]` 7. znajdzie tylko stringi, które są anagramami znaków `abcd`, `dane = ['bcda', 'abce', 'cbda', 'cbea', 'adcb']` 8. doda do siebie trzy listy `l1 = [1, 2, 3]`, `l2 = [4, 5, 6]`, `l3 = [7, 8, 9]` 2. Stwórz program, który wczytuje dane o książkach z pliku tekstowego, a następnie przetwarza je za pomocą _lambda function_ lub _list comprehension:_ 1. należy wczytać plik tekstowy _books.txt_ pamiętając o obsłudze błędów zawierający min. 6 książek z danymi:`Tytuł książki, Autor, Rok wydania, Liczba stron`, np. Władca Pierścieni, Tolkien, 1954, 1216 Harry Potter, Rowling, 1997, 309 2. i zapisać je w formie listy zawierającej słowniki, np. `[{"tytul": "Władca Pierścieni", "autor": "Tolkien", "rok": 1954, "strony": 1216}, ...]` _\* aby dostać do się do konkretnego pola można użyć notacji_ `book["tytul"]` _lub_ `book["autor"]` 3. a następnie w osobnych funkcjach: 1. wyfiltrować książki wydane po 1970 roku 2. obliczyć średnią liczbę stron w książkach 3. posortować książki alfabetycznie po tytule 4. znaleźć autorów, którzy mają więcej niż jedną książkę w spisie 4. \* zapisać statystykę z punktu c do pliku _books\_statistic.txt_ 5. _\*\*_ dodać możliwość dodawania wpisów, dodatkowych książek do istniejącego pliku _books.txt_ [PreviousLaboratorium 5](/jezyki-skryptowe/laboratorium-5) [NextLaboratorium 7](/jezyki-skryptowe/laboratorium-7) Last updated 2 months ago --- # Laboratorium 11 | Języki Skryptowe [](#venv) venv ------------------- skrót od _Virtual Environment_ to narzędzie, które umożliwia tworzenie izolowanych środowisk uruchomieniowych. Każde takie środowisko jest odseparowane od siebie, co pozwala na instalowanie i zarządzanie zależnościami projektu bez wpływu na resztę systemu PyCharm automatycznie tworzy wirtualne środowisko przy zakładanie nowego projektu manualne tworzenie nowego środowiska, standardowa nazwa to _venv_ Copy python -m venv nazwa_srodowiska python -m venv venv aby aktywować środowisko Copy # linux, mac source nazwa_srodowiska/bin/activate # windows nazwa_srodowiska\Scripts\activate i dezaktywować Copy deactivate [](#pip) pip ----------------- skrót od _Pip Installs Packages_ lub _Pip Installs Python._ Jest to narzędzie do zarządzania pakietami w języku Python i służy do instalowania, aktualizowania, usuwania i zarządzania zależnościami. Współpracuje z **PyPI** czyli _Python Package Index_, które jest publicznym repozytorium pakietów Pythona. instalacja pakietów Copy pip install nazwa_pakietu aktualizacja pakietów Copy pip install --upgrade nazwa_pakietu usuwanie pakietów Copy pip uninstall nazwa_pakietu wyświetlanie zainstalowanych pakietów Copy pip list Po zainstalowaniu zależności projektu w środowisku wirtualnym, można utworzyć plik `requirements.txt`, który zawiera listę wszystkich pakietów i ich wersji wymaganych do uruchomienia aplikacji Copy # plik requirements.txt numpy==1.21.2 pandas==1.3.3 Aby zainstalować zależności projektu z pliku `requirements.txt`, który wymusza konkretną wersję `numpy` oraz `pandas` należy użyć poniższej komendy w terminalu Copy pip install -r requirements.txt można też automatycznie zapisać informację o **wszystkich** zainstalowanych aktualnie paczkach Copy pip freeze > requirements.txt [](#praca-z-paczkami-z-poziomu-pycharm) Praca z paczkami z poziomu PyCharm ------------------------------------------------------------------------------- 1. uruchamiamy projekt 2. z kart na dole wybieramy zakładkę `Terminal` 3. aktywujemy środowisko wirtualne za pomocą komendy `venv\Scripts\activate` 4. przed ścieżką będzie widoczny prefix `(venv)` oznaczający, że w nim jesteśmy 5. przeprowadzamy interesujące nas operacje za pomocą `pip`, np. `pip install numpy` lub `pip install -r requirements.txt` 6. po skończonej pracy możemy dezaktywować środowisko `deactivate` [](#package) Package ------------------------- Odnosi się do sposób organizacji i strukturyzacji kodu. Paczka to zbiór modułów, które są ze sobą powiązane i umieszczone w jednym katalogu. Ma to na celu uporządkowanie i ułatwienie zarządzania kodem w większych projektach. * moduł = pojedynczy plik `.py` * paczka = folder z plikami `.py` + `__init__.py` Aby zorganizować swoje moduły w funkcjonalną paczkę, a następnie ją zbudować należy: ### [](#id-1.-przygotowac-projekt-z-odpowiednia-struktura) 1\. Przygotować projekt z odpowiednią strukturą Przykładowa struktura, może wyglądać następująco: Copy moj_projekt/ |-- moja_paczka/ | |-- __init__.py | |-- modul1.py | |-- modul2.py |-- setup.py |-- README.md * `moj_projekt` - główny folder projektu * `moja_paczka` \- tutaj znajdują się stworzone przez nas moduły`modul1.py` oraz `modul2.py` * `__init__.py` - plik oznaczający, że jest to paczka * `setup.py` - plik konfiguracyjny * `README.md` - dokumentacja ### [](#id-2.-kod-rozrozniajacy-program-glowny-od-importowanego-modulu) 2\. Kod rozróżniający program główny od importowanego modułu `if __name__ == "__main__"` to warunek sprawdzający, czy plik został uruchomiony jako program główny, a nie importowany jako moduł do innego skryptu. * **program główny,** plik jest uruchamiany, `__name__` przyjmuje wartość `"__main__"` * **moduł w innym skrypcie**, plik jest importowany, `__name__` przyjmuje nazwę modułu Copy # modul1.py def funkcja1(): print("Funkcja 1 wykonała się") if __name__ == "__main__": print("Ten kod zostanie wykonany tylko, gdy plik zostanie uruchomiony bezpośrednio, nie zaimportowany.") funkcja1() ### [](#id-3.-plik-__init__.py) 3\. Plik \_\_init\_\_.py Kiedy interpreter Pythona widzi plik `__init__.py` w danym katalogu, traktuje ten katalog jako paczkę. Jest on automatycznie wykonywany w momencie importu, można w nim umieścić kod inicjalizacyjny. To może obejmować ustawianie zmiennych, konfigurację lub import modułów. W naszym przypadku może on zostać pusty. W starszych wersjach Pythona, plik `__init__.py` był wymagany dla poprawnego działania jako paczki. **Od wersji 3.3 nie jest on wymagany dla samego działania paczki**, ale wciąż może być używany do celów konfiguracyjnych. ### [](#id-4.-plik-setup.py) 4\. Plik setup.py `setup.py` zawiera informacje o paczce, takie jak jej nazwa i wersja Copy from setuptools import setup setup( name='moj_projekt', # nazwa version='1.0.0', # wersja install_requires=[], # wymagane paczki dodatkowe ) ### [](#id-5.-tworzenie-paczki) 5\. Tworzenie paczki Instalujemy narzędzie `setuptools` oraz `build` czyli zestaw narzędzi dla języka Python, który ułatwia zarządzanie i dystrybucję pakietów Copy pip install setuptools pip install build Przechodzimy do głównego folderu projektu, czyli do miejsca gdzie znajduje się `setup.py` i wykonujemy polecenie budujące paczkę Copy python -m build powstanie nowy katalog `dist` w którym znajdą się dwa pliki * `*.tar.gz` - paczka źródłowa, zazwyczaj zawierająca kod źródłowy i inne pliki niezbędne do zbudowania i zainstalowania pakietu * `*.whl` - **interesujący nas plik Wheel** czyli format pakietów Pythona zaprojektowany w celu szybkiego i łatwego instalowania ### [](#id-6.-instalacja-paczki) 6\. Instalacja paczki Aby przetestować swoją paczkę lokalnie możemy ją zainstalować **w innym projekcie** za pomocą Copy pip install dist/moj_projekt-1.0.0-py3-none-any.whl Jeżeli chcemy zainstalować paczkę w trybie edycji, co daje nam wygodny dostęp do zmieniającego kodu używamy Copy pip install -e . A następnie zaimportować Copy from moja_paczka.modul1 import funkcja1 import moja_paczka.modul2 as m2 [](#dodatkowe-materialy) Dodatkowe materiały ------------------------------------------------- * [https://www.geeksforgeeks.org/python-packages/](https://www.geeksforgeeks.org/python-packages/) * [https://setuptools.pypa.io/en/latest/userguide/quickstart.html](https://setuptools.pypa.io/en/latest/userguide/quickstart.html) * [https://github.com/pypa/sampleproject](https://github.com/pypa/sampleproject) [](#zadania) Zadania ------------------------- 1. Znajdź na githubie dowolny otwartoźródłowy program w Pythonie, pobierz go, a następnie stwórz w terminalu środowisko potrzebne do jego uruchomienia i uruchom go, np. 1. [https://github.com/ytdl-org/youtube-dl](https://github.com/ytdl-org/youtube-dl) 2. [https://github.com/cookiecutter/cookiecutter](https://github.com/cookiecutter/cookiecutter) 2. Utwórz nowy projekt z nowym środowiskiem, a następnie w terminalu 1. w którym zainstalujesz za pomocą `pip` biblioteki `numpy`, `pandas`, `requests` oraz `matplotlib` 2. wyeksportuj zainstalowane biblioteki do pliku `requirements.txt` 3. Zbuduj swoją paczkę, a następnie zainstaluj w nowym środowisku i uruchom testy do poniższego zadania: Napisz funkcję `unikalne_pary`, która przyjmuje listę liczb i zwraca listę zawierającą wszystkie unikalne pary liczb, których suma wynosi 10 (reprezentowane jako tupla) Copy unikalne_pary([1, 2, 3, 4, 5, 6, 7, 8, 9]) # na wyjściu chcemy otrzymać [(1, 9), (2, 8), (3, 7), (4, 6)] Przygotuj przypadki testowe uruchamiane przez `pytest`, które pokrywają różne aspekty funkcji: 1. przypadek, gdy lista jest pusta, 2. przypadek, gdy nie ma par o sumie równej 10, 3. przypadek, gdy jedna liczba występuje kilka razy, 4. przypadek, gdy wszystkie liczby są takie same, 5. dowolny przypadek własnego autorstwa nr 1 6. dowolny przypadek własnego autorstwa nr 2 **Jeśli pojawią się problemy, to wskazują one na konieczność poprawy implementacji funkcji. Upewnij się, że wszystkie przygotowane testy przechodzą** Copy ============================= test session starts ============================= ... ============================== 10 passed in 0.01s ============================== Process finished with exit code 0 [PreviousLaboratorium 10](/jezyki-skryptowe/laboratorium-10) [NextLaboratorium 12](/jezyki-skryptowe/laboratorium-12) Last updated 1 month ago ---