![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Seznam (list) je uspořádaná řada hodnot s připojeným indexem. Jednotlivým hodnotám říkáme položky seznamu. Seznamy jsou podobné řetězcům, jež jsou uspořádané řady znaků; položky seznamu mohou být však libovolného typu. Seznamy, řetězce a jiné entity, které se chovají jako uspořádané řady, nazýváme sekvence.
Nový seznam vytvoříme nejjednodušeji uzavřením položek do hranatých závorek [ ].
[10, 20, 30, 40] ["spam", "bungee", "swallow"]
Prvním příkladem je seznam čtyř celých čísel. Druhým je seznam tří řetězců. Položky seznamu nemusí být stejného typu. Následující seznam obsahuje řetězec, float (číslo v plovoucí řádové čárce), integer (celé číslo) a (mirabile dictu) další seznam:
["hello", 2.0, 5, [10, 20]]
Seznamu uvnitř jiného seznamu říkáme, že je vnořený.
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:.
>>> if []: ... print "This is true." ... else : ... print "This is false." ... This is false. >>>
Při všech těchto možnostech tvorby seznamů by bylo zklamáním, kdybychom nemohli přiřadit seznam hodnot k proměnné, nebo zadat seznam jako parametr funkce. Věc se má tak, že můžeme.
>>>vocabulary = ["ameliorate", "castigate", "defenestrate"]
>>>numbers = [17, 123]
>>>empty = []
>>>print vocabulary, numbers, empty
['ameliorate', 'castigate', 'defenestrate'] [17, 123] []
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 [ ] (nezaměňovat s prázdným seznamem). Výraz v závorkách určuje index položky. Nezapomeňme, že indexy začínají nulou:
>>> print numbers[0]
17
Jako index lze použít jakýkoli celočíselný výraz:
>>> numbers[9-8] 5 >>> numbers[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:
>>> numbers[2] 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:
>>> numbers[-1] 5 >>> numbers[-2] 17 >>> numbers[-3] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list index out of range
numbers[-1] je poslední položka seznamu, numbers[-2] je předposlední a numbers[-3] neexistuje.
Je obvyklé použít proměnnou smyčky jako index seznamu:
horsemen = ["war", "famine", "pestilence", "death"] i = 0 while i < 4: print horsemen[i] i = i + 1
Tato smyčka počítá od 0 do 4. Jakmile má proměnná smyčky hodnotu 4, podmínka nevyhoví a smyčka končí. Takže tělo smyčky je provedeno pro i = 0, 1, 2 a 3.
Při každém cyklu smyčky je proměnná i použita jako index položky, která se tiskne. Tento způsob výpočtu se nazývá traverzování seznamem.
Funkce len vrací délku seznamu, což je počet jeho položek. Tato hodnota se výhodně používá jako horní mez smyčky místo konstanty. Tím si zajistíme, že pokaždé, když se změní velikost seznamu, nemusíme procházet programem, abychom opravili všechny dotčené smyčky:
horsemen = ["war", "famine", "pestilence", "death"] i = 0 while i < len(horsemen): print horsemen[i] i = i + 1
Po posledním provedením těla smyčky je i=len(horsemen)-1, což je index poslední položky. Je-li i=len(horsemen), podmínka není splněna a tělo se neprovede, což je dobré, protože len(horsemen) není přípustný index.
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]]
Klíčové slovo in je booleovský operátor, který testuje příslušnost prvku k sekvenci. Použili jsme jej už u řetězců a pracuje také se seznamy a jinými uspořádanými množinami:
>>> horsemen = ['war', 'famine', 'pestilence', 'death'] >>> 'pestilence' in horsemen True >>> 'debauchery' in horsemen False
Protože pestilence je částicí seznamu horsemen, vrátí operátor in hodnotu True. Jelikož debauchery v seznamu není, vrátí False.
Můžeme použít slovo not ve spojení s in, abychom ověřili, že položka není částicí seznamu:
>>> 'debauchery' not in horsemen
True
Operátor + zřetězí seznamy:
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = a + b
>>> print c
[1, 2, 3, 4, 5, 6]
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.
Operace s úseky, které jsme poznali u řetězců, platí také u seznamů:
>>> list = ['a', 'b', 'c', 'd', 'e', 'f'] >>> list[1:3] ['b', 'c'] >>> list[:4] ['a', 'b', 'c', 'd'] >>> list[3:] ['d', 'e', 'f'] >>> list[:] ['a', 'b', 'c', 'd', 'e', 'f']
Seznamy, které obsahují po sobě jdoucí celá čísla jsou tak běžné, že Python poskytuje jednoduchý způsob jejich tvorby:
>>> range(1, 5) [1, 2, 3, 4]
Funkce range přijímá dva argumenty a vrací seznam, který obsahuje všechna mezilehlá celá čísla; včetně prvního, vyjma druhého (argumentu).
Jsou dvě další formy fce range. S jediným argumentem vytvoří seznam, který začíná nulou:
>>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Případný třetí argument určí rozdíl mezi sousedními hodotami a nazývá se krok. Následující příklad počítá od 1 do 10 s krokem 2:
>>> range(1,10, 2) [1, 3, 5, 7, 9]
Je-li hodnota kroku záporná, potom počátek musí být větší než konec,
>>> range(10,4, -5) [20, 15, 10, 5]
jinak bude výsledkem prázdný seznam.
>>> range(10,20, -5) []
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 na levé straně můžeme obměnit jednu z položek:
>>> fruit = ["banana", "apple", "quince"]
>>> fruit[0] = "pear"
>>> fruit[-1] = "orange"
>>> print fruit
['pear', 'apple', 'orange']
Závorkový operátor můžeme u seznamu použít kdekoliv ve výrazu. Objeví-li se na levé straně přiřazení, mění jednu z položek seznamu. Přiřazení hodnoty položce se nazývá položkové přiřazení (item assignment). Takovéto přiřazení nejde použít u řetězců:
>>> my_string = 'TEST' >>> my_string[2] = 'X' Traceback (most recent call last): File "<stdin >", line 1, in <module > TypeError: 'str' object does not support item assignment (objekt 'str' nepodporuje položkové přiřazení)
ale podporuje je pro seznamy:
>>> 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'] >>> print a_list ['a', 'x', 'y', 'd', 'e', 'f']
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] = [] >>> print a_list ['a', 'd', 'e', 'f']
A můžeme také přidat položky do seznamu vmáčknutím do prázdného úseku v potřebném místě:
>>> a_list = ['a', 'd', 'f'] >>> a_list[1:1] = ['b', 'c'] >>> print a_list ['a', 'b', 'c', 'd', 'f'] >>> a_list[4:4] = ['e'] >>> print a_list ['a', 'b', 'c', 'd', 'e', 'f']
Použití úseků k výmazu položek je neohrabané a proto náchylné k chybám. Python poskytuje šikovnější alternativu.
Příkaz del odstraní položku ze seznamu:
>>> a = ['one', 'two', 'three']
>>> del a[1]
>>> a
['one', 'three']
Nepřekvapí nás, že del manipuluje také se zápornými indexy a vyvolá chybu při běhu programu, je-li index mimo dovolený rozsah.
Jako indexy pro del můžeme použít také úseky:
>>> list = ['a', 'b', 'c', 'd', 'e', 'f'] >>> del list[1:5] >>> print list ['a', 'f']
Jako obvykle, úseky vyberou všechny položky zadaného rozsahu, kromě druhého indexu.
Provedeme-li tyto příkazy přiřazení,
a = "banana" b = "banana"
víme, že a a b poukazují na řetězec s písmeny "banana". Není však zřejmé, zda se jedná o tentýž řetězec.
Jsou dvě možné situace:

