V minulém díle jste viděli…¶
Předtavili jsme si polnohodnotné vývojové prostředí VSCode, resp. VSCodium:
- instalace VSCodia a potřebných rozšíření, základní nastavení prostředí
- vyvoření zdrojového souboru v Pythonu (koncovka
.py
) a jeho spuštění ve VSCodiu i mimo něj - použití debuggeru z rozšíření Python pro VSCodium
- zobrazení a editace Jupyter notebooků ve VSCodiu
Ukázali jsme si práci s modulem turtle
pro kreslení obrázků pomocí želví grafiky, například:
import turtle
# draw a square
def square():
for i in range(4):
turtle.forward(100)
turtle.right(90)
square()
# wait until the user closes the window
turtle.mainloop()
Iterátory¶
Iterátory jsou velmi důležitým konceptem Pythonu. Umožňují nám zpracovávat data postupně nebo kombinovat hodnoty z různých zdrojů. Na předchozích cvičeních jsme již s nimi pracovali, i když skrytě, při práci s kontejnery a kdykoliv jsme v programech použili for
-cyklus. Iterátory oceníme především při zpracování velkých objemů dat, kdy umožňují přístup k jednotlivým hodnotám až ve chvíli, kdy jsou potřeba, bez nutnosti ukládání celého objemu dat do paměti.
Iterovatelné objekty (iterables)¶
Základním stavebním kamenem iterace a zpracování dat v Pythonu jsou iterovatelné objekty (iterables). Iterovatelný objekt je jakýkoliv objekt, přes který může být prováděna iterace (tj. můžeme přistupovat k jednotlivým prvkům v objektu postupně, jeden po druhém, například pomocí for
-cyklu). Mezi iterovatelné objekty patří řada vestavěných datových typů v Pythonu, například kontejnery (list
, tuple
, str
, dictionary
, set
, ...), range
nebo datové proudy (např. objekty představující soubory).
Poznámka: O datových proudech si řekneme více na některém z dalších cvičení.
s = [1,2,3]
for x in s:
print(x, end = " ")
1 2 3
Za iteraci na iterovatelném objektu, například v rámci for
-cyklu, je zodpovědný objekt zvaný iterátor. Ten během iterace postupně (jeden po druhém) poskytuje další prvky iterovatelného objektu. Pamatuje si svůj vnitřní stav (ví, které prvky již poskytl a který prvek bude na řadě příště). Jakmile iterátor poskytne (právě jednou) všechny prvky iterovatelného objektu, vyvolá výjimku StopIteraion
, což iteraci ukončí.
Iterátor pro daný iterovatelný objekt získáme pomocí vestavěné funkce iter(iterable)
:
my_list = [1, 5, 4]
my_iterator = iter(my_list)
print(my_iterator)
<list_iterator object at 0x7efcd76ebe50>
Další prvek v iteraci získáme pomocí vestavěné funkce next(iterator)
:
# iterátor poskytuje prvky seznamu jeden po druhém
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
1 5 4
# další volání 'next' vyvolá výjimku `StopIteration`
print(next(my_iterator))
--------------------------------------------------------------------------- StopIteration Traceback (most recent call last) Cell In[5], line 2 1 # další volání 'next' vyvolá výjimku `StopIteration` ----> 2 print(next(my_iterator)) StopIteration:
Poznámka: Pro každý iterovatelný objekt může být iterátor implementován různými způsoby. Pořadí, v jakém iterátor vrací prvky, proto vždy záleží na daném iterovatelném objektu. Např. pro posloupnosti iterátor vrací prvky ve vzestupném pořadí dle jejich indexu.
Iterátor v Pythonu nelze použít opakovaně a neumí se vracet k předchozím hodnotám. Říkáme o něm, že se při použití "vyčerpává". Pokud po vyčerpání iterátoru budeme chtít provést iteraci znovu, musíme vytvořit nový iterátor. Vyzkoušejte si to na následujícím příkladu:
my_list = [1, 5, 4, 7, 9]
# vytvořte nový iterátor:
my_iterator = iter(my_list)
# zkuste si následující buňku pouštět opakovaně:
print(next(my_iterator))
# po vyčerpání iterátoru si vytvořte nový spuštěním předchozí buňky
9
Pro jeden iterovatelný objekt můžeme zároveň používat více iterátorů:
my_list = [1, 5, 4]
it_1 = iter(my_list)
it_2 = iter(my_list)
print("první: ", next(it_1))
print("první: ", next(it_1))
print(" druhý: ", next(it_2))
print("první: ", next(it_1))
print(" druhý: ", next(it_2))
první: 1 první: 5 druhý: 1 první: 4 druhý: 5
Poznámka: Iterovatelný objekt si můžeme představit jako knížku, která se skládá z jednotlivých stránek a iterátory si můžeme představit jako záložky v této knížce.
V programech s iterátory obvykle nepracujeme přímo, ale skrytě. Již jsme zmínili, že na iterátorech je založený for
-cyklus. Při for
-cyklu se pro iterovatelný objekt nejprve vytvoří iterátor a pak se na něm v cyklu volá next()
, dokud se iterátor nevyčerpá. Tento princip ilustruje následující ukázka:
my_list = [1, 8, 3]
for x in my_list:
print(x, end = " ")
... # do something
1 8 3
Kód v předchozí buňce můžeme přepsat tímto způsobem:
my_list = [1, 8, 3]
iterator = iter(my_list)
while True:
try:
x = next(iterator)
print(x, end = " ")
... # do something
except StopIteration:
break
1 8 3
Poznámka:
S dvojicí bloků try:
a except:
jsme se již setkali ve veřejných testech domácích úkolů.
Slouží k ošetřování (neboli odchytávání) chyb (výjimek). Pokud uvnitř bloku try:
dojde k chybě, tj. k vyvolání výjimky, provádění bloku try:
se okamžitě ukončí a přejde se do bloku except:
.
Pokud k chybě nedojde, blok except:
se přeskočí.
Více o výjimkách a obecně o ošetřování chyb si řekneme na jednom z následujících cvičení.
Jako zdroj hodnot pro for
-cyklus můžeme použít přímo iterátor, ale je třeba si uvědomit, že se po jednom použití vyčerpá a už nelze použít znova:
my_list = [1, 8, 3]
iterator = iter(my_list)
print("poprvé:")
for x in iterator:
print(x, end = " ")
print()
print("podruhé:")
for x in iterator:
print(x, end = " ")
print()
poprvé: 1 8 3 podruhé:
Pokud jako zdroj hodnot pro for
-cyklus použijeme přímo iterovatelný objekt, předchozí problém nenastane, protože při spuštění for
-cyklu se pro něj vytvoří vždy nový iterátor:
print("poprvé:")
for x in my_list:
print(x, end = " ")
print()
print("podruhé:")
for x in my_list:
print(x, end = " ")
print()
poprvé: 1 8 3 podruhé: 1 8 3
Poznámka: Iterátory v Pythonu pracují na zásadě líného vyhodnocování (lazy evaluation). To znamená, že prvky nejsou načítány do paměti najednou, ale jsou získávány až ve chvíli, kdy jsou potřeba. To je užitečné pro zpracování velkých datových sad, protože tak snížíme paměťové nároky programu.
Vestavěné funkce, které vrací iterátory¶
Kromě funkce iter()
jsou v Pythonu i další vestavěné funkce, které vrací iterátory:
Funkce | Krátký popis |
---|---|
reversed(sequence) |
Vrací iterátor, který poskytuje prvky posloupnosti sequence v opačném pořadí. |
map(function, iterable) |
Vrací iterátor přes function(x) pro x z iterable . |
filter(function, iterable) |
Vrací iterátor přes ta x z iterable , pro která function(x)==True . |
zip(*iterables) |
Vrací iterátor přes n-tice (x, y,...) pro x z iterable1 , y z iterable2 ,... |
enumerate(iterable,start=0) |
Vrací objekt enumerate - iterátor přes dvojice (index, x) pro x z iterable . |
Použití těchto funkcí si ukážeme na několika ilustračních příkladech:
my_list = [1,7,2,6,3,1,2]
# iterace přes prvky seznamu v opačném pořadí:
for x in reversed(my_list):
print(x, end=" ")
print("")
# funkce 'reversed' vrací iterátor (ne seznam):
m = reversed(my_list)
print(m)
# iterátor mohu převést na seznam:
reversed_list = list(m)
print(reversed_list)
print(my_list)
2 1 3 6 2 7 1 <list_reverseiterator object at 0x7f0420031780> [2, 1, 3, 6, 2, 7, 1] [1, 7, 2, 6, 3, 1, 2]
Iterátory můžeme převézt na různé typy kontejnerů - voláním příslušné funkce (konstruktoru): např. list(iterator)
, tuple(iterator)
, set(iterator)
:
my_tuple = (1,7,2,6,3,1,2)
reversed_tuple = tuple(reversed(my_tuple))
reversed_list = list(reversed(my_tuple))
my_set = set(iter(my_tuple))
print(reversed_tuple)
print(reversed_list)
print(my_tuple)
print(my_set)
(2, 1, 3, 6, 2, 7, 1) [2, 1, 3, 6, 2, 7, 1] (1, 7, 2, 6, 3, 1, 2) {1, 2, 3, 6, 7}
Funkce filter(f, iterable)
vytváří iterátor, který poskytuje pouze ty prvky z iterable, pro které funkce f(x)
vrací hodnotu True
.
def is_even(number):
return number % 2 == 0
numbers = (1, 2, 3, 4, 5, 6, 7, 8)
print("\ncyklus:", end = " ")
# iterace jen přes sudá čísla z n-tice klasicky:
for x in numbers:
if is_even(x):
print(x, end=" ")
# iterace jen přes sudá čísla z n-tice klasicky:
s = []
for x in numbers:
if is_even(x):
s.append(x)
even_numbers = tuple(s)
print("\n",even_numbers)
print("\nfilter:", end = " ")
# iterace jen přes sudá čísla z n-tice pomocí filter:
for x in filter(is_even, numbers):
print(x, end=" ")
# iterátor mohu převést na iterovatelný objekt (např. n-tici):
even_numbers = tuple(filter(is_even, numbers))
print("\n",even_numbers)
cyklus: 2 4 6 8 (2, 4, 6, 8) filter: 2 4 6 8 (2, 4, 6, 8)
Funkce map(f, iterable)
vytváří iterátor, který poskytuje f(x)
pro každý prvek x
z iterable
.
def square(number):
return number ** 2
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
print("\ncyklus:", end = " ")
# iterace přes druhé mocniny čísel ze seznamu klasicky:
for x in numbers:
print(square(x), end=" ")
# iterace přes druhé mocniny čísel ze seznamu klasicky:
s = []
for x in numbers:
s.append(square(x))
print("\n",s)
print("\nmap: ", end = " ")
# iterace přes druhé mocniny čísel ze seznamu pomocí map:
for x in map(square, numbers):
print(x, end=" ")
print("")
# iterátor mohu převést na iterovatelný objekt (např. seznam):
squares = list(map(square, numbers))
print(squares)
cyklus: 1 4 9 16 25 36 49 64 [1, 4, 9, 16, 25, 36, 49, 64] map: 1 4 9 16 25 36 49 64 [1, 4, 9, 16, 25, 36, 49, 64]
Poznámka:
Funkce filter()
a map()
se dají použít elegantněji v kombinaci s tzv. anonymními (lambda) funkcemi, jak ukazují následující příklady.
even_numbers = tuple(filter(lambda x: x % 2 == 0, numbers)) squares = list(map(lambda x: x ** 2, numbers))Tato látka je ovšem nad rámec tohoto základního kurzu. Více o anonymních funkcích se dozvíte např. v dokumentaci.
Funkce zip(*iterables)
vytvoří iterátor n-tic pro prvky z několika iterovatelných objektů:
names = ["Anna", "Bob", "Cyril"]
salaries = [25000, 35000, 45000]
print(list(zip(names, salaries)))
for name, salary in zip(names, salaries):
print(f"{name} má plat {salary} Kč.")
[('Anna', 25000), ('Bob', 35000), ('Cyril', 45000)] Anna má plat 25000 Kč. Bob má plat 35000 Kč. Cyril má plat 45000 Kč.
Pokud mají iterovatelné objekty různé počty prvků, funkce zip prvky navíc ignoruje:
x = [1, 2, 3, 4, 5]
y = ("a", "b", "c")
z = { 11 : "A", 12 : "B", 13 : "C", 14 : "D"}
w = list(zip(x,y,z.items()))
print(w)
[(1, 'a', (11, 'A')), (2, 'b', (12, 'B')), (3, 'c', (13, 'C'))]
Funkce enumerate(iterable, start=0)
vrací enumerate objekt, což je iterátor, který poskytuje dvojice (index,x)
pro každý prvek x
z iterable
.
numbers = {10,1,2,0}
print(enumerate(numbers))
# iterace:
for index, value in enumerate(numbers):
print(f"Index: {index}, Value: {value}")
string = "abrakadabra"
print(list(enumerate(string)))
# volitelný parametr start nastaví začátek číslování:
print(list(enumerate(string, start=10)))
<enumerate object at 0x7f04035f0ef0> Index: 0, Value: 0 Index: 1, Value: 1 Index: 2, Value: 10 Index: 3, Value: 2 [(0, 'a'), (1, 'b'), (2, 'r'), (3, 'a'), (4, 'k'), (5, 'a'), (6, 'd'), (7, 'a'), (8, 'b'), (9, 'r'), (10, 'a')] [(10, 'a'), (11, 'b'), (12, 'r'), (13, 'a'), (14, 'k'), (15, 'a'), (16, 'd'), (17, 'a'), (18, 'b'), (19, 'r'), (20, 'a')]
Třídění iterovatelných objektů¶
K třídění (řazení) prvků iterovatelných objektů slouží funkce sorted(iterable, /, *, key=None, reverse=False
). Funkce vrací nový seznam. Ten obsahuje všechny prvky iterovatelného objektu iterable
seřazené od nejmenšího po největší (nebo od největšího po nejmenší) pomocí operátorů pro porovnání (<=
). Defaultně řadí funkce prvky vzestupně, pro sestupné pořadí je třeba nastavit hodnotu volitelného parametru reverse=True
:
my_tuple = (5, 2, 3, 1, 4)
sorted_list = sorted(my_tuple)
print(sorted_list)
sorted_list_1 = sorted(my_tuple, reverse=True)
print(sorted_list_1)
[1, 2, 3, 4, 5] [5, 4, 3, 2, 1]
my_tuple = (True, False, True)
sorted_list = sorted(my_tuple)
print(sorted_list)
sorted_list_1 = sorted(my_tuple, reverse=True)
print(sorted_list_1)
[False, True, True] [True, True, False]
# stringy:
my_set = {"abc","abd", "ABC", "aBc", "ab", "abČ"}
sorted_list = sorted(my_set)
print(sorted_list)
['ABC', 'aBc', 'ab', 'abc', 'abd', 'abČ']
# porovnávat a třídit můžeme i posloupnosti:
print((0,True,"abc") > (0,False,"ab"),
(0,True,"abc") > (0,True,"ab"))
my_list = [
(1, True, "abc"),
(0, True, "ab"),
(0, False, "abc"),
(0, True, "abc"),
(1, True, "ab"),
(0, False, "abc")
]
sorted_list = sorted(my_list)
print(sorted_list)
True True [(0, False, 'abc'), (0, False, 'abc'), (0, True, 'ab'), (0, True, 'abc'), (1, True, 'ab'), (1, True, 'abc')]
my_dict = {3:"c", 2:"b", 4:"a"}
sorted_list = sorted(my_dict)
print(sorted_list)
sorted_list = sorted(my_dict.values())
print(sorted_list)
sorted_list = sorted(my_dict.items())
print(sorted_list)
dict_1 = dict(sorted(my_dict.items()))
print(dict_1)
[2, 3, 4] ['a', 'b', 'c'] [(2, 'b'), (3, 'c'), (4, 'a')] {2: 'b', 3: 'c', 4: 'a'}
Funkce sorted
má další volitelný parametr key
, který definuje metodu nebo funkci, která bude zavolaná na každý prvek předtím, než se provede třídění.
my_string = "Anna and Bob decided to buy a beautiful house in Brighton"
my_list = my_string.split()
print("original: ", my_list)
print("without key:", sorted(my_list))
print("with key: ",sorted(my_list, key=str.lower))
original: ['Anna', 'and', 'Bob', 'decided', 'to', 'buy', 'a', 'beautiful', 'house', 'in', 'Brighton'] without key: ['Anna', 'Bob', 'Brighton', 'a', 'and', 'beautiful', 'buy', 'decided', 'house', 'in', 'to'] with key: ['a', 'and', 'Anna', 'beautiful', 'Bob', 'Brighton', 'buy', 'decided', 'house', 'in', 'to']
print("sort by lenghts:", sorted(my_list, key=len))
sort by lenghts: ['a', 'to', 'in', 'and', 'Bob', 'buy', 'Anna', 'house', 'decided', 'Brighton', 'beautiful']
Iterovatelné objekty často potřebujeme třídit podle hodnot na nějakém indexu:
my_tuples = [(3, 'bc', True), (3, 'ba', False), (4, 'bba', True)]
sorted_list = sorted(my_tuples)
print("default: ", sorted_list)
def second(x):
return x[1]
def third(x):
return x[2]
# setřídění podle druhé hodnoty v n-tici:
sorted_list = sorted(my_tuples, key=second)
print("dle druhého: ", sorted_list)
# setřídění podle druhé hodnoty v n-tici:
sorted_list = sorted(my_tuples, key=lambda x : x[1])
print("dle druhého: ", sorted_list)
# setřídění podle třetí hodnoty v n-tici:
sorted_list = sorted(my_tuples, key=third)
print("dle třetího: ", sorted_list)
default: [(3, 'ba', False), (3, 'bc', True), (4, 'bba', True)] dle druhého: [(3, 'ba', False), (4, 'bba', True), (3, 'bc', True)] dle druhého: [(3, 'ba', False), (4, 'bba', True), (3, 'bc', True)] dle třetího: [(3, 'ba', False), (3, 'bc', True), (4, 'bba', True)]
Třídění seznamů¶
Narozdíl od jiných iterovatelných objektů můžeme u seznamů kromě funkce sorted()
použít také metodu sort(*, key=None, reverse=False)
. Ta narozdíl od funkce sorted()
nevrací nový seznam, ale modifikuje ten původní:
my_list = [-5, 2, -3, 1, 4]
my_list.sort()
print(my_list)
my_list.sort(reverse=True)
print(my_list)
my_list.sort(reverse=True, key=abs)
print(my_list)
[-5, -3, 1, 2, 4] [4, 2, 1, -3, -5] [-5, 4, -3, 2, 1]
U seznamů je také třeba dávat pozor, abychom si nespletli funkci reversed()
, která vrací iterátor a metodu reverse()
, která modifikuje původní seznam:
my_list = [5, 2, 3, 1, 4]
print(list(reversed(my_list)))
print(my_list)
my_list.reverse()
print(my_list)
[4, 1, 3, 2, 5] [5, 2, 3, 1, 4] [4, 1, 3, 2, 5]
Další užitečné vestevěné funkce¶
Kromě funkcí, které vrací iterátory a funkce sorted
existuje i řada dalších užitečných funkcí nad iterovatelnými objekty:
Funkce | Krátký popis
-----------------------------------|-----------------------------
all(iterable)
| Vrací True
, pokud každý prvek z iterable
má hodnotu True
, jinak vrací False
.
any(iterable)
| Vrací True
, pokud alespoň jeden prvek z iterable
má hodnotu True
, jinak vrací False
.
sum(iterable,/,start=0)
| Vrací součet prvků z iterable
.
max(iterable,/,key=None)
| Vrací největší prvek z iterable
.
min(iterable,/,key=None)
| Vrací nejmenší prvek z iterable
.
range(stop)
, range(start,stop)
, range(start,stop,step)
| Vrací iterovatelný objekt typu range
, nemodifikovatelnou posloupnost čísel.
Použití těchto funkcí si ukážeme na několika ilustračních příkladech:
# any, all, sum, max, min:
numbers = {0,1,2,10}
print(any(numbers), all(numbers), sum(numbers), max(numbers), min(numbers))
# range:
print(range(3))
print(list(range(3)))
True False 13 10 0 range(0, 3) [0, 1, 2]
Poznámka: Další funkce pro práci s iterátory a iterovatelnými objekty naleznete v modulu itertools. Jsou zde například funkce vracející kombinatorické iterátory:
import itertools
# permutace:
print(list(itertools.permutations("abcd")))
for x in itertools.permutations("abcd"):
print("".join(x), end=" ")
print("")
# variace:
for x in itertools.permutations("abcd",2):
print("".join(x), end=" ")
print("")
# kombinace:
for x in itertools.combinations("abcd",2):
print("".join(x), end=" ")
print("")
# kombinace s opakováním:
for x in itertools.combinations_with_replacement("abcd",2):
print("".join(x), end=" ")
[('a', 'b', 'c', 'd'), ('a', 'b', 'd', 'c'), ('a', 'c', 'b', 'd'), ('a', 'c', 'd', 'b'), ('a', 'd', 'b', 'c'), ('a', 'd', 'c', 'b'), ('b', 'a', 'c', 'd'), ('b', 'a', 'd', 'c'), ('b', 'c', 'a', 'd'), ('b', 'c', 'd', 'a'), ('b', 'd', 'a', 'c'), ('b', 'd', 'c', 'a'), ('c', 'a', 'b', 'd'), ('c', 'a', 'd', 'b'), ('c', 'b', 'a', 'd'), ('c', 'b', 'd', 'a'), ('c', 'd', 'a', 'b'), ('c', 'd', 'b', 'a'), ('d', 'a', 'b', 'c'), ('d', 'a', 'c', 'b'), ('d', 'b', 'a', 'c'), ('d', 'b', 'c', 'a'), ('d', 'c', 'a', 'b'), ('d', 'c', 'b', 'a')] abcd abdc acbd acdb adbc adcb bacd badc bcad bcda bdac bdca cabd cadb cbad cbda cdab cdba dabc dacb dbac dbca dcab dcba ab ac ad ba bc bd ca cb cd da db dc ab ac ad bc bd cd aa ab ac ad bb bc bd cc cd dd
Příklady:¶
1a. palindrom Napište funkci palindrome(sequence)
, která ověří, zda je daná posloupnost palindromem (tj. zda se čte stejně od začátku jako od konce). Využijte některou z funkcí, se kterými jsme se seznámili na tomto cvičení (např. reversed
).
def palindrome(sequence):
#return sequence == sequence[::-1]
return list(reversed(sequence)) == list(sequence)
assert palindrome("kobylamamalybok")
assert palindrome((1,23,6,6,23,1))
assert palindrome([1,23,6,6,23]) == False
1b. počet palindromů Napište funkci count_palindromes(sequence)
, která vrátí počet prvků z posloupnosti sequence
, které jsou palindromy. Využijte některé z funkcí, se kterými jsme se seznámili na tomto cvičení (např. map
,sum
).
# nápověda 1:
print(sum([1,2,3,4]))
print(True + True)
print(sum([True, False, True]))
10 2 2
# nápověda 2:
word_list = ["ananas", "otto", "radar", "hello", "level", "civic", "python"]
for x in map(palindrome,word_list):
print(x, end = " ")
print()
print(list(map(palindrome,word_list)))
print(list(filter(palindrome,word_list)))
False True True False True True False [False, True, True, False, True, True, False] ['otto', 'radar', 'level', 'civic']
# řešení bez map, sum:
def count_palindromes1(sequence):
suma = 0
for x in sequence:
if palindrome(x):
suma += 1
return suma
def count_palindromes(sequence):
suma = 0
for x in sequence:
suma += palindrome(x)
return suma
word_list = ["ananas", "otto", "radar", "hello", "level", "civic", "python"]
assert count_palindromes(word_list) == 4
# řešení s map:
def count_palindromes(sequence):
suma = 0
for x in map(palindrome,word_list):
suma += x
return suma
word_list = ["ananas", "otto", "radar", "hello", "level", "civic", "python"]
assert count_palindromes(word_list) == 4
# řešení s map, sum:
def count_palindromes(sequence):
return sum(map(palindrome,word_list))
word_list = ["ananas", "otto", "radar", "hello", "level", "civic", "python"]
assert count_palindromes(word_list) == 4
1c. palindromy Napište funkci palindromes(sequence)
, která vrátí seznam prvků z posloupnosti sequence
, které jsou palindromy. Využijte některou z funkcí, se kterými jsme se seznámili na tomto cvičení (např. filter
).
# řešení bez filter:
def palindromes(sequence):
result = []
for x in sequence:
if palindrome(x):
result.append(x)
return result
word_list = ["ananas", "otto", "radar", "hello", "level", "civic", "python"]
assert palindromes(word_list) == ['otto', 'radar', 'level', 'civic']
# zbytečně dlouhé řešení s filter:
def palindromes(sequence):
result = []
for x in filter(palindrome,sequence):
result.append(x)
return result
word_list = ["ananas", "otto", "radar", "hello", "level", "civic", "python"]
assert palindromes(word_list) == ['otto', 'radar', 'level', 'civic']
# řešení s filter:
def palindromes(sequence):
return list( filter(palindrome,sequence))
word_list = ["ananas", "otto", "radar", "hello", "level", "civic", "python"]
assert palindromes(word_list) == ['otto', 'radar', 'level', 'civic']
- vytvoř loginy Máme dva seznamy, v jednom jsou jména osob a v druhém jim přiřazená čísla (ID). Napište funkci, která vrátí seznam loginů. Každý login bude vytvořen tak, že vezmeme první 4 písmena ze jména, změníme je na malá, doplníme případně znakem
'_'
na 4 znaky , a na konec připojíme celé ID. Využijte některou z funkcí, se kterými jsme se seznámili na tomto cvičení (např.zip
nebomap
).
def f(tuple):
name, id = tuple
return name[:4].lower().ljust(4,'_') + str(id)
def create_logins(names, ids):
return list(map(f,zip(names,ids)))
names = ["John", "Alice", "Eduard", "Bob", "Ed"]
ids = [143,787,546,165,798]
assert create_logins(names,ids) == ['john143', 'alic787', 'edua546', 'bob_165', 'ed__798']
- setřiď podle id Napište funkci, která pro seznam loginů ve tvaru
"jméno"+"id"
, kdeid
je tvořeno čtyřmi číslicemi, vrátí nový seznam, kde budou loginy setříděny sestupně podleid
def f(x):
return int(x[-4:])
def sort_logins_by_id(logins):
return sorted(logins, key=f, reverse=True)
login_list = ["john1234", "alice5678", "bob2345", "eve8765"]
assert sort_logins_by_id(login_list) == ['eve8765', 'alice5678', 'bob2345', 'john1234']
assert login_list == ["john1234", "alice5678", "bob2345", "eve8765"]
4a. setřiď podle vzdálenosti Napište funkci, která vezme seznam bodů v n-rozměrném Euklidovském prostoru a vrátí ho setříděný vzestupně podle vzdálenosti bodů od bodu (0,0,...,0). Body jsou reprezentované jako n-tice čísel.
def dist(vector):
s = 0
for x in vector:
s += x**2
return s**0.5
def sort_vectors_by_distance(vectors):
return sorted(vectors,key=dist)
vectors = [(3, 4.5, 0), (1, 2, -3), (0, 0, 0), (-1, -1, 1), (0.5, 5, -1)]
sorted_vectors = sort_vectors_by_distance(vectors)
assert sorted_vectors == [(0, 0, 0), (-1, -1, 1), (1, 2, -3), (0.5, 5, -1), (3, 4.5, 0)]
assert vectors == [(3, 4.5, 0), (1, 2, -3), (0, 0, 0), (-1, -1, 1), (0.5, 5, -1)]
4b. Změňte předchozí funkci tak, aby setřídila přímo původní seznam vectors
:
def sort_vectors_by_distance(vectors):
vectors.sort(key=dist)
vectors = [(3, 4.5, 0), (1, 2, -3), (0, 0, 0), (-1, -1, 1), (0.5, 5, -1)]
sort_vectors_by_distance(vectors)
assert vectors == [(0, 0, 0), (-1, -1, 1), (1, 2, -3), (0.5, 5, -1), (3, 4.5, 0)]
- známky Seznam studentů je reprezentovaný jako seznam slovníků, kde pro každého studenta je jeho jméno a seznam získaných známek. Například:
grades = [{'name': 'Adam', 'grades': [1, 2, 3, 1, 2]},
{'name': 'Martin', 'grades': [1, 2, 2]},
{'name': 'Filip', 'grades': [1, 3]},
{'name': 'David', 'grades': [1, 2, 2, 3]},
{'name': 'Jakub', 'grades': [1, 2, 2, 1, 1]}]
5a. Napište funkci, která vypíše jména studentů a jejich průměr známek v pořadí od studenta s nejlepším průměrem známek po studenta s nejhorším průměrem. Využijte některou z funkcí, se kterými jsme se seznámili na tomto cvičení (např. sorted
).
def average(student):
return sum(student["grades"])/len(student["grades"])
def sort_students_by_average_grade(students):
for x in sorted(students,key=average):
print("student:",x["name"], ", prumer znamek: ", average(x))
sort_students_by_average_grade(grades)
student: Jakub , prumer znamek: 1.4 student: Martin , prumer znamek: 1.6666666666666667 student: Adam , prumer znamek: 1.8 student: Filip , prumer znamek: 2.0 student: David , prumer znamek: 2.0
5b. Napište funkci, která vrátí seznam jmen studentů, kteří nemají dostatek známek (alespoň n
). Využijte některou z funkcí, se kterými jsme se seznámili na tomto cvičení (např. filter
).
def students_with_not_enough_grades(students, n):
...
assert students_with_not_enough_grades(grades,4) == ['Martin', 'Filip']
['Martin', 'Filip']
6a. indexy Napište funkci, která vrátí seznam všech indexů, kde se v řetězci string
vyskytuje znak char
.
Využijte některou z funkcí, se kterými jsme se seznámili na tomto cvičení (např. enumerate
).
def find_letter_indexes(string, letter):
...
assert find_letter_indexes("hello world", "l") == [2, 3, 9]
6b. indexy Napište funkci, která vrátí seznam všech indexů, na kterých v řetězci string
začíná podstring substring
.
def find_substring_indexes(string, substring):
...
assert find_substring_indexes("ara aaraara arara", "ara") == [0, 5, 8, 12, 14]
- hra uhodni heslo Napište funkci
guess_password
, která se pokusí 'uhodnout' heslopasswd
. Heslo má má danou délkun
a může se skládat ze znaků uvedených v stringuchars
. Funkce bude volat funkcievaluate_password
, která odpoví, zda je daný string správné heslo nebo ne. Využijte některou z funkcí z moduluitertools
. Vyzkoušejte si, jak dlouho bude programu trvat uhodnutí různě dlouhých a různě složitých hesel.
chars = "0123456789"
#chars = "0123456789abcdefghijklmnopqrstuvwxyz"
n = 4
def evaluate_password(string):
''' Returns True if string == passwd
'''
passwd = chars[-1]*n
return string == passwd
def guess_password(chars, n):
...
passwd = guess_password(chars, n)
print("Finished: ", passwd)
Finished: None