Entice (
>>> tup = "a", 52, 3.8, [2, 8]# entice s vnořeným seznamem
Zápis na pravé straně vyhodnotí interpret jako entici (tuple) a jako takovou ji vrátí v závorkách:
>>> tup; type(tup) ('a', 52, 3.8, [2, 8]) <class 'tuple'>
Formát entice má i výraz s jedinou položkou se závěrečnou čárkou:
>>> t1 = 'a', >>> t1; type(t1) ('a',)# závorky si doplnil interpret <class 'tuple'>
Bez čárky by byl výraz
>>> tup_t = "nazdar",; type(tup_t), len(tup_t) (<class 'tuple'>, 1) >>> tup_s = "nazdar"; type(tup_s), len(tup_s) (<class 'str'>, 6)
Entici lze rovněž vytvořit z iteráblu
>>> tup_lst = tuple([2,3,"a",2]); tup_lst (2, 3, 'a', 2) >>> tup_set = tuple({2,3,"a",2}); tup_set (2, 3, 'a') >>> tup_str = tuple("ovčín"); tup_str; ('o', 'v', 'č', 'í', 'n') >>> tup_dct = tuple({"letadlo": "Boeing", "model": "747"}); tup_dct ('letadlo', 'model')
Jako argument funkce
>>> tup_ent = tuple(('Jane', (25, 1.75), 'Brno')); tup_ent ('Jane', (25, 1.75), 'Brno') >>> tup = "a", 52, 3.8, [2, 8] >>> tup_tup = tuple(tup); tup_tup ('a', 52, 3.8, [2, 8])# V první ukázce vidíme příklad entice s vnořenou enticí
Odhlédneme-li od skladby, jsou operace s enticemi stejné jako operace se seznamy. Indexový operátor
vybere položku z entice:
>>> tup = "a", 52, 3.8, [2, 8] >>> tup[3][1] 8
Úsekový operátor vybere rozsah položek:
>>> tup[1:3]# 1 inclusive, 3 exclusive (52, 3.8)
Pokusíme-li se změnit některou z indexem vybraných položek, dostaneme chybové hlášení:
>>> tup[0] = 'A'TypeError: 'tup' object doesn't support item assignment
Neměnitelnost entice znamená, že ji nelze změnit beze změny identity (ID). Pokud nám nevadí změna ID, můžeme entici - jako přiřazenou hodnotu k proměnné, upravit pomocí součtu entic a úsekového operátoru:
>>> ruple = ('a', 'b', 'c', 'd', 'e'); id(ruple) 56396448 >>> ruple = ruple[:2] + ("X",) + ruple[2:] >>> ruple; id(ruple) ('a', 'b', 'X', 'd', 'e') 63672720
Entici lze ovšem změnit i beze změny ID, pokud měníme její měnitelný člen, například seznam:
>>> mtup = ("a", [3,"b"], True); id(mtup) 1613369562880 >>> mtup[1][0] = 7; mtup; id(mtup) ('a', [7, 'b'], True) 1613369562880# ID se nezměnilo
Co s tím? Vést tuto možnost v patrnosti a podle toho se v případě potřeby zařídit.
Entice (tuple) je 'neměnitelná' kolekce prvků. Pokud však entice obsahuje
Metoda 'copy' nemění identitu ani u změněného objektu. >>> import copy >>> lt = ("a", [2.5, "b"])
Pokud u kopie dojde ke změně, změní se i původní objekt!# vložený seznam >>> slt = copy.copy(lt)# závislá kopie >>> id(lt), id(slt); lt; slt# před změnou (3027328, 3027328) ('a', [2.5, 'b']) ('a', [2.5, 'b']) >>> slt[1][1] = "joj" >>> id(lt), id(slt) ; lt; slt# po změně (3027328, 3027328) ('a', [2.5, 'joj']) ('a', [2.5, 'joj'])Metoda 'deep copy' mění identitu kopie. >>> lt = ("a", [2.5, "b"]) >>> dlt = copy.deepcopy(lt)
Pokud u kopie dojde ke změně, původní objekt se nezmění.# nezávislá kopie id(lt), id(dlt); lt; dlt# před změnou (3027328, 3039104) ('a', [2.5, 'b']) ('a', [2.5, 'b']) >>> dlt[1][1] = "hoj" >>> id(lt), id(dlt) ; lt; dlt# po změně (3027328, 3039104) ('a', [2.5, 'b']) ('a', [2.5, 'hoj'])
Při úpravě vloženého slovníku musíme zadávat nikoliv index, nýbrž klíč:
>>> import copy >>> dt = ("a", {2: "b"})# vložený slovník >>> sdt = copy.copy(dt)# závislá kopie >>> sdt[1][2] = "číč"; dt, sdt (('a', {2: 'číč'}), ('a', {2: 'číč'})) >>> dt = ("a", {2: "b"}) >>> ddt = copy.deepcopy(dt)# nezávislá kopie >>> ddt[1][2] = "rýč"; dt, ddt >>> (('a', {2: 'b'}), ('a', {2: 'rýč'}))
Závislou kopii jak prosté, tak složené entice lze rovněž vytvořit úsekovým operátorem
>>> tup = ('a', 'b', 'c') >>> rup = tup[:]; rup ('a', 'b', 'c') >>> id(tup), id(rup) (46444232, 46444232) dt = ("a", {2: "b"}) >>> sdt = dt[:]; sdt ('a', {2: 'b'}) >>> id(dt), id(sdt) (46497384, 46497384)
Obšírnější popis kopírování viz kap. 11.4.
Pojmenovaná entice (named tuple) je neměnitelná entice, opatřená jménem a názvy položek. Prvky entice jsou tedy kromě indexů přístupné také přes jejich slovní označení.
Práce s pojmenovanou enticí připomíná práci s deklarovanou třídou a jejími instancemi. Třídou je zde "
Název_typu =namedtuple ('Název_typu', < výpis polí> [, rename=False] [, defaults=None] [, module=None])
Z takto obecně deklarované entice (třídy) vytvoříme jednotlivé entice (instance) s konkrétními hodnotami příslušných položek. Užitečnost pojmenované entice spočívá v tom, že si nemusíme pamatovat význam jednotlivých polí.
Práci s pojmenovanou enticí si nejlépe ukážeme na konkrétním příkladě, ve kterém si vytvoříme kartotéku se jmény účastníků setkání, jejich bydliště a věk:
# nt_person.py - pojmenované entice - named tuples - NT from collections import namedtuple ## Vytvoření výchozí entice s určením polí (atributů): # název_NT = namedtuple('název_NT', 'názvy .. polí') Person = namedtuple('Person', 'jméno, místo, věk')# Výpis zadaných polí entice (v Thonny): '''>>> print(Person._fields) # _fields je metoda NT ('jméno', 'místo', 'věk')'''## Vytvoření jednotlivých entic (instancí): # <jméno_pol> = <název_NT>(<hodnoty jednotlivých atributů>) eva = Person('Eva Novotná', 'Brno', věk= 18) tim = Person('Tim Brown', 'Brno', 18)'''>>> print(eva); print(tim) Person(jméno='Eva Novotná', místo='Brno', věk=18) Person(jméno='Tim Brown', místo='Brno', věk=18)''' ## Přístup k jednotlivým polím je trojí (výstupy viz Thonny): '''>>> print(eva[1]) # přes index >>> print(eva.místo) # přes klíč >>> print(getattr(eva, 'místo'))''' # přes fci getattr() ## Vytvoření dalších instancí NT s použitím funkce _make(~) a operátoru ** li = ['Jan Veselý','Zlín','22']# list i tuple jan = Person._make(li)'''>>> print(Person._make(li)) Person(jméno='Jan Veselý', místo='Zlín', věk='22')''' di = {'jméno':'Hugo Brom','místo':'Kolín','věk':'28'} hugo = Person(**di)'''>>> print(Person(**di)) # dict Person(jméno='Hugo Brom', místo='Kolín', věk='28')'''## Konverze instance z entice na slovník: '''>>> print(eva._asdict()) {'jméno': 'Eva Novotná', 'místo': 'Brno', 'věk': 18}''' ## Dodatečné operace, podporované formátem 'named tuples': # _fields - vrací klíčová slova deklarované NT: '''>>> print(hugo._fields) 'jméno', 'místo', 'věk')''' # _replace - přechodně změní hodnotu pole deklarované NT: '''>>> print(eva._replace(věk=21)) Person(jméno='Eva Novotná', místo='Brno', věk=21)''' # __new__() - vytvoří novou instanci 'třídy' Person: '''>>> sam = Person.__new__(Person,'Samuel Vorel', 'Tábor', 27); sam Person(jméno='Samuel Vorel', místo='Tábor', věk=27)''' # __getnewargs__() - vrátí NT jako prostou entici: '''>>> print(hugo.__getnewargs__()) ('Hugo Brom', 'Kolín', 28)''' # 'hugo' musí být aktivní
Vytvoření seznamu pojmenovaných entic. Předchozí skript doplníme o následující kód:
print('-'*32)# dekorace textu emp_list = [eva, tim, jan, hugo] for emp in emp_list: print( "%-15s bydliště %s" % (emp.jméno, emp.místo) ) print('-'*32)# dekorace textu
>>> %Run nt_person.py -------------------------------- Eva Novotná bydliště Brno Tim Brown bydliště Brno Jan Veselý bydliště Zlín Hugo Brom bydliště Kolín Samuel Vorel bydliště Tábor --------------------------------
Kromě prezentovaných metod
Nevýhodou pojmenované entice oproti normální entici je to, že NT je výrazně pomalejší.
Set (množina) je neuspořádaná
Kolekce
>>> basket ={ 'apple','orange','apple','pear','orange', ... 'banana'} ; basket# deklarace výčtem {'orange', 'apple', 'banana', 'pear'}# žádné duplikáty! >>> song = set("Okolo Hradce"); song# deklarace funkcí {'o', 'O', 'c', 'd', 'l', 'e', 'a', 'k', ' ', 'r', 'H'} >>> tup = (1,2,3,"alpha",2)# jiný příklad >>> set_tup = set(tup); set_tup {'alpha', 1, 2, 3} >>> fro_set_tup = frozenset(tup); fro_set_tup frozenset({'alpha', 1, 2, 3})
Použijeme-li jako argument pro funkce
>>> dic = {"a": 1, "b": 2, "c": 3} >>> set_dic = set(dic); set_dic {'c', 'a', 'b'} >>> fro_set_dic = frozenset(dic); fro_set_dic frozenset({'c', 'a', 'b'})
Set i frozenset mají definovanou částečně společnou řadu metod:
set_meth = add, clear, copy, difference, difference_update, discard, intersection, intersection_update, isdisjoint, issubset, issuperset, pop, remove, symmetric_difference, union, update, symmetric_difference_updatefrozenset_meth = copy, difference, intersection, isdisjoint, issubset, issuperset, symmetric_difference, union
Objekt typu set nepodporuje změnu položky. Složení setu lze nicméně měnit metodami
Ukážeme si některé operace na setech:
>>> a = set('abracadabra'); a {'a', 'c', 'b', 'r', 'd'} >>> b = set('alacazam'); b {'a', 'c', 'z', 'm', 'l'} >>> >>> a-b, b-a# rozdíl ({'b', 'r', 'd'}, {'z', 'l', 'm'}) >>> a | b# sjednocení {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'} >>> a & b# průnik {'a', 'c'} >>> a ^ b# doplněk {'r', 'd', 'b', 'm', 'z', 'l'}
Šikovná je redukce hromady čísel na jedinečnou řadu a posléze přeměna na posloupnost čísel:
>>> e = (1,2,3,2,1,2,3,4,5,6,5,6,4,7,8,3,2,1,3,4,5,6) >>> l = list(set(e)); l [1, 2, 3, 4, 5, 6, 7, 8]
Stejně jako pro seznam lze i pro set definovat
>>> s = {v for v in "ABCDABCD" if v not in "CB"} >>> s >>> {'A', 'D'}
Zápisy
Dosud poznané složené datové typy – řetězce, seznamy a entice – jsou sekvence, které používají celá čísla jako indexy pro přístup k jednotlivým položkám.
Slovník (dictionary, dict), je uspořádaná (Python > 3.7) a měnitelná kolekce párových položek key : value. Klíčem může být pouze neměnitelný datový typ, hodnotou libovolný datový typ.
Jako příklad vytvoříme slovník pro překlad anglických slov do španělštiny. Klíči i hodnotami u tohoto slovníku budou řetězce.
Začneme tak, že vytvoříme prázdný slovník, do kterého přidáme párové položky. Prázdný slovník se označuje {}:
>>> en2sp = {} >>> en2sp['one'] = 'uno' >>> en2sp['two'] = 'dos' >>> en2sp {'one': 'uno', 'two': 'dos'}
První přiřazení vytvoří prázdný slovník s názvem
Jiným způsobem vytvoříme slovník tak, že přímo zadáme výčet slovníkových párů:
>>> en2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'}
Případně pro vytvoření slovníku použijeme vestavěnou funkci
>>> di = dict()Funkce dict() očekává pouze 1 argument; proto je nutné výpis entic (u dt, ds, dl) uzavřít do dalšího páru závorek (typu tuple, set a list). >>> dt = dict((('foo', 100), ('bar', 200))); dt# dict(tuple) {'foo': 100, 'bar': 200} >>> ds = dict({('foo', 100), ('bar', 200)}); ds# dict(set) {'bar': 200, 'foo': 100} >>> dl = dict([('foo', 100), ('bar', 200)]); dl# dict(list) {'foo': 100, 'bar': 200} >>> dj = dict(a=10, b=20); dj# dict(what?) {'a': 10, 'b': 20}
Hodnoty ve slovníku jsou přístupné prostřednictvím klíčů:
>>> en2sp['two'] 'dos'
Klíčový operátor použijeme také pro přidání nové dvojice na konec slovníku:
>>> en2sp['four'] = "quatro"; en2sp {'one': 'uno', 'two': 'dos', 'three': 'tres', 'four': 'quatro'}
Při výskytu dvou zadaných stejných klíčů se uplatní jen ten později zadaný:
>>> en2sp['two'] = "duo"; en2sp {'one': 'uno', 'two': 'duo', 'three': 'tres', 'four': 'quatro'}
Procedura
>>> ovoce = {'apples': 430, 'bananas': 312, 'pears': 217, 'oranges': 525} >>> ovoce {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217}
Když někdo skoupí všechny hrušky, můžeme tento vstup ze slovníku vyjmout:
>>> del ovoce['pears']; ovoce {'apples': 430, 'bananas': 312, 'oranges': 525}
Nebo očekáváme-li, že hrušky zase budou, můžeme pouze změnit hodnotu spojenou s hruškami:
>>> ovoce['pears'] = 0; ovoce {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 0}
U slovníku můžeme také použít funkci
>>> len(ovoce) 4
Vestavěná funkce
>>> ovoce = {"ořech": 3, "banán": 2, "švestka": 5} >>> for plod inreversed (ovoce): print(plod, end=" ") švestka banán ořech >>> ovoce {'ořech': 3, 'banán': 2, 'švestka': 5}
Slovníky mají řadu užitečných vestavěných metod, jejichž seznam získáme známou funkcí
>>> dir(dict) ['__class__', '...', 'clear', 'copy', 'fromkeys', 'get', 'items',
'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
Metoda
>>> car = {"značka": "Ford", "model": "Mustang","rok": 1964} >>> car.update({"color": "black"}); car {'značka': 'Ford', 'model': 'Mustang', 'rok': 1964, 'color': 'black'}
Metoda
>>> car = {"značka": "Ford", "model": "Mustang","rok": 1964} >>> car.get("model") 'Mustang'
Metoda
>>> car.items() dict_items([('značka', 'Ford'), ('model', 'Mustang'), ('rok', 1964)])
Metoda
>>> car.keys() dict_keys(['značka', 'model', 'rok'])
Metoda
>>> car.values() dict_values(['Ford', 'Mustang', 1964])
Výpis
>>> for i in car: print(i, end=' ') značka model rok
Výpis
>>> for i in car.(values): print(i, end=' ') Ford Mustang 1964
K rozbalení klíčů, hodnot i položek slovníku můžeme také použít
>>> [*car] ['značka', 'model', 'rok'] >>> [*car.keys()] ['značka', 'model', 'rok'] >>> [*car.values()] ['Ford', 'Mustang', 1964] >>> [*car.items()] [('značka', 'Ford'), ('model', 'Mustang'), ('rok', 1964)]
Přítomnost klíče ve slovníku lze ověřit idiomem s klíčovým slovem
>>> "model" in car True >>> "barva" in car False
Verze Python 3.9.0 přináší dva nové operátory pro sloučení slovníků,
d |= e
Sjednocení | sloučí obsah obou operandů (zde slovníků). Nachází-li se stejný klíč v obou operandech, pro sloučení se vybere jeho hodnota z pravého operandu - viz případ
>>> d = {'spam': 1, 'vejce': 2, 'sýr': 3} >>> e = {'sýr': 'čedar', 'sele': 'Pepík'} >>> d | e {'spam': 1, 'vejce': 2, 'sýr': 'čedar', 'sele': 'Pepík'} >>> e | d {'sýr': 3, 'sele': 'Pepík', 'spam': 1, 'vejce': 2}
Rozšířené přiřazení |= provede přiřazení se sjednocením:
>>> d |= e# totéž jako d = d | e >>> d {'spam': 1, 'vejce': 2, 'sýr': 'čedar', 'sele': 'Pepík'} >>> e {'sýr': 'čedar', 'sele': 'Pepík'}
Rozšířené přiřazení lze použít ke změně přiřazené hodnoty:
>>> d |= [('spam', 999)]; d {'spam': 999, 'vejce': 2, 'sýr': 'čedar', 'sele': 'Pepík'}
Případně k vložení nového páru:
>>> d |= [('ham', 777)]; d {'spam': 999, 'vejce': 2, 'sýr': 'čedar', 'sele': 'Pepík', 'ham': 777}
Komprehence slovníku se příliš neliší od komprehence seznamu. Výstupem z komprehence slovníku je slovník, vytvořený aplikací zadaného výrazu pro každý element iteráblu. Schematická skladba je tato:
{key: valuefor (key [, value])in iterable}
Iteráblem zde může dle okolností být objekt typu
>>> dct_range= {x: x**2 for x in range(5)}; dct_range {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}Totéž pomocí mrožího operátoru: >>> print(dct_range:= {x: x**2 for x in range(5)}) {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Při komprehenci slovníku ze dvou iteráblů můžeme použít i funkci
>>> keys = ['a', 'b', 'c'] >>> vals = [1, 2, 3] >>> print(dict_compr_zip := {keys:vals \ ... for (keys,vals) inzip (keys, vals)}) {'a': 1, 'b': 2, 'c': 3} >>> dict_compr_zip# vytvořenou proměnnou lze nezávisle použít {'a': 1, 'b': 2, 'c': 3}
Slovník vytvoříme i z jednoho iteráblu(tuple, list) funkcemi
>>> a = ['hello','world','nomen','omen'] >>> dict(zip(i := iter(a), i))# zip(i,i) {'hello': 'world', 'nomen': 'omen'}
Protože jsou slovníky měnitelné, musíme si dát pozor na aliasování. Kdykoliv dvě proměnné odkazují ke stejnému objektu, jeho změna prostřednictvím jedné proměnné je sdílena i druhou proměnnou.
Chceme-li měnit slovník a přitom si zachovat kopii originálu, použijeme metodu pro slovník, zvanou
>>> oppos = {'up': 'down', 'right': 'wrong', 'true': 'false'} >>> alias = opposid(alias) == id(oppos) >>> kopie = oppos.copy()id(kopie) != id(oppos)
Proměnné
>>> alias['right'] = 'left' >>> oppos['right'] 'left'
Když naproti tomu upravíme
>>> kopie['right'] = 'seno' >>> oppos['right'] 'left'
Výběrovou proceduru switch case či dispatch lze v Pythonu vytvořit pomocí slovníku. Místo sekvence podmínek
def func_a(): print("fce-a") def func_b(): print("fce-b") def func_c(): print("fce-c") oslík = {"a": func_a, "b": func_b, "c": func_c} def print_f(value):# Včetně částečného ošetření výjimek oslík.get(value, lambda: print("Neplatné!"))()
Výběr funkce provedeme voláním funkce
>>> print_f("b") fce-b >>> print_f(5) Neplatné >>> oslík["c"]() # Kulaté závorky dotvářejí volání funkce. fce-c
Volané funkce mohou být také deklarovány jako vložené funkce lambda:
def kalkul (operátor, x, y): cases = { "+": lambda a, b: a + b, "-": lambda a, b: a - b, "*": lambda a, b: a * b, "/": lambda a, b: a / b, }# Deklarované případy: if operátorin cases.keys():return cases[operátor](x, y)# Částečné ošetření výjimek else :return cases.get(operátor, "Nenalezeno!")
>>> kalkul('/', 5, 2) 2.5 >>> kalkul(# v kontextu známá hodnota NameError: name 'kalkul' is not defined >>> calcul(^, 5, 3)# v kontextu neznámá hodnota SyntaxError: invalid syntax
Funkce lambda lze zajisté nahradit vestavěnými funkcemi pro operace
import math def add(x, y): return x + y def sub(x, y): return x - y def mul(x, y): return x * y def div(x, y): return x / y def kalk(operátor, x, y): cases = {"+": add, "-": sub, "*": mul, "/": div} return cases[operátor](x, y)# >>> kalk('+', 9, 3) --> 12
Simulaci přepínače lze také vytvořit prostřednictvím třídy.
V kapitole 6.13, cvičení 2 a 3 jsme počítali výskyt zadaného znaku v zadaném řetězci a to pomocí smyčky s počítadlem, případně přímo prostřednictvím metody 'count'.
Také jsme v kap 8.10 a 8.11 počítali výskyty náhodných čísel v jednolivých úsecích rozpětí 0.0 až 1.0 jako potvrzení skutečnosti, že funkce 'random' modulu 'random' generuje pseudonáhodná čísla.
V následujícím komentovaném programu
Před realizací programu je vhodné vyčlenit dedikovanou složku (například "F:/Codetest/HowToPY/Alice"), do níž umístíme náš program
Zkoumaný text získáme z adresy
"https://howto.py.cz/resources/alice_wonderland.txt"
Soubor
# countLetters.py# Ošetření tisknutelných (chr(i)) i netisknutelných znaků: ''' Tato funkce bude opakovaně použita v následné smyčce. Argument 'i' je UCP (Unicode Code Point) zkoumaného znaku. ''' def display (i):if i == 10:return 'LF'if i == 13:return 'CR'if i == 32:return 'SPACE'return chr(i)# Načtení textu ze souboru do paměti interpreta: inpath = 'alice_wonderland.txt'# cesta k souboru infile = open(inpath, encoding="utf-8") text = infile.read() infile.close()''' Pro anglický text (kódování ASCii) lze zadat délku seznamu counts = 127 * [0], pro český text (UTF-8) je nutné zadat counts = 383 * [0]''' # Načtení výskytů do seznamu 'counts': counts = 127 * [0]# máme angl. text for letterin text: counts[ord(letter)] += 1# ord(letter) vrací UCP # Strukturovaný zápis výskytů do souboru 'letter_counts.dat': # deklarace cesty: outpath = 'F:/Codetest/HowToPY/Alice/letter_counts.dat' outfile = open(outpath, 'w')# otevření souboru # formátované záhlaví souboru: outfile.write("%-12s%s\n" % ("Character", "Count")) outfile.write("=================\n")# formátovaný obsah pod záhlavím: for iin range(len(counts)):# len(counts) = 126+1** if counts[i]:# if counts[i] != 0 outfile.write("%-12s%d\n" % (display(i), counts[i])) outfile.close()# povinné zavření otevřeného souboru ''' ** Funkce 'range' v proceduře 'range(len(counts))' je důvodem ke zvýšení délky seznmu 'counts' o 1. ''' # Toto oznámení se vytiskne v konzole interpreta IDLE: # Frekvenční tabulka - viz soubor 'letter_counts.dat'.
Spusťte si tento program v IDE Thonny a prohlédněte si generovaný výstupní soubor 'letter_counts.dat' v textovém editoru.
Pomocí slovníku vytvoříme seznam výskytů znaků elegantním způsobem:
>>> počet_znaků = {}# <class 'dict'> >>>for znakin "Mississippi": počet_znaků[znak] = počet_znaků.get (znak, 0) + 1 >>> počet_znaků {'M': 1, 'i': 4, 's': 4, 'p': 2}
Začínáme prázdným slovníkem. Na konci procesu máme slovník obsahující dvojice písmen a jejich četností.
Bylo by ještě působivější, kdybychom výskyt písmen uspořádali podle abecedy. Můžeme to udělat pomocí
univerzální funkce
>>> sorted(počet_znaků.items()) [('M', 1), ('i', 4), ('p', 2), ('s', 4)]
Proč je
>>> ord("M"), ord("i") (77, 105)
Výskyt zadaného slova ve vstupním řetězci určíme jednoduše metodou
text = "apple mango apple orange orange apple guava\ mango mango"def word_count(text, word):str (text.count (word)))
>>> word_count(text, "mango") mango 3
Nejjednodušší způsob určení výskytu slov v textu je metodou
text = "Woodchuck, how much wood would a woodchuck \ chuck if a woodchuck could chuck wood ?" sett =set ()# prázdný kolektor typu 'set' lstt = text.split ()# konverze stringu na list for iin lstt: sett.add ((i, lstt.count (i)))# 'add' přijímá 1 arg.
S výstupem coby slovník:
>>> print(dict(sett))# konverze setu na slovník {'a': 2, 'would': 1, 'how': 1, 'much': 1, 'could': 1, 'chuck': 2, 'Woodchuck,': 1, 'wood': 2, 'woodchuck': 2, '?': 1, 'if': 1}
Případně coby seznam:
>>> print(list(sett))# konverze setu na seznam [('?', 1), ('chuck', 2), ('woodchuck', 2), ('would', 1), ('Woodchuck,', 1), ('how', 1), ('wood', 2), ('could', 1), ('much', 1), ('a', 2), ('if', 1)]
def make_empty (seq): """ >>> make_empty([1, 2, 3, 4]) [] >>> make_empty(('a', 'b', 'c')) () >>> make_empty("No, not me!") '' """def insert_at_end (val, seq): """ >>> insert_at_end(5, [1, 3, 4, 6]) [1, 3, 4, 6, 5] >>> insert_at_end('x', 'abc') 'abcx' >>> insert_at_end(5, (1, 3, 4, 6)) (1, 3, 4, 6, 5) """def insert_in_front (val, seq): """ >>> insert_in_front(5, [1, 3, 4, 6]) [5, 1, 3, 4, 6] >>> insert_in_front(5, (1, 3, 4, 6)) (5, 1, 3, 4, 6) >>> insert_in_front('x', 'abc') 'xabc' """def index_of (val, seq, start=0): """ >>> index_of(9, [1, 7, 11, 9, 10]) 3 >>> index_of(5, (1, 2, 4, 5, 6, 10, 5, 5)) 3 >>> index_of(5, (1, 2, 4, 5, 6, 10, 5, 5), 4) 6 >>> index_of('y', 'happy birthday') 4 >>> index_of('banana', ['apple', 'banana', 'cherry', 'date']) 1 >>> index_of(5, [2, 3, 4]) -1 >>> index_of('b', ['apple', 'banana', 'cherry', 'date']) -1 """def remove_at (index, seq): """ >>> remove_at(3, [1, 7, 11, 9, 10]) [1, 7, 11, 10] >>> remove_at(5, (1, 4, 6, 7, 0, 9, 3, 5)) (1, 4, 6, 7, 0, 3, 5) >>> remove_at(2, "Yomrktown") 'Yorktown' """def remove_val (val, seq): """ >>> remove_val(11, [1, 7, 11, 9, 10]) [1, 7, 9, 10] >>> remove_val(15, (1, 15, 11, 4, 9)) (1, 11, 4, 9) >>> remove_val('what', ('who', 'what', 'when', 'where', 'why', 'how')) ('who', 'when', 'where', 'why', 'how') """def remove_all (val, seq): """ >>> remove_all(11, [1, 7, 11, 9, 11, 10, 2, 11]) [1, 7, 9, 10, 2] >>> remove_all('i', 'Mississippi') 'Msssspp' """def count (val, seq): """ >>> count(5, (1, 5, 3, 7, 5, 8, 5)) 3 >>> count('s', 'Mississippi') 4 >>> count((1, 2), [1, 5, (1, 2), 7, (1, 2), 8, 5]) 2 """def reverse (seq): """ >>> reverse([1, 2, 3, 4, 5]) [5, 4, 3, 2, 1] >>> reverse(('shoe', 'my', 'buckle', 2, 1)) (1, 2, 'buckle', 'my', 'shoe') >>> reverse('Python') 'nohtyP' """def sort_sequence (seq): """ >>> sort_sequence([3, 4, 6, 7, 8, 2]) [2, 3, 4, 6, 7, 8] >>> sort_sequence((3, 4, 6, 7, 8, 2)) (2, 3, 4, 6, 7, 8) >>> sort_sequence("nothappy") 'ahnoppty' """ if __name__ == "__main__": import doctest doctest.testmod()
def letter_counts(retiazka): ...
Výstup pro "Mississippi" má tvar:
>>> letter_counts("Mississippi") {'M': 1, 'i': 4, 'p': 2, 's': 4}
Pokuste se přeformulovat předchozí úlohu tak aby výstupní frekvenční tabulka pro "Mississippi" měla formát:
M 1 i 4 s 4 p 2
Pro formulaci výstupu můžete použít postup, použitý v kap. 11.8. Nezapomeňte si prohlédnout generovaný výstupní soubor
>>> d = {"apples":15, "bananas":35, "grapes":12} >>> d["bananas"]
>>> d["oranges"] = 20
>>> len(d)
>>> "grapes" in d
>>> d["pears"]
>>> d.get("pears", 0)
>>> fruits = d.keys() >>> sorted(fruits)
>>> del d["apples"] >>> "apples" in d
def add_fruit(inventory, fruit, quantity=0): pass# tyto testy by měly vyjít new_inventory = {} add_fruit(new_inventory, 'strawberries', 10) test('strawberries' in new_inventory, True) test(new_inventory['strawberries'], 10) add_fruit(new_inventory, 'strawberries', 25) test(new_inventory['strawberries'] , 35)
Word Count ======================= a 631 a-piece 1 abide 1 able 1 about 94 above 3 absence 1 absurd 2Kolikrát se v knize objeví slovo