V prvním případě odkazují a a b ke dvoum různým věcem, které mají stejnou hodnotu. Ve druhém případě odkazují k téže věci. Těmto "věcem" říkáme objekty. Objekt je něco, na co může proměnná odkazovat.
Každý objekt má jedinečný identifikátor, k němuž máme přístup prostřednictvím funkce id. Jeho vytištěním můžeme zjistit, zda se obě proměnné a i b odkazují ke stejnému objektu:
>>> id(a) 135044008 >>> id(b) 135044008
Dostali jsme dvakrát stejný identifikátor, což znamená, že Python vytvořil pouze jeden řetězec a jak a, tak b se k němu odkazují.
Je zajímavé, že seznamy se chovají odlišně. Vytvoříme-li dva seznamy, dostaneme dva objekty:
>>> a = [1, 2, 3] >>> b = [1, 2, 3] >>> id(a) == id(b) False
Zobrazení vztahů vypadá tedy takto:

Proměnné a a b mají stejnou hodnotu ale nevztahují se ke stejnému objektu.
Proměnné odkazují k objektům; přiřadíme-li jednu proměnnou ke druhé, potom obě proměnné odkazují ke stejnému objektu:
>>> a = [1, 2, 3] >>> b = a >>> id(a) == id(b) True
V tomto případě vypadá schema vztahů takto:

