1.5. Pythonizmy

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:

~$ python

1.5.1. Operatory * i **

Operator * służy rozpakowaniu listy zawierającej wiele argumentów, które chcemy przekazać do funkcji:

Kod nr
1
2
3
# 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):

Kod nr
1
2
3
4
5
def kalendarz(data, wydarzenie):
    print("Data:", data,"\nWydarzenie:", wydarzenie)

slownik = {"data" : "10.02.2015", "wydarzenie" : "szkolenie"}
kalendarz(**slownik)

1.5.2. 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().

Kod nr
1
2
3
4
kwadraty = []
for x in range(10):
    kwadraty.append(x**2)
print(kwadraty)

1.5.3. Iteratory

Obiekty, z których pętle odczytują kolejne dane to 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.:

Kod nr
1
2
3
4
5
6
7
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:

Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
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)

1.5.4. 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 generatory wyrażeń (ang. generator expressions), które zwracają iteratory. Poniższy przykład wydrukuje wszystkie imiona z dużej litery:

1
2
3
4
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:

Kod nr
1
2
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.

1.5.5. Wyrażenia listowe

Jeżeli nawiasy okrągłe w generatorze wyrażeń zamienimy na kwadratowe, dostaniemy wyrażenie listowe (ang. list comprehensions), które – jak wskazuje nazwa – zwraca listę:

Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 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:

1.5.5.1. Mapowanie funkcji

Funkcja map() funkcję podaną jako pierwszy argument stosuje do każdego elementu sekwencji podanej jako argument drugi:

Kod nr
1
2
3
4
5
def kwadrat(x):
    return x**2

kwadraty = map(kwadrat, range(10))
list(kwadraty)

1.5.5.2. 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.

Kod nr
1
2
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:

1
2
3
4
5
6
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.

1.5.5.3. 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:

Kod nr
1
2
3
wyrazy = ['anna', 'ala', 'ela', 'wiola', 'ola']
imiona = filter(lambda imie: len(imie) == 3, wyrazy)
list(imiona)

1.5.6. 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:

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)

1.5.7. Pliki

Czytanie plików tekstowych:

Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
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:

1
2
3
4
dane = ['pierwsza linia', 'druga linia']
with open("output.txt", "w") as f:
    for linia in dane:
        f.write(linia + '\n')

Użycie formatu csv:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
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:

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)

1.5.8. 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

Licencja Creative Commons Materiały Python 101 udostępniane przez Centrum Edukacji Obywatelskiej na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.

Utworzony:2017-09-08 o 18:17 w Sphinx 1.5.3
Autorzy:Patrz plik “Autorzy”