.. _pythonizmy: Pythonizmy ########### .. contents:: :depth: 1 :local: Python jest językiem wydajnym i zwartym dzięki wbudowanym mechanizmom ułatwiającym wykonywanie typowych i częstych zadań programistycznych. Podane niżej **przykłady należy przećwiczyć w konsoli Pythona**, którą uruchamiamy poleceniem w terminalu: .. code-block:: bash ~$ python Operatory **\*** i **\*\*** ******************************** Operator ``*`` służy rozpakowaniu listy zawierającej wiele argumentów, które chcemy przekazać do funkcji: .. raw:: html
Kod nr
.. code-block:: python :linenos: # wygeneruj liczby parzyste od 2 do 10 lista = [2,11,2] list(range(*lista)) Operator ``**`` potrafi z kolei rozpakować słownik, dostarczając funkcji nazwanych argumentów (ang. *keyword argument*): .. raw:: html
Kod nr
.. code-block:: python :linenos: def kalendarz(data, wydarzenie): print("Data:", data,"\nWydarzenie:", wydarzenie) slownik = {"data" : "10.02.2015", "wydarzenie" : "szkolenie"} kalendarz(**slownik) Pętle ************************ Pętla to podstawowa konstrukcja wykorzystywana w językach programowania. Python oferuje różne sposoby powtarzania wykonywania określonych operacji, niekiedy wygodniejsze lub zwięźlejsze niż pętle. Są to przede wszystkim generatory wyrażeń i wyrażenia listowe, a także funkcje ``map()`` i ``filter()``. .. raw:: html
Kod nr
.. code-block:: python :linenos: kwadraty = [] for x in range(10): kwadraty.append(x**2) print(kwadraty) Iteratory *************** Obiekty, z których pętle odczytują kolejne dane to :term:`iteratory` (ang. *iterators*) Są to strumienie danych zwracanych po jednej wartości na raz za pomocą metody ``__next()__``. Jeżeli w strumieniu nie ma więcej danych, wywoływany jest wyjątek ``StopIteration``. Wbudowana funkcja ``iter()`` zwraca iterator utworzony z dowolnego iterowalnego obiektu. Iteratory wykorzystujemy do przeglądania **list**,** tupli**, **słowników** i **plików** używając instrukcji ``for x in y``, w której *y* jest obiektem iterowalnym równoważnym wyrażeniu ``iter(y)``. Np.: .. raw:: html
Kod nr
.. code-block:: python :linenos: lista = [2, 4, 6] for x in lista: print(x) slownik = {'Adam':1, 'Bogdan':2 , 'Cezary':3} for x in slownik: print(x, slownik[x]) Listy można łączyć ze sobą i przekształcać w inne iterowalne obiekty. Z dwóch list lub z jednej zawierającej tuple (klucz, wartość) można utworzyć słownik: .. raw:: html
Kod nr
.. code-block:: python :linenos: panstwa = ['Polska', 'Niemcy', 'Francja'] # lista państw stolice = ['Warszawa', 'Berlin', 'Paryż'] # lista stolic panstwa_stolice = zip(panstwa, stolice) # utworzenie iteratora lista_tupli = list(panstwa_stolice) # utworzenie listy tupli (państwo, stolica) print(lista_tupli) slownik = dict(lista_tupli) # utworzenie słownika z listy tupli print(slownik) slownik.items() # zwraca tuple (klucz, wartość) slownik.keys() # zwraca klucze slownik.values() # zwraca wartości for klucz, wartosc in slownik.items(): print(klucz, wartosc) Generatory wyrażeń ************************ Jeżeli chcemy wykonać jakąś operację na każdym elemencie sekwencji lub wybrać podzespół elementów spełniający określone warunki, stosujemy :term:`generatory wyrażeń` (ang. *generator expressions*), które zwracają iteratory. Poniższy przykład wydrukuje wszystkie imiona z dużej litery: .. code-block:: python :linenos: wyrazy = ['anna', 'ala', 'ela', 'wiola', 'ola'] imiona = (imie.capitalize() for imie in wyrazy) for imie in imiona: print(imie) Schemat składniowy generatora jest następujący: ``( wyrażenie for x in sekwencja if warunek )`` – przy czym: - ``wyrażenie`` – powinno zawierać zmienną ``x`` z pętli ``for`` - ``if warunek`` – opcjonalna klauzula filtrująca wartości nie spełniające warunku Gdybyśmy chcieli wybrać tylko imiona 3-literowe w wyrażeniu, użyjemy: .. raw:: html
Kod nr
.. code-block:: python :linenos: imiona = (imie.capitalize() for imie in wyrazy if len(imie) == 3) list(imiona) Omawiane wyrażenia można zagnieżdzać. Przykłady podajemy niżej. Wyrażenia listowe *********************** Jeżeli nawiasy okrągłe w generatorze wyrażeń zamienimy na kwadratowe, dostaniemy :term:`wyrażenie listowe` (ang. *list comprehensions*), które – jak wskazuje nazwa – zwraca listę: .. raw:: html
Kod nr
.. code-block:: python :linenos: # wszystkie poniższe wyrażenia listowe możemy przypisać do zmiennych, # aby móc później korzystać z utworzonych list # lista kwadratów liczb od 0 do 9 [x**2 for x in range(10)] # lista dwuwymiarowa [20,40] o wartościach a a = int(input("Podaj liczbę całkowtią: ")) [[a for y in range(20)] for x in range(40)] # lista krotek (x, y), przy czym x != y [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y] # utworzenie listy 3-literowych imion i ich pierwszych liter wyrazy = ['anna', 'ala', 'ela', 'wiola', 'ola'] [ [imie, imie[0]] for imie in wyrazy if len(imie) == 3 ] # zagnieżdzone wyrażenie listowe tworzące listę współrzędnych # opisujących tabelę [ (x,y) for x in range(5) for y in range(3) ] # zagnieżdzone wyrażenie listowe wykorzystujące filtrowanie danych # lista kwadratów z zakresu {5;50} [ y for y in [ x**2 for x in range(10) ] if y > 5 and y < 50 ] Wyrażenia listowe w elegancki i wydajny sposób zastępują takie rozwiązania, jak: * :term:`pętla` * :term:`mapowanie funkcji` * :term:`wyrażenia lambda` * :term:`filtrowanie danych` .. _map-fun: Mapowanie funkcji ========================== Funkcja ``map()`` funkcję podaną jako pierwszy argument stosuje do każdego elementu sekwencji podanej jako argument drugi: .. raw:: html
Kod nr
.. code-block:: python :linenos: def kwadrat(x): return x**2 kwadraty = map(kwadrat, range(10)) list(kwadraty) .. _lambda: Wyrażenia lambda ========================== Słowo kluczowe ``lambda`` pozwala utworzyć zwięzły odpowiednik prostej, jednowyrażeniowej funkcji. Poniższy przykład należy rozumieć następująco: do każdej liczby wygenerowanej przez funkcję ``range()`` zastosuj funkcję w postaci wyrażenia lambda podnoszącą argument do kwadratu, a uzyskane wartości zapisz w liście ``kwadraty``. .. raw:: html
Kod nr
.. code-block:: python :linenos: kwadraty = map(lambda x: x**2, range(10)) list(kwadraty) Funkcje *lambda* często stosowane są w poleceniach sortowania jako wyrażenie zwracające klucz (wartość), wg którego mają zostać posortowane elementy. Jeżeli np. mamy listę tupli opisującą uczniów: .. code-block:: python :linenos: uczniowie = [ ('jan','Nowak','1A',15), ('ola','Kujawiak','3B',17), ('andrzej','bilski','2F',16), ('kamil','czuja','1B',14) ] - ``sorted(uczniowie)`` – posortuje listę wg pierwszego elementu każdej tupli, czyli imienia; - ``sorted(uczniowie, key=lambda x: x[1])`` – posortuje listę wg klucza zwróconego przez jednoargumentową funkcję lambda, w tym wypadku będzie to nazwisko; - ``max(uczniowie, key=lambda x: x[3])`` – zwróci najstarszego ucznia; - ``min(uczniowie, key=lambda x: x[3])`` – zwróci najmłodszego ucznia. Filtrowanie danych ========================== Funkcja ``filter()`` jako pierwszy argument pobiera funkcję zwracającą ``True`` lub ``False``, stosuje ją do każdego elementu sekwencji podanej jako argument drugi i zwraca tylko te, które spełniają założony warunek: .. raw:: html
Kod nr
.. code-block:: python :linenos: wyrazy = ['anna', 'ala', 'ela', 'wiola', 'ola'] imiona = filter(lambda imie: len(imie) == 3, wyrazy) list(imiona) Generatory ************************** Generatory (ang. *generators*) to funkcje ułatwiające tworzenie iteratorów. Od zwykłych funkcji różnią się tym, że: - zwracają iterator za pomocą słowa kluczowego ``yield``, - zapamiętują swój stan z momentu ostatniego wywołania, są więc wznawialne (ang. *resumable*), - zwracają następną wartość ze strumienia danych podczas kolejnych wywołań metody ``next()``. Najprostszy przykład generatora zwracającego kolejne liczby parzyste: .. code-block:: python def gen_parzyste(N): for i in range(N): if i % 2 == 0: yield i gen = gen_parzyste(10) next(gen) next(gen) list(gen) Pliki ************************** Czytanie plików tekstowych: .. raw:: html
Kod nr
.. code-block:: python :linenos: with open("test.txt", "r") as f: # odczytywanie linia po linii for linia in f: print(linia.strip()) f = open('test.txt', 'r') for linia in f: # odczytywanie linia po linii print(linia.strip()) f.close() f = open('test.txt', 'r') tresc = f.read() # odczytanie zawartości całego pliku for znak in tresc: # odczytaywanie znak po znaku print(znak) f.close() Pierwsza metoda używająca instrukcji ``with ... as ...`` jest preferowana, ponieważ zapewnia obsługę błędów i dba o zamknięcie pliku. Zapisywanie danych do pliku tekstowego: .. code-block:: python :linenos: dane = ['pierwsza linia', 'druga linia'] with open("output.txt", "w") as f: for linia in dane: f.write(linia + '\n') **Użycie formatu** `csv `_: .. code-block:: python :linenos: import csv # moduł do obsługi formatu csv dane = ([1, 'jan', 'kowalski'], [2, 'anna', 'nowak']) plik = "test.csv" with open(plik, "w", newline='') as plikcsv: tresc = csv.writer(plikcsv) for lista in dane: tresc.writerow(lista) with open(plik, newline='') as plikcsv: # otwórz plik do odczytu tresc = csv.reader(plikcsv) for linia in tresc: # przeglądamy kolejne linie print(linia) **Użycie formatu** `json `_: .. code-block:: python import os import json dane = {'uczen1':[1, 'jan', 'kowalski'], 'uczen2':[2, 'anna', 'nowak']} plik = "test.json" with open(plik, "w") as plikjson: json.dump(dane, plikjson) if os.path.isfile(plik): # sprawdzenie, czy plik istnieje with open(plik, "r") as plikjson: dane = json.load(plikjson) print(dane) Materiały ************************** 1. http://pl.wikibooks.org/wiki/Zanurkuj_w_Pythonie 2. http://brain.fuw.edu.pl/edu/TI:Programowanie_z_Pythonem 3. http://pl.python.org/docs/tut/ 4. http://en.wikibooks.org/wiki/Python_Programming/Input_and_Output 5. https://wiki.python.org/moin/HandlingExceptions 6. http://learnpython.org/pl 7. http://www.checkio.org 8. http://www.codecademy.com 9. https://www.coursera.org