Protože tentýž seznam má dvě různá jména (a, b), říkáme, že je aliasován. Změny provedené s jedním aliasem se projeví i u druhého:
>>> b[0] = 5
>>> print a
[5, 2, 3]
I když toto chování může být užitečné, je někdy nečekané, ba přímo nežádoucí. Obecně vzato, pracujeme-li s měnitelnými objekty, je bezpečnější se aliasování vyhnout. S neměnitelnými objekty ovšem žádný problém není. Proto Python aliasuje řetězce docela běžně.
Chceme-li provést úpravy v seznamu a zároveň si uchovat kopii originálu, potřebujeme zkopírovat samotný seznam, nikoliv jen jeho odkaz. Tomuto procesu někdy říkáme klonování, abychom se vyhnuli dvojznačnosti slova "kopírování".
Nejjednodušší způsob klonování je užití úsekového operátoru:
>>> a = [1, 2, 3]
>>> b = a[:]
>>> print b
[1, 2, 3]
Vytvoření úseku vytváří nový seznam. V tomto případě je úsekem celý seznam.
Nyní můžeme měnit b bez obav o a.
>>> b[0] = 5
>>> print a
[1, 2, 3]
Smyčku for lze použít i u seznamů. Zobecněná skladba je tato:
for VARIABLE in LIST:
BODY
Tento příkaz je rovnocenný zápisu:
i = 0 while i < len(LIST): VARIABLE = LIST[i] BODY i += 1
Smyčka for je stručnější, protože se obejdeme bez její proměnné i. Zde je dříve vytvořená smyčka s použitím for:
for horseman in horsemen: print horseman
Čte se to téměř jako prostá čeština: "Pro každého žokeje v (seznamu) žokejů vytiskni (jméno) žokeje."
Použití smyčky for je velmi rozmanité:
for number in range(20): if number%3 == 0: print number for fruit in ["banana", "apple", "quince"]: print "I like to eat" + fruit +"s!"
První příklad vytiskne všechny násobky 3 mezi 0 a 19. Druhý příklad vyjádří nadšení pro různé druhy ovoce.
Měnitelnost seznamu nám umožňuje upravit při traverzování každou jeho položku. Následující kód vytvoří druhé mocniny čísel od 1 do 5:
numbers = [1, 2, 3, 4, 5] for index in range(len(numbers)): numbers[index] = numbers[index]**2
Zamyslete se nad příkazem range(len(numbers)) a snažte se pochopit, jak tento příkaz pracuje. Uvnitř seznamu nás zajímá jak hodnota položky, tak i její index.
Tento postup je natolik běžný, že Python nabízí k použití i jiný způsob:
numbers = [1, 2, 3, 4, 5] for index, value in enumerate(numbers): numbers[index] = value**2
enumerate generuje při traverzování seznamem jak index, tak i odpovídající hodnotu. Pro lepší pochopení práce příkazu enumerate si vyzkoušej následující příklad:
>>> for index, value in enumerate(['banana', 'apple', 'pear', 'quince', ]): ... print index, value ... 0 banana 1 apple 2 pear 3 quince >>>
Při zadávání seznamu jako argument se ve skutečnosti předává odkaz, nikoliv kopie seznamu. Protože jsou seznamy měnitelné, mohou být jeho položky použitou funkcí změněny. Například, následující funkce přijme seznam jako argument a vynásobí dvěma každou jeho položku:
def double_stuff(a_list): for index, value in enumerate(a_list): a_list[index] = 2 * value
Vložíme-li double_stuff do souboru se jménem ch09.py, můžeme si postup vyzkoušet:
>>> from ch09 import double_stuff >>> things = [2,5,'spam',9.5] >>> double_stuff(things) >>> things [4, 10, 'spamspam', 19.0] >>>
Parametr a_list a proměnná things jsou aliasy pro tentýž objekt.
Funkce, které přijmou seznam jako argument a změní jej při provádění, se nazývají modifikátory a změnám které provedou na zadaném argumentu, se říká vedlejší účinky. Funkci s uvedenými vlastnostmi jsme si zapsali v předchozím odstavci.
Čistá funkce neprodukuje vedlejší účinky. Komunikuje s okolním programem pouze prostřednictvím parametrů které nepřetváří a prostřednictvím výstupní hodnoty. Zde je double_stuff jako čistá funkce:
def double_stuff ( a_list ): new_list = [] for value in a_list: new_list += [2*value] return new_list
Tato verze double_stuff nemění své argumenty:
>>> from ch09 import double_stuff >>> things = [2,5,'spam',9.5] >>> double_stuff(things) [4, 10, 'spamspam', 19.0] >>> things [2, 5, 'spam', 9.5] >>>
Chceme-li aby čistá funkce double_stuff změnila seznam things, přiřadíme mu výstupní hodnotu fce:
>>> thigs = double_stuff(things) >>> things [4, 10, 'spamspam', 19.0] >>>
Všechno, co může být provedeno pomocí modifikátorů, může být také provedeno čistými funkcemi. Některé programovací jazyky znají vlastně jenom čisté funkce. Má se zato, že čisté funkce se snadněji tvoří a jsou méně náchylné k chybám než programy, které používají modifikátory. Nicméně, modifikátory jsou někdy vhodné a v některých případech jsou programy s čistými funkcemi méně výkonné.
Doporučujeme tedy používat čisté funkce kdykoli je to účelné, a k modifikátorům se uchylovat jen při zjevné výhodnosti. Tento přístup lze označit jako funkcionální programovací styl.
Vnořený seznam je seznam, kteý se vyskytuje jako položka jiného seznamu. V naší ukázce je položka s indexem 3 vnořeným seznamem:
>>> nested = ["hello", 2.0, 5, [10,20]]
Zadáme-li nested[3], dostaneme [10,20]. Abychom vyjmuli položku z vnořeného seznamu, můžeme postupovat ve dvou krocích:
>>> elem = nested[3] >>> elem[0] 10
Nebo tyto kroky můžeme zkombinovat:
>>> nested[3][1] 20
Operátory s hranatými závorkami jsou vyhodnocovány zleva doprava, takže tento výraz dává nejprve tři-tou položku seznamu nested a z ní vyjme položku s indexem 1.
Vnořené seznamy se často používají k vyjádření matic. Například, matice:

