Cvičení č. 16 rozšířené o poznámky ze cvičení a řešení některých příkladů (ZS 2025/26)¶
V minulém díle jste viděli…¶
Iterovatelné objekty (iterables) v Pythonu jsou objekty, přes které může být provedena iterace, např. pomocí for-cyklu. Mezi iterovatelné objekty patří např. kontejnery. Za iteraci na iterovatelném objektu je zodpovědný objekt zvaný iterátor, který postupně poskytuje jednotlivé prvky iterovatelného objektu.
Iterátor pro daný iterovatelný objekt získáme pomocí vestavěné funkce iter(iterable), další prvek v iteraci získáme pomocí funkce next(iterator). Jakmile iterátor poskytne všechny prvky iterovatelného objektu, vyvolá výjimku StopIteraion, což iteraci ukončí:
my_list = [1, 5, 4]
my_iterator = iter(my_list)
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
1 5 4
--------------------------------------------------------------------------- StopIteration Traceback (most recent call last) Cell In[1], line 7 5 print(next(my_iterator)) 6 print(next(my_iterator)) ----> 7 print(next(my_iterator)) StopIteration:
V programech s iterátory často nepracujeme přímo, ale skrytě - na iterátorech je založený for-cyklus:
my_list = [1, 8, 3]
for x in my_list:
... # do something
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)
... # do something
except StopIteration:
break
# další ukázka
s = [1, 2, 4, 3]
x = reversed(s)
x
<list_reverseiterator at 0x7fe2c0121a20>
for x in reversed(s):
print(x, end = " ")
t = tuple(reversed(s))
t
3 4 2 1
(3, 4, 2, 1)
Seznámili jsme se s několika užitečnými vestavěnými funkcemi v Pythonu, 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. |
A s dalšími vestavěnými funkcemi nad iterovatelnými objekty:
| Funkce | Krátký popis |
|---|---|
sorted(iterable, /, *, key=None, reverse=False) |
Vrací setříděný seznam prvků z iterable. |
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. |
Generátory¶
Generátory jsou zvláštním druhem iterátoru, který neiteruje přes existující iterovatelný objekt, ale přes průběžně generované hodnoty. Můžeme ho vytvořit pomocí tzv. generátorové funkce (generator function) nebo pomocí tzv. generátorového výrazu (generator expression).
Generátorová funkce je taková funkce, která hodnoty nevrací (pomocí příkazu return), ale generuje (pomocí příkazu yield). Například:
def print_squares(n):
for x in range(n):
print(x ** 2, end = " ")
print_squares(8)
0 1 4 9 16 25 36 49
def list_squares(n):
l = []
for x in range(n):
l.append(x ** 2)
return l
list_squares(8)
[0, 1, 4, 9, 16, 25, 36, 49]
def generate_squares(n):
for x in range(n):
yield x ** 2
# přes generátor mohu iterovat:
for x in generate_squares(8):
print(x, end = " ")
0 1 4 9 16 25 36 49
# nebo generátor převedu na kontejner:
tuple(generate_squares(8))
(0, 1, 4, 9, 16, 25, 36, 49)
Kdykoliv v programu zavoláme generátorovou funkci, funkce vrátí nový generátor - tj. iterátor, který iteruje přes hodnoty generované pomocí yield.
m = generate_squares(5)
print(m)
<generator object generate_squares at 0x7f6bb0845ff0>
for x in m:
print(x, end = " ")
0 1 4 9 16
# ukázka: generátor se použitím vyčerpává
for x in m:
print(x, end = " ")
print("\npodruhe")
for x in m:
print(x, end = " ")
0 1 4 9 16 podruhe
# ukázka: generátor se použitím vyčerpává
# řešení: pokaždé iteruji přes nový generátor:
for x in generate_squares(5):
print(x, end = " ")
print("\npodruhe")
for x in generate_squares(5):
print(x, end = " ")
0 1 4 9 16 podruhe 0 1 4 9 16
Podrobněji:
Generátor si pamatuje aktuální pozici v rámci funkce. Při volání next() iterátor spustí generátorovou funkci od aktuální pozice. Provádění příkazů přeruší u příkazu yield a jako návratovou hodnotu funkce next() poskytne příslušnou hodnotu. Při dalším volání next() funkce pokračuje dál od daného místa. Například:
def generate_whatever():
x = 1
yield x
x = 2
yield x
yield "the end"
for x in generate_whatever():
print(x)
1 2 the end
m = generate_whatever()
print(m)
<generator object generate_whatever at 0x7fe2c02e4a00>
# opět si zkuste pustit tuto buňku opakovaně:
print(next(m))
1
# generátor můžeme převést na iterovatelný objekt:
s = tuple(generate_whatever())
print(s)
(1, 2, 'the end')
# nebo přes něj můžeme iterovat:
for x in generate_whatever():
print(x)
1 2 the end
# další ukázka: generátor hodnot od 0 do n-1:
def my_range(n):
i = 0
while i < n:
yield i
i = i + 1
for x in my_range(21):
print(x, end = " ")
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Poznámka: Generátory šetří časové i paměťové nároky programu: nemusíme uchovávat všechna data v paměti najednou (např. v kontejneru), hodnoty jsou generované jedna po druhé až ve chvíli, kdy jsou potřeba.
Příklady¶
1a. Generátor dělitelů. Napište generátorovou funkci, která vrátí generátor všech dělitelů zadaného přirozeného čísla n. Čísla budou generována v pořadí od nejmenšího po největší.
def divisors_print(n): # vypíše dělitele
for i in range(1, n+1):
if n % i == 0:
print(i, end = " ")
divisors_print(504)
1 2 3 4 6 7 8 9 12 14 18 21 24 28 36 42 56 63 72 84 126 168 252 504
def divisors(n): # vrátí seznam dělitelů
l = []
for i in range(1, n+1):
if n % i == 0:
l.append(i)
return l
print(divisors(504))
[1, 2, 3, 4, 6, 7, 8, 9, 12, 14, 18, 21, 24, 28, 36, 42, 56, 63, 72, 84, 126, 168, 252, 504]
def divisors_generator(n): # vrátí generátor dělitelů
for i in range(1, n+1):
if n % i == 0:
yield i
s = tuple(divisors_generator(27))
print(s)
for i in divisors_generator(27):
print(i, end = " ")
(1, 3, 9, 27) 1 3 9 27
def divisors_generator(n):
for i in range(1, n+1):
if n % i == 0:
yield i
n = 24
for divisor in divisors_generator(n):
print(divisor, end=' ')
print(list(divisors_generator(504)))
assert list(divisors_generator(504)) == [1, 2, 3, 4, 6, 7, 8, 9, 12, 14, 18, 21, 24, 28, 36, 42, 56, 63, 72, 84, 126, 168, 252, 504]
1 2 3 4 6 8 12 24 [1, 2, 3, 4, 6, 7, 8, 9, 12, 14, 18, 21, 24, 28, 36, 42, 56, 63, 72, 84, 126, 168, 252, 504]
2a. Generátor posloupnosti Napište generátorovou funkci, která vrátí generátor prvků následující posloupnosti (pro dané n): 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 ... 1 2 ... n.
def sequence_generator(n):
for i in range(1, n+1):
for j in range(1, i+1):
yield j
n = 5
generator = sequence_generator(n)
for num in generator:
print(num, end=' ')
print(list(sequence_generator(8)))
assert list(sequence_generator(8)) == [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8]
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8]
4a. Generátor délek slov. Naprogramujte generátorovou funkci, která vrátí generátor délek všech slov v textu. Předpokládejme, že slova jsou oddělená pomocí obyčejných mezer (možná několika za sebou). Hodit se mohou i metody pro stringy (např. split()).
text = "Toto je příklad textu s několika slovy oddělenými mezerami"
print(text.split())
['Toto', 'je', 'příklad', 'textu', 's', 'několika', 'slovy', 'oddělenými', 'mezerami']
def word_lengths_generator(text):
for word in text.split():
yield len(word)
#print(word, end = ", ")
text = "Toto je příklad textu s několika slovy oddělenými mezerami"
for length in word_lengths_generator(text):
print(length, end=' ')
assert (list(word_lengths_generator(text)) == [4, 2, 7, 5, 1, 8, 5, 10, 8])
4 2 7 5 1 8 5 10 8
# skoncili jsme zde
Generátorové výrazy a generátorová notace modifikovatelných kontejnerů¶
Generátorové výrazy umožňují vytvářet jednoduché generátory elegantně bez nutnosti vytváření generátorových funkcí. Generátorová notace (comprehension) u modifikovatelných (mutable) kontejnerů (list, set, dict) nám pak výrazně zjednodušuje vytváření a zpracování těchto objektů.
Základní syntaxe je následující:
python:
new_generator = (expression for member in iterable)
new_list = [expression for member in iterable]
new_set = {expression for member in iterable}
new_dict = {key:expression for member in iterable}
Výrazy se liší jen typem použitých závorek. Pokud použijeme kulaté závorky, bude výsledkem generátor, jinak příslušný kontejner. Použitou syntaxi si vysvětlíme na několika následujících příkladech:
Například pro seznam příkaz s = [expression for member in iterable] můžeme přepsat jako:
python:
s = []
for member in iterable:
s.append(expression)
Obdobně pro množinu s = {expression for member in iterable}:
python:
s = set()
for member in iterable:
s.add(expression)
Pro slovník d = {key:expression for member in iterable}:
python:
d = {}
for member in iterable:
d[key] = expression
Ukážeme si to na konkrétních příkladech:
# ukázky pro seznam + bez generátorové notace vs. s ní
t = (1, 6, 2)
#s = [ ... for ... in ... ]
s = [ x for x in t ]
print(s)
s = [ 1 for x in t ]
print(s)
s = [ 2 * x for x in t ]
print(s)
[1, 6, 2] [1, 1, 1] [2, 12, 4]
# to samé dvěma způsoby:
s = [ 2 * x for x in t ]
print(s)
s = []
for x in t:
s.append(2*x)
s
[2, 12, 4]
[2, 12, 4]
# pro množinu,...
s = { 2 * x for x in t }
print(s)
{2, 12, 4}
# pro slovnik...
s = { x:str(x) for x in t }
print(s)
{1: '1', 6: '6', 2: '2'}
# přímo generátor...
g = (2 * x for x in t)
g
<generator object <genexpr> at 0x7fe2c0130e10>
list(g)
[2, 12, 4]
# dvakrát to samé:
s = list(2 * x for x in t)
s
[2, 12, 4]
s = [2 * x for x in t]
s
[2, 12, 4]
# generátorová notace seznamu, množiny a slovníku:
my_tuple = (1,8,3)
my_list = [x*2 for x in my_tuple]
my_set = {x*2 for x in my_tuple}
my_dict = {x:x*2 for x in my_tuple}
print(my_tuple)
print(my_list)
print(my_set)
print(my_dict)
(1, 8, 3)
[2, 16, 6]
{16, 2, 6}
{1: 2, 8: 16, 3: 6}
# když chci tuple s prvky vynásobenými dvěma:
# nejméně efektivní způsob: pomocí +=
my_tuple = (1, 8, 3)
new_tuple = ()
for x in my_tuple:
new_tuple += (2*x,)
new_tuple
(2, 16, 6)
# když chci tuple s prvky vynásobenými dvěma:
# efektivněji: převedu na list + append
my_tuple = (1, 8, 3)
s = []
for x in my_tuple:
s.append(2*x)
new_tuple = tuple(s)
new_tuple
(2, 16, 6)
# když chci tuple s prvky vynásobenými dvěma:
# nejefektivněji a na jeden řádek: použiji generátor
my_tuple = (1, 8, 3)
new_tuple = tuple(2*x for x in my_tuple)
new_tuple
(2, 16, 6)
# generátorový výraz:
my_generator = (x*2 for x in my_tuple)
print(my_generator)
for x in my_generator:
print(x, end = " ")
# generátorový výraz přímo ve for-cyklu:
for x in (x*2 for x in my_tuple):
print(x, end = " ")
<generator object <genexpr> at 0x7fd64bc48a00> 2 16 6 2 16 6
Výraz my_generator = (x**2 for x in my_tuple) je zkratkou následujícího kódu:
# generátorová funkce:
def generate_squares(source):
for x in source:
yield x ** 2
my_generator = generate_squares(my_tuple)
my_generator
<generator object generate_squares at 0x7fd66151b850>
my_generator = (x**2 for x in my_tuple)
my_generator
<generator object <genexpr> at 0x7fd661519be0>
Výraz new_list = [expression for member in iterable] můžeme ekvivalentně zapsat jako:
new_list = list(expression for member in iterable). Obdobně pro množinu. Pro slovník bude syntaxe lehce odlišná - argumentem funkce dict může být generátor dvojic (klíč, hodnota):
my_tuple = (1,8,3)
my_list = list(x*2 for x in my_tuple)
my_set = set(x*2 for x in my_tuple)
new_tuple = tuple(x*2 for x in my_tuple) # mohu vytvořit i tuple
my_dict = dict((x, x*2) for x in my_tuple)
print(my_list)
print(my_set)
print(new_tuple)
print(my_dict)
my_list = [x*2 for x in my_tuple]
my_set = {x*2 for x in my_tuple}
my_dict = {x: x*2 for x in my_tuple}
print(my_list)
print(my_set)
print(my_dict)
[2, 16, 6]
{16, 2, 6}
(2, 16, 6)
{1: 2, 8: 16, 3: 6}
[2, 16, 6]
{16, 2, 6}
{1: 2, 8: 16, 3: 6}
my_dict = {x: x*2 for x in my_tuple}
my_dict
{1: 2, 8: 16, 3: 6}
# funkce dict chce kontejner/iterátor dvojic (klíč, hodnota)
dict([(2,2), (4,5)])
{2: 2, 4: 5}
my_dict = dict((x, x*2) for x in my_tuple)
my_dict
{1: 2, 8: 16, 3: 6}
Generové výrazy můžeme rozšířit o podmínky a můžeme pomocí nich kombinovat hodnoty z více zdrojů:
- Filtrování (obdoba funkce
filter):
python:
(expression for member in iterable if condition)
- Kombinace hodnot z více zdrojů:
python:
(expression for member1 in iterable1 (if condition1)
for member2 in iterable2 (if condition2)
...
for memberN in iterableN (if conditionN))
Příkaz s = [f(x) for x in iterable if condition] je zkratkou za:
python:
s = []
for x in iterable:
if condition:
s.add(f(x))
Příkaz s = [x+y for x in range(5) for y in range(x)] je zkratkou za:
python:
s = []
for x in range(5):
for y in range(x):
s.append(x+y)
Opět si to ukážeme na konkrétních příkladech:
# generátorová notace seznamu (list comprehension):
s = [x for x in range(1, 11)]
print(s, end ="\n\n")
t = [2 ** x for x in range(1, 11)]
print(t, end ="\n\n")
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
# generátorová notace množiny (set comprehension) s podmínkou:
m = {x for x in s if x % 2== 0}
print(m, end ="\n\n")
{2, 4, 6, 8, 10}
# generátorová notace seznamu s více zdroji:
trojice =[(i,j,k) for i in [1,2,3] for j in {True, False} for k in "AB"]
print(trojice, end ="\n\n")
[(1, False, 'A'), (1, False, 'B'), (1, True, 'A'), (1, True, 'B'), (2, False, 'A'), (2, False, 'B'), (2, True, 'A'), (2, True, 'B'), (3, False, 'A'), (3, False, 'B'), (3, True, 'A'), (3, True, 'B')]
# generátorová notace seznamu s využitím funkce zip:
trojice =[(i,j,k) for (i,j,k) in zip([1,2,3], {True, False},"AB")]
print(trojice, end ="\n\n")
[(1, False, 'A'), (2, True, 'B')]
# generátorová notace slovníku:
šachovnice ={(i,j) : "" for i in "abcdefgh" for j in range(1, 9)}
print(šachovnice)
print()
šachovnice["c",4] = "bílý pěšec"
šachovnice["a",1] = "černý král"
print(šachovnice)
{('a', 1): '', ('a', 2): '', ('a', 3): '', ('a', 4): '', ('a', 5): '', ('a', 6): '', ('a', 7): '', ('a', 8): '', ('b', 1): '', ('b', 2): '', ('b', 3): '', ('b', 4): '', ('b', 5): '', ('b', 6): '', ('b', 7): '', ('b', 8): '', ('c', 1): '', ('c', 2): '', ('c', 3): '', ('c', 4): '', ('c', 5): '', ('c', 6): '', ('c', 7): '', ('c', 8): '', ('d', 1): '', ('d', 2): '', ('d', 3): '', ('d', 4): '', ('d', 5): '', ('d', 6): '', ('d', 7): '', ('d', 8): '', ('e', 1): '', ('e', 2): '', ('e', 3): '', ('e', 4): '', ('e', 5): '', ('e', 6): '', ('e', 7): '', ('e', 8): '', ('f', 1): '', ('f', 2): '', ('f', 3): '', ('f', 4): '', ('f', 5): '', ('f', 6): '', ('f', 7): '', ('f', 8): '', ('g', 1): '', ('g', 2): '', ('g', 3): '', ('g', 4): '', ('g', 5): '', ('g', 6): '', ('g', 7): '', ('g', 8): '', ('h', 1): '', ('h', 2): '', ('h', 3): '', ('h', 4): '', ('h', 5): '', ('h', 6): '', ('h', 7): '', ('h', 8): ''}
{('a', 1): 'černý král', ('a', 2): '', ('a', 3): '', ('a', 4): '', ('a', 5): '', ('a', 6): '', ('a', 7): '', ('a', 8): '', ('b', 1): '', ('b', 2): '', ('b', 3): '', ('b', 4): '', ('b', 5): '', ('b', 6): '', ('b', 7): '', ('b', 8): '', ('c', 1): '', ('c', 2): '', ('c', 3): '', ('c', 4): 'bílý pěšec', ('c', 5): '', ('c', 6): '', ('c', 7): '', ('c', 8): '', ('d', 1): '', ('d', 2): '', ('d', 3): '', ('d', 4): '', ('d', 5): '', ('d', 6): '', ('d', 7): '', ('d', 8): '', ('e', 1): '', ('e', 2): '', ('e', 3): '', ('e', 4): '', ('e', 5): '', ('e', 6): '', ('e', 7): '', ('e', 8): '', ('f', 1): '', ('f', 2): '', ('f', 3): '', ('f', 4): '', ('f', 5): '', ('f', 6): '', ('f', 7): '', ('f', 8): '', ('g', 1): '', ('g', 2): '', ('g', 3): '', ('g', 4): '', ('g', 5): '', ('g', 6): '', ('g', 7): '', ('g', 8): '', ('h', 1): '', ('h', 2): '', ('h', 3): '', ('h', 4): '', ('h', 5): '', ('h', 6): '', ('h', 7): '', ('h', 8): ''}
Příklady¶
Předně můžete zkusit naprogramovat příklady z minulého cvičení tak, aby místo funkcí map a filter používaly generátory.
1b. Seznam dělitelů. Napište funkci, která vrátí seznam všech dělitelů zadaného přirozeného čísla seřazený od nejmenšího po největší. Úlohu řeště tentokrát pomocí generátorové notace seznamu (list comprehension). Příklad navazuje na příklad 1a výše.
def divisors_list(n):
# return [ ... for ... in ... if ... ]
# podívejte se na řešení pomocí generátorových funkcí, bude to "stejné, jen zpřeházené"
return [ i for i in range(1, n+1) if n % i == 0]
n = 24
for divisor in divisors_list(n):
print(divisor, end=' ')
assert divisors_list(504) == [1, 2, 3, 4, 6, 7, 8, 9, 12, 14, 18, 21, 24, 28, 36, 42, 56, 63, 72, 84, 126, 168, 252, 504]
1 2 3 4 6 8 12 24
1c. Generátor dělitelů podruhé. Šla by předchozí funkce jednoduše upravit tak, aby místo seznamu dělitelů vracela generátor dělitelů?
def divisors_generator(n): # liší se jen závorkami
return ( i for i in range(1, n+1) if n % i == 0)
n = 24
for divisor in divisors_generator(n):
print(divisor, end=' ')
assert list(divisors_generator(504)) == [1, 2, 3, 4, 6, 7, 8, 9, 12, 14, 18, 21, 24, 28, 36, 42, 56, 63, 72, 84, 126, 168, 252, 504]
1 2 3 4 6 8 12 24
2b. Generátor posloupnosti podruhé Napište funkci, která vrátí generátor prvků následující posloupnosti (pro dané n): 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 ... 1 2 ... n. Tentokrát úlohu řešte pomocí generátorového výrazu. Funkce bude vracet generátor. Příklad navazuje na příklad 2a výše.
def sequence(n):
# podívejte se na řešení pomocí generátorových funkcí, bude to "stejné, jen zpřeházené"
return (j for i in range(1, n+1) for j in range(1, i+1))
n = 8
nums = sequence(n)
for num in nums:
print(num, end=' ')
print(list(sequence(n)))
nums = sequence(n)
assert list(nums) == [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8]
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8]
- Prohoď klíče a hodnoty. Naprogramujte funkci, která na základě slovníku vytvoří nový slovník, kde budou prohozené klíče a hodnoty. Úlohu řešte pomocí generátorové generátorové notace slovníku.
# připomenutí:
my_tuple = (1, 8, 3)
my_dict = dict((x, x*2) for x in my_tuple)
my_dict = {x: x*2 for x in my_tuple}
my_dict
{1: 2, 8: 16, 3: 6}
original_dict = {'a': 1, 'b': 2, 'c': 3}
for key in original_dict:
print(key)
for key, value in original_dict.items():
print(key, value)
a b c a 1 b 2 c 3
def swap_keys_and_values(input_dict):
return {input_dict[key]:key for key in input_dict}
def swap_keys_and_values(input_dict):
return {value:key for key, value in input_dict.items()}
def swap_keys_and_values(input_dict):
return dict((value, key) for key, value in input_dict.items())
original_dict = {'a': 1, 'b': 2, 'c': 3}
swapped_dict = swap_keys_and_values(original_dict)
print(swapped_dict)
assert swapped_dict == {1: 'a', 2: 'b', 3: 'c'}
{1: 'a', 2: 'b', 3: 'c'}
4b. Délka slov. Naprogramujte funkci, která zjistí délku každého slova v textu. Předpokládejme, že slova jsou oddělená pomocí obyčejných mezer (možná několika za sebou). Úlohu řešte tentokrát pomocí generátorového výrazu nebo generátorové notace seznamu. Funkce bude vracet generátor nebo seznam. Hodit se mohou i metody pro stringy (např. split()).
"Toto je příklad textu s několika slovy oddělenými mezerami".split()
['Toto', 'je', 'příklad', 'textu', 's', 'několika', 'slovy', 'oddělenými', 'mezerami']
# podívejte se na řešení pomocí generátorových funkcí
def word_lengths_generator(text):
for x in text.split():
yield len(x)
def word_lengths(text):
return [ len(slovo) for slovo in text.split()]
text = "Toto je příklad textu s několika slovy oddělenými mezerami"
for length in word_lengths(text):
print(length, end=' ')
print(list(word_lengths(text)))
assert (list(word_lengths(text)) == [4, 2, 7, 5, 1, 8, 5, 10, 8])
4 2 7 5 1 8 5 10 8 [4, 2, 7, 5, 1, 8, 5, 10, 8]
4c. Jen krátká slova. Naprogramujte funkci, která z textu odstraní všechna moc dlouhá slova, tj. slova, která jsou delší než n písmen.
Předpokládejme, že slova jsou oddělená pomocí obyčejných mezer. Úlohu řešte s využitím generátorové notace. Hodit se mohou i metody pro stringy (např. join() a split()).
s = "Toto je příklad textu s několika slovy oddělenými mezerami".split()
t = "_".join(s)
print(s)
print(t)
['Toto', 'je', 'příklad', 'textu', 's', 'několika', 'slovy', 'oddělenými', 'mezerami'] Toto_je_příklad_textu_s_několika_slovy_oddělenými_mezerami
def remove_long_words(text, n):
return " ".join([ slovo for slovo in text.split() if len(slovo) <= n ])
text = "Toto je příklad textu s několika slovy oddělenými mezerami"
new_text = remove_long_words(text, 5)
print(new_text)
assert remove_long_words(text,6) == "Toto je textu s slovy"
Toto je textu s slovy
4d. Zkrať moc dlouhá slova. Naprogramujte funkci, která z textu zkrátí na n písmen všechna moc dlouhá slova, tj. slova, která jsou delší než n písmen.
Předpokládejme, že slova jsou oddělená pomocí obyčejných mezer. Úlohu řešte s využitím generátorové notace. Hodit se mohou i metody pro stringy (např. join() a split()).
def shorten_long_words(text, n):
return " ".join(slovo[:n] for slovo in text.split())
text = "Toto je příklad textu s několika slovy oddělenými mezerami"
new_text = shorten_long_words(text, 3)
print(new_text)
assert shorten_long_words(text,6) == "Toto je příkla textu s několi slovy odděle mezera"
Tot je pří tex s něk slo odd mez
- Bláznivé křížení zvířat podruhé. Máme dva seznamy
s,ts názvy zvířat. Napište funkcimerge_animals(s, t), která vytvoří nový seznam, který bude obsahovat "zkřížené" názvy zvířat tak, že z prvního názvu vezmeme vždy první polovinu a z druhého druhou polovinu. Např. 'hroch' a 'tigr' -> 'hrogr'. Úlohu řešte tentokrát pomocí generátorové notace. Hodit se může i funkcezip().
def merge_animals(s, t):
...
print(merge_animals(["hroch","potkan"],["žirafa","orangutan","lev"]))
assert merge_animals(["hroch","potkan"],["žirafa","orangutan","lev"]) == ['hrafa', 'potgutan']
- Frekvenční analýza písmen. Napište funkci
freq_analysis(text), která spočítá výskyt jednotlivých písmen (znaků) ve vstupním textu a vrátí výsledek jako slovník s prvkypísmeno: počet výskytů. Malá a velká písmena nebudeme rozlišovat. Úlohu řešte tentokrát pomocí generátorové notace slovníku. Hodit se mohou i různé metody pro stringy (např.count(),lower(),upper()neboisalpha()). Písmena a počty jejich výskytů vypište setříděné sestupně podle počtu výskytů.
def freq_analysis(text):
...
d = freq_analysis("All the world is a stage and all the men and women merely players.")
print(d)
print(sorted(d.items()))
# vypište setříděné sestupně podle počtu výskytů:
...
None
- Frekvenční analýza slov. Napište funkci
freq_analysis_words(text), která spočítá výskytů jednotlivých slov ve vstupním textu a vrátí výsledek jako slovník s prvkyslovo: počet výskytů. Malá a velká písmena nebudeme rozlišovat. Úlohu řešte tentokrát pomocí generátorové notace slovníku. Hodit se mohou i různé metody pro stringy (např.count(),lower(),upper()nebosplit()). Slova a počty výskytů vypište setříděné vzestupně podle abecedy.
def freq_analysis(text):
...
d = freq_analysis("This is a test. This is only a test, not a real situation.")
print(d)
# vypište setříděné vzestupně podle abecedy:
...
- indexy Napište funkci, která vrátí seznam všech indexů, kde se v řetězci
stringvyskytuje znakchar. Úlohu řešte tentokrát pomocí generátorové notace seznamu nebo generátorové funkce. Hodit se může i funkceenumerate().
# generátorová notace:
def find_letter_indexes(string, letter):
...
print(find_letter_indexes("hello world", "l"))
assert find_letter_indexes("hello world", "l") == [2, 3, 9]
# generátorová funkce:
def generate_letter_indexes(string, letter):
...
print(list(generate_letter_indexes("hello world", "l")))
assert list(generate_letter_indexes("hello world", "l")) == [2, 3, 9]
8b. indexy Napište funkci, která vrátí seznam všech indexů, na kterých v řetězci string začíná podstring substring. Úlohu řešte tentokrát pomocí generátorové notace seznamu nebo generátorové funkce. Hodit se může i funkce enumerate().
def find_substring_indexes(string, substring):
...
print(find_substring_indexes("ara aaraara arara", "ara"))
assert find_substring_indexes("ara aaraara arara", "ara") == [0, 5, 8, 12, 14]
# generátorová funkce:
def generate_substring_indexes(string, substring):
...
print(list(generate_letter_indexes("ara aaraara arara", "ara")))
assert list(generate_letter_indexes("ara aaraara arara", "ara")) == [0, 5, 8, 12, 14]