![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Seznam (
Položkou seznamu může být i další seznam. Takový seznam se nazyvá vnořený seznam - viz také odst. 11.1.5.
Nový seznam vytvoříme nejjednodušeji uzavřením položek do hranatých závorek:
[10, 20, 30, 40]# seznam se 4 čísly ["spam", "bungee", "swallow"]# 3 řetězce ["hello", 2.0, 5, [10, 20]]# řetězec, 2 čísla, seznam
Při práci se seznamem je důležité si uvědomit, že numerické typy (Kap. 2.2) představují jedinou hodnotu (singleton), složené datové typy (string, list, ...) mohou obsahovat žádnou, jednu, či více hodnot.
Seznamu uvnitř jiného seznamu říkáme, že je vnořený (nested). Vnořených seznamů může být v seznamu i více a to i nestejné délky, případně může seznam obsahovat prvky různých typů:
mli = [("a", 5.2), [7, True], range(5), "pešek", {2.5, 2}, b'R\xc5\xaf\xc5\xbe']
Konečně, existuje speciální seznam, který neobsahuje žádné položky. Nazývá se prázdný seznam a značí se [ ].
Stejně jako číselná hodnota 0 a prázdný řetězec, je prázdný seznam nepravdivý v booleovských výrazech:.
>>>bool (["hello", 2.0]) True >>>bool ([])# kulaté závorky ohraničují argument funkce False
Vytvořený seznam můžeme samozřejmě přiřadit k proměnné nebo zadat jako parametr či argument funkce.
>>>vocabulary = ["ameliorate", "castigate", "defenestrate"] >>>numbers = [17, 123] >>>empty = [] >>>
Funkce
>>>list ("osel")# typ str ['o', 's', 'e', 'l'] >>>list (b"osel")# typ bytes [111, 115, 101, 108] >>>list (("a", 5, True))# typ tuple ['a', 5, True] >>>list (range (4))# typ range [0, 1, 2, 3] >>>list ({"a", 5, True})# typ set [True, 5, 'a'] >>>list ({"a":2, "b":False, "c":"d"})# typ dict ['a', 'b', 'c']
Při práci se seznamem s výhodou použijeme komprehenci seznamu (potažmo iteráblu) - viz odstavec 3.5.
Syntaxe pro přístup k položkám seznamu je stejná jako syntaxe pro přístup ke znakům řetězce – pomocí hranatých závorek s indexem. Nezapomeňte, že indexy začínají nulou:
>>>nested = ["hello", 123, [10,20]]# proměnná >>> nested[1]# proces 123
Jako index lze použít jakýkoli celočíselný výraz (integer):
>>> nested[9-8]# 9-8 = 1 123 >>> nested[1.0]# lze zapsat: nested[int(1.0)] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: list indices must be integers
Pokusíme-li se číst nebo psát položku, která neexistuje, dostaneme chybu při běhu programu:
>>> nested[3]Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list index out of range
Má-li index zápornou hodnotu, počítá se od konce seznamu:
>>> nested[-1] [10, 20] >>> nested[-3] 'hello' >>> nested[-4]Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list index out of range
Pro prvek vnořeného seznamu uvedeme rovněž jeho index:
>>> nested[2][1] 20
Vestavěná funkce
>>>horsemen = ["war", "famine", "pestilence", "death"] >>> i = 0# počítadlo >>>while i < len(horsemen): # výstup ze smyčky
I když jeden seznam může obsahovat další seznam, ten vnořený se stále počítá jako jedna položka. Délka tohoto seznamu je 4:
['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]
Traverzování i vnořeným seznamem popisuje text kap. 11.1.5
K výmazu položky ze seznamu použijeme příkaz
>>>a = ['one', 'two', 'three'] >>>del a[1]; a ['one', 'three'] >>> del a[-1]; a ['one']
Jako indexy pro
>>>a_list = ['a', 'b', 'c', 'd', 'e', 'f'] >>>del a_list[1:5] >>>
Jako obvykle, úseky vyberou všechny položky zadaného rozsahu, kromě horní meze.
Operátor + zřetězí seznamy:
>>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = a + b >>>
Podobně, operátor * opakuje seznam v zadaném počtu:
>>> [0]*4 [0, 0, 0, 0] >>> [1, 2, 3]*3 [1, 2, 3, 1, 2, 3, 1, 2, 3]
První příklad opakuje [0] čtyřikrát. Druhý příklad opakuje seznam [1, 2, 3] třikrát.
Pro seznamy neexistuje modul
Metody -viz text Python List Methods: append, clear, copy, count, extend, index, insert, pop, remove, reverse, sort Funkce filter(), list(), range(), slice(), sorted() len(), max(), min()# společné pro všechny iterábly
Klíčové slovo
>>>horsemen = ['war', 'famine', 'pestilence', 'death'] >>> 'pestilence'in horsemen True >>> 'debauchery'in horsemen False
Protože
Můžeme použít slovo
>>> 'debauchery'not in horsemen True
Vyhlazením (flatten) seznamu rozumějme eliminaci vložených sekvencí převodem jejich prvků do základního seznamu.
Vyhlazení lze provést s použitím vnořených smyček, komprehence seznamu, rekurze a vestavěných či importovaných funkcí či metod.
Nejúčinější způsob je použití metody
>>> fromitertools import chain >>>mli = [(2.5, 12, 3+2j), ("a", 5.2), [7, True], range(5), "pešek", {2.5, 2}, b'R\xc5\xaf\xc5\xbee'] >>>flat_list =list (chain (*mli)) >>>
Jak vidno z ukázky, tento postup odstraní vložené seznamy, entice a sety, jakož i převede sekvenci bajtů na sekvenci kódových bodů utf-8.
Nevýhodou je, že při výskytu solitérních numerických hodnot v základním seznamu je hlášena chyba
Operace s úseky, které jsme poznali u řetězců, platí také u seznamů:
>>>a_list = ['a', 'b', 'c', 'd', 'e', 'f'] >>> a_list[1:3] ['b', 'c'] >>> a_list[:4] ['a', 'b', 'c', 'd'] >>> a_list[3:] ['d', 'e', 'f'] >>> a_list[:] ['a', 'b', 'c', 'd', 'e', 'f']
Na rozdíl od řetězců jsou seznamy měnitelné, což znamená, že můžeme měnit jejich položky. Použitím závorkového operátoru [ ] můžeme měnit hodnotu položek:
>>>fruit = ["banana", "apple", "quince"] >>> fruit[0] = "pear" >>> fruit[-1] = "orange" >>>
Přiřazení hodnoty položce seznamu se nazývá položkové přiřazení (item assignment).:
>>>my_list = ['T', 'E', 'S', 'T'] >>> my_list[2] = 'X' >>> my_list ['T', 'E', 'X', 'T']
Úsekovým operátorem můžeme změnit několik položek najednou:
>>>a_list = ['a', 'b', 'c', 'd', 'e', 'f'] >>> a_list[1:3] = ['x', 'y']# [inclusive : exclusive] >>>
Můžeme také odstranit položky ze seznamu tím, že je nahradíme prázdným seznamem:
>>>a_list = ['a', 'b', 'c', 'd', 'e', 'f'] >>> a_list[1:3] = [] >>>
A můžeme také přidat položky do seznamu v zadaném místě:
>>>a_list = ['a', 'd', 'f'] >>> a_list[1:1] = ['b', 'c'] >>>
Interní mechanizmus smyčky for - viz kap 5.3.
Použití smyčky
>>>fruit = ["banana", "apple", "quince"]# proveďte v Thonny >>>for ovoce in fruit:
Měnitelnost seznamu nám umožňuje při jeho procházení (traverzování) upravit každou jeho položku. Následující kód vytvoří druhé mocniny zadaných čísel:
>>>numbers = [3, 4, 5]# proveďte v Thonny >>>for elem in range(len(numbers)):
Funkce
>>>for index, value in enumerate(['banana', 'apple', 'pear']): ...
Jiné příklady využití funkce enumerate() - viz kap. 5.8.
Většina počítačových programů provádí při každém spuštění totéž, takže říkáme, že jsou deterministické.
Determinismus je obvykle dobrá věc, protože můžeme předpokládat, že stejný výpočet povede ke stejnému výsledku. U některých aplikacích si však přejeme, aby počítač byl nepředvídatelný. Hry jsou zřejmým příkladem, ale těch příkladů může být více.
Ukazuje se, že napsat program se skutečně nepředvídatelným chováním není snadné, ale jsou způsoby, kterak jej učinit alespoň zdánlivě nedeterministickým. Jedním ze způsobů je použití náhodných čísel. Python poskytuje vestavěnou funkci, která generuje pseudonáhodná čísla, která nejsou náhodná v přísně matematickém smyslu, ale pro naše účely postačí.
Modul
>>>import random >>>x =random. random () print(x); print(x*3) 0.4359029716422217# náhodné číslo 0 <= x < 1 1.307708914926665# náhoené číslo 0 <= x < 3
Více náhodných hodnot můžeme vygenerovat opakovaným voláním funkce
no_name.py import random def rand (high):# high určuje počet volání for i in range(high): x =random . random () # náhodná čísla 0 <= x < 1 # náhodná čísla 0 <= x < 3*high
>>> rand(3) 1.7262996561032347 0.11591785822094725 2.292141024033198
Náhodná čísla mezi nulou a zadanou mezí
Podobným problémem jako vytvoření náhodného čísla je provedení náhodného výběru. Ten lze provést pomocí funkce
>>> fromrandom import choice >>>fokus = 'Petra', 'Pavla', 'Maruš', 'Alenka', 'Věrka' >>>volba =choice (fokus); volba 'Alenka'
Každá invokace
K vytvoření výčtu náhodných čísel, musíme od první chvíle vědět, v jakém rozsahu se generovaná náhodná čísla budou pohybovat a kolik těch čísel má seznam obsahovat (zřejmě n). Jméno
Tělo funkce začíná vytvořením seznamu s
rand_list.py import random def randomList (n): s = [0] * n# počáteční seznam s nulami for i in range(n): s[i] =random .random ()# náhrada nuly za náhodné číslo return s# seznam 'n' náhodných čísel
Voláním (invokací) této funkce pro
>>> randomList(6) [0.5199466739572948, 0.452751456638563, 0.41454566096564627, 0.7953941766158702, 0.3872848065377861, 0.9080198286105817]
Předpokládá se, že náhodná čísla, generovaná systémovou funkcí
Tento předpoklad si zkusíme ověřit napsáním programu, který rozdělí hodnoty do úseků a určí počet výskytů v jednotlivých úsecích, neboli jejich četnost (
Rozdělíme-li celý interval možných náhodných hodnot do stejně velikých úseků, a spočítáme-li výskyt náhodných hodnot v jednotlivých úsecích, měl by tento výskyt být všude přibližně stejný.
Označíme-li počet úseků jménem
K výpočtu mezí jednotlivých úseků použijeme smyčku. Pro každý úsek určíme jeho spodní (low) a horní (high) hodnotu. Proměnná
def bucket_witdth(buckets): bucketWidth = 1.0 / buckets# počet úseků for i low = i * bucketWidth high = low + bucketWidthin range(buckets):
Při výpočtu dolní meze jednotlivého úseku (kyblíku) násobíme proměnnou smyčky podílem na jeden kyblík.
Horní mez je o
Pro
>>> bucket_witdth(8) 0.0 to 0.125 0.125 to 0.25 0.25 to 0.375 0.375 to 0.5 0.5 to 0.625 0.625 to 0.75 0.75 to 0.875 0.875 to 1.0
Těmto hodnotám by se ideálně měly blížit hodnoty, zastižené dalším zkoumáním v jednotlivých úsecích.
Chceme procházet vygenerovaným seznamem n náhodných čísel (
Sestavíme si funkci
Inspirujeme se upravenou sekvencí příkazů ve cvičení 6.13.2, kde jména
V dalším kroku změníme předmět prověřování. Nezajímá nás výskyt písmen v řetězci ale chceme vědět, zda se hodnota proměnné
Za tím účelem doplníme smyčku
count = 0for num in list :# list vytvoříme funkcí randomList(n) - viz 8.10.1 if low < num < high : count = count + 1
Následně zapouzdříme upravený kód do funkce zvané
def inBucket (list, low, high): count = 0for num in list :if low < num < high : count = count + 1return count
Právě odvozenou funkci možná použijeme jako pomocnou funkci v dalším výpočtu. Musíme ale dořešit, kterak operativně dosazovat meze low a high pro jednotlivé úseky.
Pro záznam výskytů náhodných čísel v jednotlivých úsecích vytvoříme seznam
list =randomList (n)# seznam náhodných čísel numBuckets# alias n_b: počet úseků výskyty = [0] * numBuckets# počáteční seznam s nulami bucketWidth = 1.0 / numBuckets# číselný rozsah jednoho intervalu for i in range (numBuckets): low = i * bucketWidth# dolní mez intervalu high = low + bucketWidth# horní mez intervalu výskyty[i] = inBucket(list, low, high)
K hladkému provedení výše uvedeného skriptu musí mít interpret Pythonu k disposici importovaný modul
Nejlépe to zajistíme tak, že založíme soubor
Z výše uvedeného skriptu vytvoříme funkci
Když v interaktivní konzole (IDLE, Thonny) provedeme volání
[138, 124, 128, 118, 130, 117, 114, 131]# SUMA = 1000
Tato čísla jsou docela blízká číslu
I když nám náš program chodí, mohl by chodit ještě lépe. Pokaždé, když volá funkci
Lepší by bylo projít seznamem jen jednou a pro každou hodnotu náhodného čísla určit rovnou index úseku (neboli index položky seznamu
Idea výhodnějšího řešení spočívá v tom, že náhodné číslo
Vytvořenou funkci
def buckets_b (n,b): výskyty = [0] * b# akumulátor list = randomList(n)# volání funkce for iin list: index = int(i * b)# zaokrouhlení dolů výskyty[index] = výskyty[index] + 1
Výstupem z funkce
[111, 132, 144, 127, 114, 123, 130, 119]# SUMA = 1000
['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]a vytiskne délku každé položky. Co se stane, zadáme-li vestavěné funkci
# zde napište zadání úlohy""" # zde překopírujte doctest úlohy """ # zde napište řešení úlohy
Podle naznačených výsledků sestavte možnou hodnotu seznamu
""" >>> a_list[3] 42 >>> a_list[6] 'Ni!' >>> len(a_list) 8 """
Podle naznačených výsledků sestavte možnou hodnotu seznamu
""" >>> b_list[1:] ['Stills', 'Nash'] >>> group = b_list + c_list >>> group[-1] 'Young' """
Podle naznačených výsledků sestavte možnou hodnotu seznamu
""" >>> 'war' in mystery_list False >>> 'peace' in mystery_list True >>> 'justice' in mystery_list True >>> 'oppression' in mystery_list False >>> 'equality' in mystery_list True """
Vytvořte funkci
""" >>> list_range(a, b, c) [5,9,13,17] """
>>> range(10, 0, -2)
Po opětovném prostudování odstavce 5.7 napište funkci
a = [1, 2, 3] b = a[:] b[0] = 5
this = ['I', 'am', 'not', 'a', 'crook'] that = ['I', 'am', 'not', 'a', 'crook'] print("Test 1: %s" % (id(this) == id(that))) that = this print("Test 2: %s" % (id(this) == id(that)))
Přidejte podrobné vysvětlení výsledků.
Určete hodnoty proměnných
""" >>> 13 in junk True >>> del junk[4] >>> junk [3, 7, 9, 10, 13, 17, 21, 24, 27] >>> del junk[a:b] >>> junk [3, 7, 27] """
Nakreslete schema seznamu
""" >>> nlist[2][1] 0 >>> nlist[0][2] 17 >>> nlist[1][1] 5 """
Podle výstupu z metody
""" >>> retiazka.split() ['this', 'and', 'that'] """
def add_lists (a, b): """ >>> add_lists([1,1], [1,1]) [2, 2] >>> add_lists([1,2], [1,4]) [2, 6] >>> add_lists([1,2,1], [1,4,3]) [2, 6, 4] """
Fce
def mult_lists (a, b): """ >>> mult_lists([1,1], [1,1]) 2 >>> mult_lists([1,2], [1,4]) 9 >>> mult_lists([1,2,1], [1,4,3]) 12 """
Ověřte si, že fce
def replace (s, old, new): """ >>> replace ('Mississippi','i', 'I') 'MIssIssIppI' >>> s = 'I love spom! Spom is my favorite food. Spom, spom, spom, yum!' >>> replace(s, 'om', 'am') 'I love spam! Spam is my favorite food. Spam, spam, spam, yum!' >>> replace(s, 'o', 'a') 'I lave spam! Spam is my favarite faad. Spam, spam, spam, yum!' """
Řešení musí zajisté vyhovovat doctestům. Použije se
>>> nums = [1, 2, 3, 4] >>> [x**3 for x in nums]
>>> nums = [1, 2, 3, 4] >>> [x**2 for x in nums if x**2 != 4]
>>> nums = [1, 2, 3, 4] >>> [(x, y) for x in nums for y in nums]
>>> nums = [1, 2, 3, 4] >>> [(x, y) for x in nums for y in nums if x != y]
def add_row (matrix): """ >>> m = [[0,0], [0,0]] >>> add_row(m) [[0, 0], [0, 0], [0, 0]] >>> n = [[3, 2, 5], [1, 4, 7]] >>> add_row(n) [[3,2,5], [1,4,7], [0,0,0]] >>> n [[3,2,5], [1,4,7]] """def add_column (matrix): """ >>> m = [[0,0], [0,0]] >>> add_column(m) [[0,0,0], [0,0,0]] >>> n = [[3,2], [5,1], [4,7]] >>> add_column(n) [[3,2,0], [5,1,0], [4,7,0]] >>> n [[3,2], [5,1], [4,7]] """
Všimněte si, že poslední doctesty v každé funkci ověřují, že
Poslední dva doctesty opět potvrzují, žedef add_matrices (m1, m2): """ >>> a = [[1,2], [3,4]] >>> b = [[2,2], [2,2]] >>> add_matrices(a, b) [[3,4], [5,6]] >>> c = [[8,2], [3,4], [5,7]] >>> d = [[3,2], [9,2], [10,12]] >>> add_matrices(c, d) [[11,4], [12,6], [15,19]] >>> c [[8,2], [3,4], [5,7]] >>> d [[3,2], [9,2], [10,12]] """
def scalar_mult (n, m): """ >>> a = [[1,2], [3,4]] >>> scalar_mult(3, a) [[3, 6], [9, 12]] >>> b = [[3,5,7], [1,1,1], [0,2,0], [2,2,3]] >>> scalar_mult(10, b) [[30, 50, 70], [10, 10, 10], [0, 20, 0], [20, 20, 30]] >>> b [[3, 5, 7], [1, 1, 1], [0, 2, 0], [2, 2, 3]] """
def matrix_mult (m1, m2): """ matrix_mult([[1,2], [3,4]], [[5,6], [7,8]]) [[19, 22], [43, 50]] >>> matrix_mult([[1,2,3], [4,5,6]], [[7,8], [9,1], [2,3]]) [[31, 19], [85, 55]] >>> matrix_mult([[7,8], [9,1], [2,3]], [[1,2,3], [4,5,6]]) [[39, 54, 69], [13, 23, 33], [14, 19, 24]] """
Pro lepší porozumění booleovským výrazům jsou dobré pravdivostní tabulky. Dva booleovské výrazy jsou logicky rovnocenné tehdy a jen tehdy, mají-li stejné pravdivostní tabulky.
Následující skript vytiskne pravdivostní tabulku pro libovolný booleovský výraz s proměnnou
expression = input("Zadej booleovský výraz \ pro 'p' a 'q' : " ) print(" p q %s" % expression) delka = len(" p q %s" % expression) print(delka* "=") for p in True, False: for q in True, False: print("%-7s %-7s %-7s" % (p, q, eval(expression)))Tento skript použijeme pro osvojení booleovských výrazů. Uložte program do souboru
p q p or q ------------------------ True True True True False True False True True False False False
Funkci zavoláme z konzoly IDLE:def truth_table (expression): print(" p q %s" % expression) delka = len(" p q %s" % expression) print(delka* "=") for p in True, False: for q in True, False: print("%-7s %-7s %-7s" % (p, q, eval(expression)))
>>> truth_table ("p or q") p q p or q ------------------------ True True True True False True False True True False False FalseVyzkoušejte si fci
Které výrazy jsou logicky eqvivalentní?
Napište fci
Uložte ji do souboru
>>> is_divisible(20,4) Toto číslo je dělitelné číslem 4 >>> is_divisible(21,8) Toto číslo neni dělitelné číslem 8
Při řešení použijete podmínky
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |