Nacházíte se zde: Domů Ponořme se do Pythonu 3

Úroveň obtížnosti: ♦♦♢♢♢

Přirozené datové typy

Wonder is the foundation of all philosophy, inquiry its progress, ignorance its end.
(Zvědavost je základem celé filozofie, hledání odpovědí na otázky ji žene vpřed, ignorance ji zabíjí.)
— Michel de Montaigne

 

Ponořme se

Datové typy. Přestaňme si na chvíli všímat našeho prvního pythonovského programu a pojďme si popovídat o datových typech. Každá hodnota v Pythonu je určitého datového typu, ale u proměnných nemusíme datový typ deklarovat. Jak to tedy funguje? Při každém přiřazení hodnoty do proměnné si Python zjistí, jakého typu hodnota je, a vnitřně si to eviduje.

Python používá mnoho přirozených datových typů (ve smyslu „přirozených pro Python“). Uveďme zde ty hlavní:

  1. Boolean (booleovský typ) nabývá buď hodnoty True nebo False.
  2. Čísla mohou být celá (integer; 1 a 2), reálná (float; 1.1 a 1.2), zlomky (fraction; 1/2 and 2/3), nebo dokonce čísla komplexní.
  3. Řetězce jsou posloupnosti Unicode znaků. Tuto podobu může mít například HTML dokument.
  4. Bajty a pole bajtů, například soubor s obrázkem ve formátu JPEG.
  5. Seznamy jsou uspořádané posloupnosti hodnot.
  6. N-tice jsou uspořádané, neměnné posloupnosti hodnot.
  7. Množiny jsou neuspořádané kolekce hodnot.
  8. Slovníky jsou neuspořádané kolekce dvojic klíč-hodnota.

Těch typů je samozřejmě víc. V Pythonu je vše objektem, proto musí existovat také typy jako modul, funkce, třída, metoda, soubor, a dokonce přeložený kód. S některými z nich už jsme se setkali: moduly mají jména, funkce mají docstring atd. O třídách se dozvíte v kapitole Třídy a iterátory, o souborech v kapitole Soubory.

Řetězce a bajty jsou důležité do té míry — a jsou také dost komplikované —, že jim je věnována samostatná kapitola. Nejdříve se podívejme na ty zbývající.

Booleovský typ

Objekt booleovského typu nabývá buď hodnoty true (pravda) nebo false (nepravda). Pro přímé přiřazení booleovských hodnot definuje Python dvě konstanty, příhodně pojmenované True a False. Booleovská hodnota může vzniknout také vyhodnocením výrazu. Na některých místech (jako u příkazu if) Python dokonce předpokládá, že se výraz vyhodnotí do podoby booleovské hodnoty. Těmto místům se říká booleovský kontext. V booleovském kontextu můžeme použít téměř libovolný výraz. Python se pokusí získat jeho pravdivostní hodnotu. Pravidla, podle kterých se v booleovském kontextu výsledek chápe jako pravdivý nebo nepravdivý (true nebo false), jsou pro různé datové typy různá. (Jakmile uvidíte dále v této kapitole konkrétní příklady, bude vám to dávat větší smysl.)

Vezměme si například následující úryvek z humansize.py:

if size < 0:
    raise ValueError('number must be non-negative')

Proměnná size obsahuje celé číslo, 0 je celé číslo a < je číselný operátor. Výsledek výrazu size < 0 má vždy booleovskou hodnotu. V pythonovském shellu si vyzkoušejte následující:

>>> size = 1
>>> size < 0
False
>>> size = 0
>>> size < 0
False
>>> size = -1
>>> size < 0
True

V důsledku problematického dědictví z Pythonu 2 se s booleovskými hodnotami může zacházet jako s čísly. True je 1; False je 0.

>>> True + True
2
>>> True - False
1
>>> True * False
0
>>> True / False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: int division or modulo by zero

Ajajaj! Takové věci nedělejte. Zapomeňte, že jsem se o tom vůbec zmínil.

Čísla

Čísla jsou obdivuhodná. Můžete si je vybrat z tak ohromného množství. Python podporuje jak celá čísla (integer), tak čísla reálná (floating point). Nerozlišují se deklarací datového typu. Python je od sebe poznává podle přítomnosti nebo nepřítomnosti desetinné tečky.

>>> type(1)                 
<class 'int'>
>>> isinstance(1, int)      
True
>>> 1 + 1                   
2
>>> 1 + 1.0                 
2.0
>>> type(2.0)
<class 'float'>
  1. Pro ověření typu libovolné hodnoty nebo proměnné můžeme použít funkci type(). Jak se dalo čekat, hodnota 1 je typu int.
  2. Podobně můžeme voláním funkce isinstance() ověřit, zda hodnota či proměnná odpovídá zadanému typu.
  3. Přidáním int k int vzniká výsledek typu int.
  4. Přidáním int k float vzniká výsledek typu float. Aby mohl Python provést sčítání, vynutí si převod typu int na float. Poté vrátí výsledek typu float.

Vynucení převodu celých čísel na reálná a naopak

Jak jste zrovna viděli, některé operátory (například sčítání) mohou podle potřeby vynutit převod celého čísla na číslo reálné. Ale k převodu je můžete donutit taky vy sami.

>>> float(2)                
2.0
>>> int(2.0)                
2
>>> int(2.5)                
2
>>> int(-2.5)               
-2
>>> 1.12345678901234567890  
1.1234567890123457
>>> type(1000000000000000)  
<class 'int'>
  1. Voláním funkce float() můžeme explicitně vynutit převod int (typ pro celé číslo) na float (typ pro reálné číslo).
  2. A nebude asi moc překvapivé, že voláním int() můžeme vynutit převod float na int.
  3. Funkce int() nezaokrouhluje, ale odsekává.
  4. Funkce int() odsekává desetinnou část u záporných čísel směrem k nule. Jde o funkci opravdového odsekávání, ne o funkci floor (tj. u záporných čísel dojde ke zvětšení čísla, protože například –2.5 se změní na –2).
  5. Čísla typu float jsou uložena s přesností na 15 desetinných míst.
  6. Celá čísla mohou být libovolně velká.

Python 2 měl oddělené typy int a long. Datový typ int byl omezen konstantou sys.maxint, která byla platformově závislá, ale obvykle nabývala hodnoty 232-1. Python 3 má pouze jeden celočíselný typ, který se chová většinou jako původní typ long z Pythonu 2. Detaily naleznete v PEP 237.

Běžné operace s čísly

S čísly můžete dělat všechno možné.

>>> 11 / 2      
5.5
>>> 11 // 2     
5
>>> −11 // 2    
−6
>>> 11.0 // 2   
5.0
>>> 11 ** 2     
121
>>> 11 % 2      
1
  1. Operátor / provádí dělení. Vrací výsledek typu float dokonce i v případě, že činitel i jmenovatel jsou typu int.
  2. Operátor // provádí svým způsobem podivné celočíselné dělení. Pokud je výsledek kladný, můžete o něm uvažovat, že vznikl odseknutím desetinných míst (tedy nikoliv zaokrouhlením). Ale pozor na to.
  3. Při celočíselném dělení záporných čísel provede operátor // zaokrouhlení „nahoru“ k nejbližšímu celému číslu. Z matematického hlediska zaokrouhluje „dolů“, protože −6 je menší než −5. Ale pokud byste očekávali, že dojde k odseknutí na −5, tak byste se nachytali.
  4. Operátor // nevrací celé číslo vždy. Pokud je čitatel nebo jmenovatel typu float, bude výsledek sice opět zaokrouhlen na celé číslo, ale výsledná hodnota bude typu float.
  5. Operátor ** znamená „umocněno na“. 112 je 121.
  6. Operátor % vrací zbytek po celočíselném dělení. 11 děleno 2 je 5 a zbytek je 1. Takže výsledkem bude 1.

V Pythonu 2 obvykle operátor / prováděl celočíselné dělení. Ale když jste ve svém kódu použili speciální direktivu, mohli jste jeho význam přepnout na reálné dělení. V Pythonu 3 operátor / vyjadřuje vždy dělení s reálným výsledkem (floating point division). Na detaily se podívejte do PEP 238.

Zlomky

Python vás neomezuje jen na celá a reálná čísla. Zvládne celou tu fantastickou matiku, kterou jste se učili na střední škole a rychle jste ji zapomněli.

>>> import fractions              
>>> x = fractions.Fraction(1, 3)  
>>> x
Fraction(1, 3)
>>> x * 2                         
Fraction(2, 3)
>>> fractions.Fraction(6, 4)      
Fraction(3, 2)
>>> fractions.Fraction(0, 0)      
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "fractions.py", line 96, in __new__
    raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
ZeroDivisionError: Fraction(0, 0)
  1. Používání zlomků zahájíme importem modulu fractions.
  2. Zlomek definujeme tak, že vytvoříme objekt třídy Fraction a předáme mu čitatele a jmenovatele.
  3. Se zlomky můžeme provádět obvyklé matematické operace. Ty vracejí nový objekt třídy Fraction. 2 * (1/3) = (2/3)
  4. Objekt třídy Fraction zlomky automaticky krátí. (6/4) = (3/2)
  5. Python má dost rozumu na to, aby nevytvořil zlomek s nulovým jmenovatelem.

Trigonometrie

Python zvládne i základy trigonometrie.

>>> import math
>>> math.pi                
3.1415926535897931
>>> math.sin(math.pi / 2)  
1.0
>>> math.tan(math.pi / 4)  
0.99999999999999989
  1. Modul math definuje konstantu π, čili poměr mezi obvodem kružnice a jejím průměrem.
  2. Modul math zvládá všechny základní trigonometrické funkce včetně sin(), cos(), tan() a varianty jako asin().
  3. Ale pozor na to, že Python neoplývá nekonečnou přesností. Funkce tan(π / 4) by měla vrátit 1.0 a ne 0.99999999999999989.

Čísla v booleovském kontextu

Čísla můžete použít v booleovském kontextu — například v příkazu if. Nulové hodnoty se interpretují jako false, nenulové jako true.

>>> def is_it_true(anything):             
...   if anything:
...     print("yes, it's true")
...   else:
...     print("no, it's false")
...
>>> is_it_true(1)                         
yes, it's true
>>> is_it_true(-1)
yes, it's true
>>> is_it_true(0)
no, it's false
>>> is_it_true(0.1)                       
yes, it's true
>>> is_it_true(0.0)
no, it's false
>>> import fractions
>>> is_it_true(fractions.Fraction(1, 2))  
yes, it's true
>>> is_it_true(fractions.Fraction(0, 1))
no, it's false
  1. A to víte, že své vlastní funkce můžete definovat i v pythonovském interaktivním shellu? Stačí zmáčknout ENTER na konci každého řádku a vše ukončit stiskem ENTER na prázdném řádku.
  2. V booleovském kontextu se nenulová celá čísla chápou jako true a nula jako false.
  3. Nenulová reálná čísla se chápou jako true, 0.0 se chápe jako false. Ale bacha na tu poslední hodnotu! Pokud dojde k sebemenší zaokrouhlovací chybě (což není nemožné, jak jste si mohli všimnout v předchozí podkapitole), pak bude Python testovat místo nuly například 0.0000000000001 a vrátí hodnotu True.
  4. Zlomky můžeme také použít v booleovském kontextu. Hodnota Fraction(0, n) se pro všechny hodnoty n vyhodnotí jako false. Všechny ostatní zlomky se vyhodnotí jako true.

Seznamy

Seznamy jsou v Pythonu nejpoužívanějšími datovými typy. Když řeknu „seznam“ (anglicky list [list]), může vás napadnout „pole, jehož velikost musím předem deklarovat, které může obsahovat jen prvky stejného typu atd.“. Tímto směrem neuvažujte. Seznamy jsou mnohem lepší.

Pythonovský seznam se podobá poli (array) v Perl 5. Proměnné polí v jazyce Perl 5 vždycky začínají znakem @. Pythonovské proměnné můžou být pojmenovány zcela libovolně. Python si vnitřně eviduje jejich datový typ.

Pythonovský seznam má větší možnosti než pole (array) v jazyce Java. (Ačkoliv pokud je to vše, co od života očekáváte, můžete jej tímto způsobem používat.) Podobnější je mu třída ArrayList, která umožňuje uchovávání libovolných objektů a při přidání nových položek se může dynamicky zvětšit.

Vytvoření seznamu

Seznam můžeme vytvořit snadno. Čárkami oddělené hodnoty uzavřeme do hranatých závorek.

>>> a_list = ['a', 'b', 'mpilgrim', 'z', 'example']  
>>> a_list
['a', 'b', 'mpilgrim', 'z', 'example']
>>> a_list[0]                                        
'a'
>>> a_list[4]                                        
'example'
>>> a_list[-1]                                       
'example'
>>> a_list[-3]                                       
'mpilgrim'
  1. Nejdříve jsme nadefinovali seznam s pěti položkami. Všimněte si, že zachovávají své původní pořadí. Není to náhoda. Seznam je uspořádaná kolekce položek.
  2. Seznam můžeme používat jako pole s indexováním od nuly. První prvek každého neprázdného seznamu zpřístupníme vždy zápisem a_list[0].
  3. Poslední prvek tohoto pětiprvkového seznamu je a_list[4], protože indexování začíná nulou.
  4. Záporným indexem zpřístupňujeme položky ve směru od konce seznamu k začátku. Poslední prvek každého neprázdného seznamu zpřístupníme vždy zápisem a_list[-1].
  5. Pokud se vám zdá použití záporného indexu matoucí, uvažujte o něm takto: a_list[-n] == a_list[len(a_list) - n]. Takže pro náš seznam pak platí a_list[-3] == a_list[5 - 3] == a_list[2].

Vytváření podseznamů

Jakmile máme vytvořen seznam, můžeme získat jakoukoliv jeho část. Anglicky se tomu říká „slicing the list“, což můžeme přeložit jako „vykrajování ze seznamu“ nebo „výřez ze seznamu“ nebo — z pohledu abstraktního záměru — vytváření podseznamu.

>>> a_list
['a', 'b', 'mpilgrim', 'z', 'example']
>>> a_list[1:3]            
['b', 'mpilgrim']
>>> a_list[1:-1]           
['b', 'mpilgrim', 'z']
>>> a_list[0:3]            
['a', 'b', 'mpilgrim']
>>> a_list[:3]             
['a', 'b', 'mpilgrim']
>>> a_list[3:]             
['z', 'example']
>>> a_list[:]              
['a', 'b', 'mpilgrim', 'z', 'example']
  1. Část seznamu, výřez (slice), můžeme získat zadáním dvou indexů. Návratovou hodnotou je nový seznam, který obsahuje položky od prvního indexu výřezu (v tomto případě a_list[1]) až po položku (ale vyjma) s druhým indexem výřezu (v našem případě a_list[3]).
  2. Výřez funguje i v případě, kdy je hodnota jednoho nebo obou indexů výřezu záporná. Můžete si pomoci následujícím způsobem uvažování. Když se na seznam díváme zleva doprava, pak první index výřezu určuje první položku, kterou chceme, a druhý index výřezu určuje první položku, kterou nechceme. Vrací se vše mezi tím.
  3. Seznamy se indexují od nuly, takže zápis a_list[0:3] vrací první tři položky seznamu počínaje položkou a_list[0] až po a_list[3] vyjma (ta už se nevrací).
  4. Pokud je levý index výřezu roven nule, můžeme nulu vynechat a Python si ji tam dosadí. Takže zápis a_list[:3] vede ke stejnému výsledku jako a_list[0:3], protože počáteční nula se dosadí jako implicitní hodnota.
  5. Podobně, pokud by pravý index výřezu měl mít hodnotu rovnou délce seznamu, můžeme jej vynechat. Protože náš seznam má pět položek, vede zápis a_list[3:] ke stejnému výsledku jako a_list[3:5]. A najdeme zde potěšitelnou symetrii. V našem pětiprvkovém seznamu vrací zápis a_list[:3] první tři položky a a_list[3:] vrací zbývající dvě. Obecně platí, že a_list[:n] vždy vrátí prvních n položek a a_list[n:] vrátí zbytek — nezávisle na délce seznamu.
  6. Pokud vynecháme oba indexy výřezu, jsou ve výsledku zahrnuty všechny položky původního seznamu. Ale není to totéž jako původní proměnná a_list. Jde o nový seznam, který má shodou okolností stejné položky. Zápis a_list[:] je tedy zkratkou pro získání úplné kopie seznamu.

Přidávání položek do seznamu

Položku můžeme do seznamu přidat čtyřmi způsoby.

>>> a_list = ['a']
>>> a_list = a_list + [2.0, 3]    
>>> a_list                        
['a', 2.0, 3]
>>> a_list.append(True)           
>>> a_list
['a', 2.0, 3, True]
>>> a_list.extend(['four', 'Ω'])  
>>> a_list
['a', 2.0, 3, True, 'four', 'Ω']
>>> a_list.insert(0, 'Ω')         
>>> a_list
['Ω', 'a', 2.0, 3, True, 'four', 'Ω']
  1. Operátor + spojí seznamy a vytvoří nový seznam. Seznam může obsahovat libovolný počet položek. Neexistuje zde žádný limit (pouze velikost dostupné paměti). Ale co se týká paměti, měli bychom si dát pozor na to, že spojením seznamů vzniká v paměti další seznam. V našem případě je nový seznam ihned přiřazen do existující proměnné a_list. Takže tento řádek kódu ve skutečnosti představuje dvoufázový proces — spojení (konkatenace) a přiřazení —, který může u rozsáhlých seznamů (dočasně) spotřebovat velké množství paměti.
  2. Seznam může obsahovat položky libovolného datového typu a v jednom seznamu nemusí být všechny položky stejného typu. V našem případě máme seznam obsahující řetězec, reálné číslo a celé číslo.
  3. Metoda append() přidává jednu položku na konec seznamu. (Teď už máme v seznamu položky se čtyřmi rozdílnými datovými typy!)
  4. Seznamy jsou implementovány formou třídy. „Vytvoření“ seznamu tedy znamená vytvoření instance třídy. V tomto smyslu mají seznamy metody, které nad nimi pracují. Metoda extend() přebírá jeden argument, kterým je seznam. Každý jeho prvek připojí na konec původního seznamu (append).
  5. Metoda insert() vloží do seznamu jednu položku. Prvním argumentem je index první položky seznamu, která bude z této pozice odsunuta. Položky seznamu nemusí být jedinečné. Například v našem případě teď seznam obsahuje dvě samostatné položky s hodnotou 'Ω': první položku (a_list[0]) a poslední položku (a_list[6]).

Volání metody a_list.insert(0, value) se podobá použití funkce unshift() v jazyce Perl. Vloží prvek na začátek seznamu a index všech ostatních položek se zvýší, aby vzniklo potřebné místo.

Podívejme se podrobněji na rozdíly mezi append() a extend().

>>> a_list = ['a', 'b', 'c']
>>> a_list.extend(['d', 'e', 'f'])  
>>> a_list
['a', 'b', 'c', 'd', 'e', 'f']
>>> len(a_list)                     
6
>>> a_list[-1]
'f'
>>> a_list.append(['g', 'h', 'i'])  
>>> a_list
['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']]
>>> len(a_list)                     
7
>>> a_list[-1]
['g', 'h', 'i']
  1. Metoda extend() přebírá jeden argument, kterým je vždy seznam, a přidá každý jeho prvek do seznamu a_list.
  2. Pokud začnete se seznamem o třech položkách a rozšíříte jej voláním extend() o seznam s dalšími třemi položkami, dostanete seznam s šesti položkami.
  3. Ve srovnání s tím metoda append() přebírá jeden argument, který může být libovolného datového typu. Na tomto řádku předáváme metodě append() seznam s třemi položkami.
  4. Pokud jsme začali se seznamem o šesti položkách a předaný seznam připojíme na konec, dostaneme seznam se sedmi položkami. Proč se sedmi? Protože poslední položkou (kterou jsme právě připojili) je celý seznam. Seznam může obsahovat data libovolného typu, včetně seznamu. Může to být právě to, co jste chtěli. Nebo možná nechtěli. Každopádně jste si o to řekli, a proto jste to dostali.

Vyhledávání hodnoty v seznamu

>>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
>>> a_list.count('new')       
2
>>> 'new' in a_list           
True
>>> 'c' in a_list
False
>>> a_list.index('mpilgrim')  
3
>>> a_list.index('new')       
2
>>> a_list.index('c')         
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
ValueError: list.index(x): x not in list
  1. Metoda count() vrací počet výskytů určité hodnoty v seznamu (což se dalo čekat).
  2. Pokud se chcete dozvědět jen to, jestli nějaká hodnota v seznamu je nebo ne, pak je použití operátoru in o něco rychlejší než volání metody count(). Operátor in vždy vrací True nebo False. Neřekne vám, kolikrát se daná hodnota v seznamu vyskytuje.
  3. Ani operátor in ani metoda count() vám ale neřeknou, kde se v seznamu hodnota vyskytuje. Pokud chcete zjistit, kde se hodnota v seznamu nachází, použijte metodu index(). Pokud neřeknete jinak, bude prohledávat celý seznam. Ale nepovinným druhým argumentem můžete zadat index (od nuly), na kterém má hledání začít. A můžeme dokonce zadat nepovinný třetí argument s indexem místa, kde má hledání skončit.
  4. Metoda index() najde první výskyt zadané hodnoty v seznamu. V tomto případě se hodnota 'new' vyskytuje v seznamu dvakrát: a_list[2] a a_list[4]. Ale metoda index() vrátí jen index prvního výskytu.
  5. Co byste ale možná nečekali, je to, že v případě nenalezení hodnoty v seznamu vyvolá metoda index() výjimku.

Počkat! Co? Je to tak. Pokud metoda index() nenajde v seznamu zadanou hodnotu, vyvolá výjimku. Jde o zjevně odlišné chování ve srovnání s jinými jazyky, které vracejí nějakou neplatnou hodnotu indexu (jako například -1). Ze začátku se vám to může zdát protivné, ale myslím, že to časem oceníte. Znamená to, že program zhavaruje v místě vzniku problému místo toho, aby potichu a divně selhal o chvíli později. Vzpomeňte si, že hodnota -1 je platným indexem prvku v seznamu. Kdyby metoda index() místo výjimky vracela hodnotu -1, mohlo by to vést k poměrně nezábavným zážitkům při ladění.

Odstraňování položek ze seznamu

Seznamy se mohou automaticky nafukovat a smršťovat. Jejich expanzi už jsme si ukázali. Odstraňování položek ze seznamu můžeme také provést několika způsoby.

>>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
>>> a_list[1]
'b'
>>> del a_list[1]         
>>> a_list
['a', 'new', 'mpilgrim', 'new']
>>> a_list[1]             
'new'
  1. Pro odstranění určené položky ze seznamu můžeme použít příkaz del.
  2. Pokud se pokoušíme o přístup k položce s indexem 1 poté, co jsme položku s indexem 1 odstranili, nedojde k chybě. Poziční index všech položek, které následují za rušenou položkou, bude posunut tak, aby byla vzniklá mezera zaplněna.

Že neznáte ten správný poziční index? Žádný problém. Odstranění položek můžete předepsat také jejich hodnotou.

>>> a_list.remove('new')  
>>> a_list
['a', 'mpilgrim', 'new']
>>> a_list.remove('new')  
>>> a_list
['a', 'mpilgrim']
>>> a_list.remove('new')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
  1. K odstranění položky ze seznamu můžete použít metodu remove(). Metoda remove() přebírá zadanou hodnotu a odstraní ze seznamu její první výskyt. A opět. Všechny položky, které následují za rušenou položkou, budou posunuty tak, aby byla vzniklá mezera zaplněna. V seznamech nikdy nevznikají díry.
  2. Metodu remove() můžete volat, kdykoliv se vám to hodí. Ale pokud se pokusíte o odstranění položky s hodnotou, která se v seznamu nevyskytuje, bude vyvolána výjimka.

Odstraňování položek ze seznamu: Bonusové kolo

Další zajímavou metodou seznamu je pop(). Metoda pop() představuje další způsob odstraňování položek ze seznamu, ale s malou fintou.

>>> a_list = ['a', 'b', 'new', 'mpilgrim']
>>> a_list.pop()   
'mpilgrim'
>>> a_list
['a', 'b', 'new']
>>> a_list.pop(1)  
'b'
>>> a_list
['a', 'new']
>>> a_list.pop()
'new'
>>> a_list.pop()
'a'
>>> a_list.pop()   
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop from empty list
  1. Pokud voláme metodu pop() bez argumentů, odstraní poslední položku seznamu a vrátí hodnotu, která byla odstraněna.
  2. Metodou pop() můžeme ze seznamu odstranit libovolnou položku. Jednoduše jí předáme poziční index. Odstraní požadovanou položku, posune následující položky tak, aby zaplnila mezeru, a vrátí odstraněnou hodnotu.
  3. Pokud voláme pop() pro prázdný seznam, vznikne výjimka.

Volání metody seznamu pop() bez argumentu se podobá volání funkce pop() v jazyce Perl. Odstraní poslední položku seznamu a vrátí hodnotu, která byla odstraněna. V jazyce Perl existuje také funkce shift(), která odstraní první položku a vrátí její hodnotu. Jde o ekvivalent pythonovského volání a_list.pop(0).

Seznamy v booleovském kontextu

Seznam můžeme použít také v booleovském kontextu, jako například v příkazu if.

>>> def is_it_true(anything):
...   if anything:
...     print("yes, it's true")
...   else:
...     print("no, it's false")
...
>>> is_it_true([])             
no, it's false
>>> is_it_true(['a'])          
yes, it's true
>>> is_it_true([False])        
yes, it's true
  1. Prázdný seznam se v booleovském kontextu vyhodnocuje jako false.
  2. Libovolný seznam, který obsahuje aspoň jednu položku, se vyhodnocuje jako true.
  3. Libovolný neprázdný seznam se vyhodnocuje jako true. Hodnota položek je nepodstatná.

N-tice

N-tice (anglicky tuple) se chová jako neměnitelný seznam. Jakmile je n-tice jednou vytvořena, nedá se nijak změnit.

>>> a_tuple = ("a", "b", "mpilgrim", "z", "example")  
>>> a_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
>>> a_tuple[0]                                        
'a'
>>> a_tuple[-1]                                       
'example'
>>> a_tuple[1:3]                                      
('b', 'mpilgrim')
  1. N-tice se definuje stejným způsobem jako seznam. Jediný rozdíl spočívá v tom, že posloupnost prvků neuzavřeme do hranatých závorek, ale do kulatých.
  2. Prvky n-tice mají definované pořadí, stejně jako u seznamu. N-tice se indexují od nuly (jako seznam), takže první element neprázdné n-tice se zapisuje vždy a_tuple[0].
  3. Záporné indexy se vyhodnocují od konce n-tice, stejně jako u seznamu.
  4. Dají se z nich získávat výřezy (slice), stejně jako u seznamů. Když získáte výřez se seznamu, má podobu nového seznamu. Když předepíšete výřez z n-tice, dostanete novou n-tici.

Hlavní rozdíl mezi n-ticemi a seznamy je ten, že n-tice nemohou být změněny. Z technického pohledu říkáme, že n-tice jsou neměnitelné (anglicky immutable). Prakticky se to projevuje tak, že neposkytují žádnou metodu, která by nám je dovolila změnit. Seznamy mají metody jako append(), extend(), insert(), remove() a pop(). N-tice žádnou z těchto metod nemají. Z n-tice můžeme vytvořit výřez (protože se vytváří nová n-tice), můžeme zjišťovat, zda n-tice obsahuje určitou hodnotu (protože tím ke změně n-tice nedochází) a… to je všechno.

# pokračování předchozího příkladu
>>> a_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
>>> a_tuple.append("new")               
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'append'
>>> a_tuple.remove("z")                 
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'remove'
>>> a_tuple.index("example")            
4
>>> "z" in a_tuple                      
True
  1. Do n-tice nemůžeme přidávat další prvky. N-tice nemají ani metodu append() ani extend().
  2. Z n-tice nemůžeme prvky odstranit. N-tice nemají žádnou z metod remove() nebo pop().
  3. V n-tici můžeme prvky vyhledávat, protože tím nedochází k její změně.
  4. Můžeme také použít operátor in pro testování, zda n-tice obsahuje zadaný prvek.

Takže na co jsou n-tice dobré?

N-tice mohou být převedeny na seznamy a naopak. Zabudovaná funkce tuple() může převzít seznam a vrací n-tici se stejnými prvky. A naopak funkce list() může převzít zadanou n-tici a vrací seznam. Z pohledu účinku tedy funkce tuple() seznam zmrazí a funkce naopak list() rozpustí n-tici.

N-tice v booleovském kontextu

N-tice můžeme použít v booleovském kontextu, jako například v příkazu if.

>>> def is_it_true(anything):
...   if anything:
...     print("yes, it's true")
...   else:
...     print("no, it's false")
...
>>> is_it_true(())             
no, it's false
>>> is_it_true(('a', 'b'))     
yes, it's true
>>> is_it_true((False,))       
yes, it's true
>>> type((False))              
<class 'bool'>
>>> type((False,))
<class 'tuple'>
  1. Prázdná n-tice se v booleovském kontextu vyhodnocuje jako false.
  2. Libovolná n-tice s alespoň jednou položkou se vyhodnocuje jako true.
  3. Libovolná n-tice s alespoň jednou položkou se vyhodnocuje jako true. Hodnota položek je nepodstatná. Ale co tady dělá ta čárka?
  4. Pokud chceme vytvořit n-tici s jedinou položkou, pak musíme za hodnotu připsat čárku. Pokud bychom čárku nepřidali, Python by si myslel, že jsme jednoduše přidali nadbytečnou dvojici závorek. Je to sice neškodné, ale n-tice se tím nevytvoří.

Přiřazení více hodnot najednou

Následuje parádní programátorská zkratka. V Pythonu můžete n-tici použít pro přiřazení více hodnot najednou.

>>> v = ('a', 2, True)
>>> (x, y, z) = v       
>>> x
'a'
>>> y
2
>>> z
True
  1. v je n-tice o třech prvcích a (x, y, z) je n-tice s třemi proměnnými. Přiřazení jedné do druhé vede k přiřazení každé z hodnot n-tice v do jednotlivých proměnných v uvedeném pořadí.

Využít se toho dá všemožnými způsoby. Dejme tomu, že chcete pojmenovat řadu hodnot. K rychlému přiřazení po sobě jdoucích hodnot můžete využít zabudovanou funkci range() a vícenásobné přiřazení.

>>> (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)  
>>> MONDAY                                                                       
0
>>> TUESDAY
1
>>> SUNDAY
6
  1. Zabudovaná funkce range() vytváří posloupnost celých čísel. (Z technického hlediska nevrací funkce range() seznam ani n-tici, ale iterátor. Odlišnosti se naučíme později.) MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, a SUNDAY jsou proměnné, které definujeme. (Tento příklad pochází z modulu calendar, což je malý zábavný modul, který tiskne kalendář podobně jako UNIXový program cal. Modul calendar definuje pro dny v týdnu celočíselné konstanty.)
  2. V tomto okamžiku má každá z proměnných svou hodnotu: Proměnná MONDAY je rovna 0, TUESDAY má hodnotu 1 a tak dále.

Současného přiřazení více proměnným můžeme využít také pro vytváření funkcí, které vracejí více hodnot najednou. Jednoduše v nich vrátíme n-tici se všemi požadovanými hodnotami. Ve volajícím kódu se k výsledku můžeme chovat jako k jedné n-tici, nebo jej můžeme přiřadit do více jednotlivých proměnných. Tento obrat používá řada standardních pythonovských knihoven, včetně modulu os. O něm si něco řekneme v následující kapitole.

Množiny

Množina (set) je neuspořádanou kolekcí jedinečných hodnot. Jedna množina může obsahovat hodnoty libovolného neměnitelného (immutable) datového typu. Pokud máme k dispozici dvě množiny, můžeme s nimi provádět standardní množinové operace, jako je sjednocení, průnik a rozdíl množin.

Vytvoření množiny

Ale nejdříve proberme základy. Množinu vytvoříme snadno.

>>> a_set = {1}     
>>> a_set
{1}
>>> type(a_set)     
<class 'set'>
>>> a_set = {1, 2}  
>>> a_set
{1, 2}
  1. Pokud chceme vytvořit množinu s jednou hodnotou, uzavřeme hodnotu do složených závorek ({}).
  2. Množiny jsou ve skutečnosti implementovány jako třídy, ale tím se teď nebudeme zatěžovat.
  3. Pokud chceme vytvořit množinu s více hodnotami, oddělíme hodnoty čárkami a vše uzavřeme do složených závorek.

Množinu můžeme vytvořit i ze seznamu.

>>> a_list = ['a', 'b', 'mpilgrim', True, False, 42]
>>> a_set = set(a_list)                           
>>> a_set                                         
{'a', False, 'b', True, 'mpilgrim', 42}
>>> a_list                                        
['a', 'b', 'mpilgrim', True, False, 42]
  1. K vytvoření množiny ze seznamu použijeme funkce set(). (Puntičkáři, kteří vědí, jak jsou množiny implementovány, by zde podotkli, že ve skutečnosti nejde o volání funkce, ale o vytváření instance třídy. Já vám slibuji, že se o tomto rozdílu dozvíte v této knize později. Prozatím nám bude stačit vědět, že set() se chová jako funkce a že vrací množinu.)
  2. Jak už jsem se zmínil dříve, jedna množina může obsahovat hodnoty libovolného datového typu. A zmínil jsem se také, že množiny jsou neuspořádané. Tato množina si nepamatuje původní pořadí prvků v seznamu, který byl použit k jejímu vytvoření. Pokud byste do množiny přidávali další prvky, nebude si množina pamatovat pořadí, v jakém jste je vkládali.
  3. Původní seznam zůstává nezměněn.

Že zatím nemáte k dispozici žádné hodnoty? Žádný problém. Můžeme vytvořit prázdnou množinu.

>>> a_set = set()    
>>> a_set            
set()
>>> type(a_set)      
<class 'set'>
>>> len(a_set)       
0
>>> not_sure = {}    
>>> type(not_sure)
<class 'dict'>
  1. K vytvoření prázdné množiny zavoláme set() bez argumentů.
  2. Zobrazená reprezentace prázdné množiny vypadá trochu divně. Očekávali jste spíš něco jako {}? Tímto způsobem se vyjadřuje prázdný slovník a ne množina. O slovnících se dozvíme později, ale ještě v této kapitole.
  3. Navzdory podivnosti zobrazené reprezentace to skutečně je množina...
  4. ...a tato množina neobsahuje žádné prvky.
  5. Prázdnou množinu nelze vytvořit zápisem dvou složených závorek kvůli historickým způsobům přeneseným z Pythonu 2. Tímto způsobem se vyjadřuje prázdný slovník a ne množina.

Úprava množiny

Do existující množiny můžeme přidávat hodnoty dvěma různými způsoby: metodou add() a metodou update().\

>>> a_set = {1, 2}
>>> a_set.add(4)  
>>> a_set
{1, 2, 4}
>>> len(a_set)    
3
>>> a_set.add(1)  
>>> a_set
{1, 2, 4}
>>> len(a_set)    
3
  1. Metoda add() přebírá jeden argument, který může být libovolného datového typu, a přidává zadanou hodnotu do množiny.
  2. Množina teď má tři členy.
  3. Množiny jsou kolekcemi jedinečných hodnot. Pokud do množiny zkusíme přidat hodnotu, která se v ní již nachází, neudělá to nic. Nevznikne chyba. Jde zkrátka o prázdnou operaci.
  4. Množina má pořád jen tři členy.
>>> a_set = {1, 2, 3}
>>> a_set
{1, 2, 3}
>>> a_set.update({2, 4, 6})                       
>>> a_set                                         
{1, 2, 3, 4, 6}
>>> a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13})  
>>> a_set
{1, 2, 3, 4, 5, 6, 8, 9, 13}
>>> a_set.update([10, 20, 30])                    
>>> a_set
{1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
  1. Metoda update() přebírá jeden argument, rovněž množinu, a přidá všechny její členy do původní množiny. Je to, jako kdybychom volali metodu add() pro všechny členy množiny předané argumentem.
  2. Protože cílová množina nemůže obsahovat jednu hodnotu dvakrát, duplicitní hodnoty se ignorují.
  3. Ve skutečnosti můžete metodu update() volat s libovolným počtem argumentů. Pokud ji zavoláte s dvěma množinami, metoda update() přidá všechny členy z každé z předaných množin do původní množiny (duplicitní hodnoty se přeskočí).
  4. Metoda update() umí zpracovat objekty různých datových typů, včetně seznamů. Pokud jí předáte seznam, pak metoda update() přidá do původní množiny všechny členy seznamu.

Odstraňování položek z množiny

Jednotlivé hodnoty lze z množiny odstranit třemi způsoby. První dva, discard() a remove(), se liší v jedné malé drobnosti.

>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> a_set
{1, 3, 36, 6, 10, 45, 15, 21, 28}
>>> a_set.discard(10)                        
>>> a_set
{1, 3, 36, 6, 45, 15, 21, 28}
>>> a_set.discard(10)                        
>>> a_set
{1, 3, 36, 6, 45, 15, 21, 28}
>>> a_set.remove(21)                         
>>> a_set
{1, 3, 36, 6, 45, 15, 28}
>>> a_set.remove(21)                         
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 21
  1. Metoda discard() přebírá jeden argument a zadanou hodnotu odebere z množiny.
  2. Pokud metodu discard() voláme s hodnotou, která v množině neexistuje, neprovede se nic. Nevznikne chyba. Jde o prázdnou operaci.
  3. Metoda remove() také přebírá hodnotu jediného argumentu a také odstraňuje hodnotu z množiny.
  4. Odlišnost se projeví v případě, kdy se zadaná hodnota v množině nenachází. V takovém případě metoda remove() vyvolá výjimku KeyError.

Množiny, stejně jako seznamy, podporují metodu pop().

>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> a_set.pop()                                
1
>>> a_set.pop()
3
>>> a_set.pop()
36
>>> a_set
{6, 10, 45, 15, 21, 28}
>>> a_set.clear()                              
>>> a_set
set()
>>> a_set.pop()                                
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'pop from an empty set'
  1. Metoda pop() odstraní jeden prvek z množiny a vrátí jeho hodnotu. Ale množiny jsou neuspořádané a neexistuje u nich nic takového jako „poslední“ hodnota. Proto také neexistuje možnost ovlivnit, která hodnota bude odstraněna. Je to zcela náhodné.
  2. Metoda clear() odstraní všechny prvky množiny a množina se stane prázdnou. Ve výsledku je to stejné jako provedení příkazu a_set = set(), který vytvoří novou prázdnou množinu a přepíše původní hodnotu proměnné a_set.
  3. Pokus o volání metody pop() pro prázdnou množinu vede k vyvolání výjimky KeyError.

Běžné množinové operace

Pythonovský datový typ set podporuje několik běžných množinových operací.

>>> a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195}
>>> 30 in a_set                                                     
True
>>> 31 in a_set
False
>>> b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21}
>>> a_set.union(b_set)                                              
{1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127}
>>> a_set.intersection(b_set)                                       
{9, 2, 12, 5, 21}
>>> a_set.difference(b_set)                                         
{195, 4, 76, 51, 30, 127}
>>> a_set.symmetric_difference(b_set)                               
{1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51}
  1. Pokud chceme otestovat, zda je daná hodnota prvkem množiny, použijeme operátor in. Funguje stejným způsobem jako u seznamů.
  2. Metoda union() (sjednocení) vrací novou množinu, která obsahuje všechny prvky jak z jedné, tak z druhé množiny.
  3. Metoda intersection() (průnik) vrací novou množinu, která obsahuje všechny prvky nacházející se v obou množinách současně.
  4. Metoda difference() (rozdíl) vrací novou množinu obsahující všechny prvky, které se nacházejí v množině a_set, ale nenacházejí se v množině b_set.
  5. Metoda symmetric_difference() (symetrický rozdíl) vrací novou množinu obsahující všechny prvky, které se nacházejí právě v jedné z množin.

Tři z těchto metod jsou symetrické.

# pokračování předchozího příkladu
>>> b_set.symmetric_difference(a_set)                                       
{3, 1, 195, 4, 6, 8, 76, 15, 17, 18, 51, 30, 127}
>>> b_set.symmetric_difference(a_set) == a_set.symmetric_difference(b_set)  
True
>>> b_set.union(a_set) == a_set.union(b_set)                                
True
>>> b_set.intersection(a_set) == a_set.intersection(b_set)                  
True
>>> b_set.difference(a_set) == a_set.difference(b_set)                      
False
  1. Symetrický rozdíl množin a_set od b_set vypadá jinak než symetrický rozdíl množin b_set od a_set. Ale pamatujte na to, že množiny jsou neuspořádané. Jakékoliv dvě množiny, jejichž všechny hodnoty se shodují (žádná nesmí být vynechána), se považují za shodné.
  2. A přesně tento případ nastal zde. Nenechte se zmást reprezentacemi těchto množin zobrazenými pythonovským shellem. Obsahují stejné hodnoty, takže jsou shodné.
  3. Sjednocení dvou množin je také symetrické.
  4. Průnik dvou množin je rovněž symetrický.
  5. Rozdíl dvou množin symetrický není. Ono to dává smysl. Podobá se to odčítání jednoho čísla od druhého. Na pořadí operandů zde záleží.

A nakonec tu máme několik otázek, které můžeme množinám položit.

>>> a_set = {1, 2, 3}
>>> b_set = {1, 2, 3, 4}
>>> a_set.issubset(b_set)    
True
>>> b_set.issuperset(a_set)  
True
>>> a_set.add(5)             
>>> a_set.issubset(b_set)
False
>>> b_set.issuperset(a_set)
False
  1. Množina a_set je podmnožinou množiny b_set — všechny prvky množiny a_set jsou současně prvky množiny b_set.
  2. Stejnou otázku můžeme položit obráceně. Množina b_set je nadmnožinou množiny a_set, protože všechny prvky množiny a_set jsou současně prvky množiny b_set.
  3. Jakmile do množiny a_set přidáme hodnotu, která se v množině b_set nenachází, oba testy vrátí hodnotu False.

Množiny v booleovském kontextu

Množiny můžeme použít v booleovském kontextu, například v příkazu if.

>>> def is_it_true(anything):
...   if anything:
...     print("yes, it's true")
...   else:
...     print("no, it's false")
...
>>> is_it_true(set())          
no, it's false
>>> is_it_true({'a'})          
yes, it's true
>>> is_it_true({False})        
yes, it's true
  1. Prázdná množina se v booleovském kontextu vyhodnocuje jako false.
  2. Libovolná množina s alespoň jedním prvkem se vyhodnocuje jako true.
  3. Libovolná množina s alespoň jedním prvkem se vyhodnocuje jako true. Hodnota prvků je nepodstatná.

Slovníky

Slovník (dictionary) je neuspořádaná kolekce dvojic klíč-hodnota. Když do slovníku přidáme klíč, musíme do něj současně přidat i hodnotu, která ke klíči patří. (Hodnotu můžeme v budoucnu kdykoliv změnit.) Pythonovské slovníky jsou optimalizované pro získávání hodnoty k zadanému klíči, ale ne naopak.

Pythonovský slovník se chová jako hash (čti [heš]; vyhledávací tabulka) v Perl 5. V jazyce Perl 5 začínají proměnné typu hash vždy znakem %. Pythonovské proměnné mohou být pojmenovány zcela libovolně. Python si vnitřně eviduje jejich datový typ.

Vytvoření slovníku

Slovník vytvoříme snadno. Syntaxe se podobá množinové, ale místo pouhé hodnoty zadáváme dvojice klíč-hodnota. Jakmile slovník existuje, můžeme v něm vyhledávat hodnoty podle jejich klíče.

>>> a_dict = {'server': 'db.diveintopython3.org', 'database': 'mysql'}  
>>> a_dict
{'server': 'db.diveintopython3.org', 'database': 'mysql'}
>>> a_dict['server']                                                    
'db.diveintopython3.org'
>>> a_dict['database']                                                  
'mysql'
>>> a_dict['db.diveintopython3.org']                                    
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'db.diveintopython3.org'
  1. Nejdříve vytvoříme slovník s dvěma položkami a přiřadíme ho do proměnné a_dict. Každá položka je tvořena dvojicí klíč-hodnota a celý výčet položek je uzavřen ve složených závorkách.
  2. Řetězec 'server' je zde klíčem a k němu přidruženou hodnotou, na kterou se odkážeme zápisem a_dict['server'], je 'db.diveintopython3.org'.
  3. Řetězec 'database' je zde klíčem. K němu přidruženou hodnotou, na kterou se odkážeme zápisem a_dict['database'], je 'mysql'.
  4. Hodnoty můžeme získat na základě klíče, ale klíče nemůžeme získat na základě znalosti hodnoty. Takže a_dict['server'] obsahuje 'db.diveintopython3.org', ale a_dict['db.diveintopython3.org'] vyvolá výjimku, protože 'db.diveintopython3.org' není klíčem.

Úprava slovníku

Slovníky nemají žádné předem určené omezení velikosti. Dvojici klíč-hodnota můžeme do slovníku přidat kdykoliv. Nebo můžeme měnit hodnotu příslušející ke klíči. Pokračování předchozího příkladu:

>>> a_dict
{'server': 'db.diveintopython3.org', 'database': 'mysql'}
>>> a_dict['database'] = 'blog'  
>>> a_dict
{'server': 'db.diveintopython3.org', 'database': 'blog'}
>>> a_dict['user'] = 'mark'      
>>> a_dict                       
{'server': 'db.diveintopython3.org', 'user': 'mark', 'database': 'blog'}
>>> a_dict['user'] = 'dora'      
>>> a_dict
{'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}
>>> a_dict['User'] = 'mark'      
>>> a_dict
{'User': 'mark', 'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}
  1. Ve slovníku se nemohou nacházet duplicitní klíče. Pokud přiřadíme hodnotu k existujícímu klíči, dojde k přepsání původní hodnoty.
  2. Dvojici klíč-hodnota můžeme přidat kdykoliv. Tato syntaxe se shoduje s případem změny existujících hodnot.
  3. Nová položka slovníku (klíč 'user', hodnota 'mark') se objevila uprostřed. To, že se u prvního příkladu položky objevily seřazené, byla pouhá náhoda. Stejná náhoda je to, že se nyní jeví jako rozházené.
  4. Přiřazení hodnoty k existujícímu klíči slovníku vede k prosté náhradě staré hodnoty novou.
  5. Změní se tímto příkazem hodnota klíče user zpět na „mark“? Nikoliv! Prohlédněte si klíč pořádně. V řetězci User je napsáno velké U. Klíče slovníků jsou citlivé na velikost písmen, takže tento příkaz vytváří novou dvojici klíč-hodnota a existující hodnotu nepřepíše. Klíč se vám sice může zdát podobný, ale z pohledu Pythonu je úplně jiný.

Slovníky se smíšeným obsahem

Slovníky nejsou určeny jen pro řetězce. Hodnoty ve slovníku mohou být libovolného datového typu včetně celých čísel, booleovských hodnot, libovolných objektů nebo dokonce slovníků. Uvnitř jednoho slovníku nemusí být všechny hodnoty stejného typu. Můžeme je míchat podle potřeby. Klíče slovníků mají větší omezení, ale mohou být typu řetězec, celé číslo a několika dalších typů. Datové typy klíčů v jednom slovníku můžeme také míchat.

Se slovníky s neřetězcovými klíči a hodnotami jsme se vlastně už setkali v kapitole Váš první pythonovský program.

SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
            1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}

Teď to v interaktivním shellu rozkucháme.

>>> SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
...             1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
>>> len(SUFFIXES)      
2
>>> 1000 in SUFFIXES   
True
>>> SUFFIXES[1000]     
['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
>>> SUFFIXES[1024]     
['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
>>> SUFFIXES[1000][3]  
'TB'
  1. Funkce len(), podobně jako u seznamů a množin, vrací počet klíčů ve slovníku.
  2. A stejně jako u seznamů a množin můžeme použít operátor in k testování, zda je zadaný klíč ve slovníku definován.
  3. Číslo 1000 je klíčem ve slovníku SUFFIXES. Jeho hodnotou je seznam osmi položek (osmi řetězců, abychom byli přesní).
  4. A podobně i číslo 1024 je klíčem ve slovníku SUFFIXES. Jeho hodnotou je také seznam s osmi položkami.
  5. A protože SUFFIXES[1000] obsahuje seznam, můžeme jeho jednotlivé prvky zpřístupňovat prostřednictvím indexu (od nuly).

Slovníky v booleovském kontextu

Slovník můžeme použít v booleovském kontextu, jako například v příkazu if.

>>> def is_it_true(anything):
...   if anything:
...     print("yes, it's true")
...   else:
...     print("no, it's false")
...
>>> is_it_true({})             
no, it's false
>>> is_it_true({'a': 1})       
yes, it's true
  1. Prázdný slovník se v booleovském kontextu vyhodnocuje jako false.
  2. Slovník s alespoň jednou dvojicí klíč-hodnota se vyhodnocuje jako true.

None

None [nan] je speciální pythonovskou konstantou. Vyjadřuje žádnou hodnotu. Ale None není totéž co False. None není nula. None není prázdný řetězec. Pokud porovnáme None s čímkoliv jiným než s None, vždycky dostaneme False.

None je jedinou „žádnou“ hodnotou. Má svůj vlastní datový typ (NoneType). Hodnotu None můžeme přiřadit do libovolné proměnné, ale nemůžeme vytvořit jiný objekt typu NoneType. Všechny proměnné, jejichž hodnota je None, jsou vzájemně shodné.

>>> type(None)
<class 'NoneType'>
>>> None == False
False
>>> None == 0
False
>>> None == ''
False
>>> None == None
True
>>> x = None
>>> x == None
True
>>> y = None
>>> x == y
True

None v booleovském kontextu

V booleovském kontextu se None vyhodnocuje jako false a not None jako true.

>>> def is_it_true(anything):
...   if anything:
...     print("yes, it's true")
...   else:
...     print("no, it's false")
...
>>> is_it_true(None)
no, it's false
>>> is_it_true(not None)
yes, it's true

Přečtěte si

© 2001–11 Mark Pilgrim