může být vyjádřena takto:
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix je seznam se třemi položkami, kde každá položka je řadou matice. Můžeme vybrat celou řadu matice obvyklým způsobem:
>>> matrix[1] [4, 5, 6]
Nebo můžeme vyjmout jedinou položku z matice s použitím dvojitého indexu:
>>> matrix[1][1] 5
První index vybere řadu, druhý index vybere sloupec. I když tento způsob prezentace matic je obvyklý, není jediný. Malou obměnou je použití seznamu sloupců místo seznamu řad. Později poznáme radikálnější alternativu s použitím slovníku.
Testem podnícený rozvoj (Test-driven development - TDD) je způsob vyvíjení programu, při kterém se postupuje po malých, automaticky ověřovaných krocích.
Tento přístup si předvedeme na doctestech, které jsme poznali již v odstavci 5.8. Řekněmež, že chceme funkci, která vytvoří matici m krát n (rows krát columns).
Nejprve pro tuto funkci sestavime test v souboru matrices.py:
def make_matrix (rows, columns): """ >>> make_matrix(3,5) [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]] """ if __name__ == '__main__': import doctest doctest:testmod()
Provedení skriptu skončí neúspěchem:
**********************************************************************
File "matrices.py", line 3, in __main__.make_matrix
Failed example:
make_matrix(3, 5)
Expected:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
Got nothing
**********************************************************************
1 items had failures:
1 of 1 in __main__.make_matrix
***Test Failed*** 1 failures.
Test nebyl úspěšný proto, že tělo funkce obsahuje pouze dokumentační řetězec a žádný příkaz return, takže je vráceno Got nothing. Náš test nám naznačuje, že jsme chtěli vrátit matici se samými nulami ve třech řadách a pěti sloupcích.
Při použití TDD zpravidla napíšeme to nejjednodušší, co projde testem, v našem případě to je příkaz return:
def make_matrix (rows, columns): """ >>> make_matrix(3,5) [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]] """ return [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]]
Při provedení tohoto skriptu v testu obstojíme, ale fce make_matrix vrací stále týž výsledek, což zajisté není to, co jsme zamýšleli. Motivujme naše vylepšení přidáním testu:
def make_matrix (rows, columns): """ >>> make_matrix(3,5) [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]] >>> make_matrix(4,2) [[0,0], [0,0], [0,0], [0,0]] """ return [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]]
což zcela nepochybně opět neprojde:
**********************************************************************
File "matrices.py", line 5, in __main__.make_matrix
Failed example:
make_matrix(4, 2)
Expected:
[[0, 0], [0, 0], [0, 0], [0, 0]]
Got:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
**********************************************************************
1 items had failures:
1 of 2 in __main__.make_matrix
***Test Failed*** 1 failures.
Tato technika se nazývá testem podnícená, protože se snažíme upravovat kód tak, abychom prošli testem. Motivováni nezdařeným pokusem, můžeme nyní zkusit obecnější řešení:
def make_matrix (rows, columns): """ >>> make_matrix(3,5) [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]] >>> make_matrix(4,2) [[0,0], [0,0], [0,0], [0,0]] """ return [[0]* columns]* rows
Zdá se, že toto řešení chodí a můžeme si myslet, že jsme hotovi, ale později objevíme chybu:
>>> from matrices import * >>> m = make_matrix(4, 3) >>> m [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] >>>m[1][2] = 7 >>>m [[0, 0, 7], [0, 0, 7], [0, 0, 7], [0, 0, 7]] >>>
Chtěli jsme přiřadit hodnotu 7 položce ve druhé řadě a třetím sloupci a místo tohtoho mají všechny položky ve třetím sloupci hodnotu 7!
Po chvilce přemýšlení si uvědomíme, že v našem řešení je rows označení pro každou řadu (viz alias). To zcele určitě není to, co jsme chtěli a proto se pustíme do nápravy problému nejprve tím, že napíšeme test, o kterém předem víme, že neprojde:
def make_matrix (rows, columns): """ >>> make_matrix(3,5) [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]] >>> make_matrix(4,2) [[0,0], [0,0], [0,0], [0,0]] >>> m = make_matrix(4, 2) >>> m[1][1] = 7 >>> m [[0,0], [0,7], [0,0], [0,0]] """ return [[0]* columns]* rows
Maje co napravovat, jsme hnáni k lepšímu řešení:
def make_matrix (rows, columns): """ >>> make_matrix(3,5) [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]] >>> make_matrix(4,2) [[0,0], [0,0], [0,0], [0,0]] >>> m = make_matrix(4, 2) >>> m[1][1] = 7 >>> m [[0,0], [0,7], [0,0], [0,0]] """ matrix = [] for row in range(rows)): matrix += [[0]* columns] return matrix
Užití TDD poskytuje našemu programátorskému snažení několik výhod:
Python má příkaz se jménem list který vezme uspořádanou řadu jako argument a vytvoří z jejích prvků seznam:
>>> list ("Crunchy Frog")
['C', 'r', 'u', 'n', 'c', 'h', 'y', ' ', 'F', 'r', 'o', 'g']
Existuje také příkaz str, který z libovolné hodnoty argumentu vytvoří řetězec:
>>> str (5)
'5'
>>> str (None)
'None'
>>> str (list("nope"))
"['n', 'o', 'p', 'e']"
Dostali jsme řetězec s dvaceti znaky, včetně tří mezer. Jak vidíme u tohoto příkladu, str nelze použít ke spojení seznamu znaků. Za tím účelem můžeme použít funkci join z modulu string:
>>> import string
>>> char_list = list("Frog")
>>> char_list
['F', 'r', 'o', 'g']
>>> string.join(char_list, '')
'Frog'
Další důležitá funcke v modulu string se týká seznamu řetězců. Funkce split rozloží řetězec na seznam slov. Libovolný počet znaků pro mezeru je implicitně považován za hranici slov:
>>> import string >>> song = "The rain in Spain..." >>> string.split(song) ['The', 'rain', 'in', 'Spain... '] >>>
Libovolný argument, nazvaný oddělovač (delimiter), může být použit k určení znaků, které mají sloužit jako hranice slov. Následující příklad používá jako oddělovač řetězec ai:
>>> string.split(song, 'ai') ['The r', 'n in Sp','n... '] >>>
Všimněte si, že se oddělovač v seznamu neobjevuje.
Fce string.join je inverzní funkcí k fci string.split. Přijímá dva argumenty: seznam řetězců a separátor, který bude umístěn mezi položky seznamu ve výsledném řetězci.
>>> import string >>> words = ['crunchy', 'raw', 'unboned', 'real', 'dead', 'frog', ] >>> string.join(words, '') 'crunchy raw unboned real dead frog' >>> string.join(words, '**') 'crunchy**raw**unboned**real**dead**frog'
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]a vytiskne délku každé položky. Co se stane, zadáme-li funkci len jako argument celé číslo?
# Zde zadej svoje doctesty: """ """ # Zde napis svoje programy: if __name__ == '__main__': import doctest doctest.testmod()
Přidávej následující doctesty do dokumentačního řetězce v předchozím skriptu a napiš k nim vyhovující kódy.
""" >>> a_list[3] 42 >>> a_list[6] 'Ni!' >>> len(a_list) 8 """
""" >>> b_list[1:] ['Stills', 'Nash'] >>> group = b_list + c_list >>> group[-1] 'Young' """
""" >>> '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 """
""" >>> range(a, b, c) [5,9,13,17] """
Přidávej vždy jen jednu sadu doctestů a nepřidávej další, dokud předchozí sada neprošla zkouškami.
>>> range(10, 0, -2)
Tři argumenty pro funkci range jsou start, stop a step. V našem příkladě je start větší než stop. Co se stane, když start<stop a step<0? Napiš pravidlo pro vztahy mezi start, stop a step.
a = [1, 2, 3] b = a[:] b[0] = 5Nakresli schematické zobrazení vztahu mezi a a b před provedením třetího řádku a po jeho provedení.
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řidej podrobné vysvětlení výsledků.
""" >>> 13 in junk True >>> del junk[4] >>> junk [3, 7, 9, 10, 17, 21, 24, 27] >>> del junk[a:b] junk [3, 7, 27] """
""" >>> nlist[2][1] 0 >>> nlist[0][2] 17 >>> nlist[1][1] 5 """
""" >>> import string >>> string.split(message, '??') ['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 add_lists musí být ve shodě s uvedenými doctesty.
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ěř si, že fce mult_lists vyhovuje uvedeným doctestům.
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]] """
Nové funkce musí projít zkouškou doctestů. Všimni si, že poslední doctesty v každé funkci ověřují, že add_row a add_column jsou funkce čisté.
def 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]] """Přidej své funkce do matrices.py a ujisti se, že projdou zkouškou uvedených doctestů. Poslední dva doctesty opět potvrzují, že add_matrices je čistá funkce.
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]] """Přidej svoji novou funkci do matrices.py a ujisti se, že projde doctesty.
def row_times_column (m1, row, m2, column): """ >>> row_times_column[[1,2], [3,4], 0, [5,6], [7,8], 0] 19 >>> row_times_column[[1,2], [3,4], 0, [5,6], [7,8], 1] 22 >>> row_times_column[[1,2], [3,4], 1, [5,6], [7,8], 0] 43 >>> row_times_column[[1,2], [3,4], 1, [5,6], [7,8], 1] 50 """ 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]] """Přidej nové funkce do matrices.py a zajisti shodu s doctesty.
import string
song = "The rain in Spain..."
Popiš vztah mezi string.join(string.split(song)) a song. Jsou stejné pro všechny řetězce? Kdy se budou lišit?
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í zajité vyhovovat doctestům. Použije se string.split a string.join.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |