Hlavní navigace

Létající cirkus (9)

Jan Švec 12. 4. 2002

Jak jsem již slíbil na konci minulého dílu našeho seriálu o jazyce Python, budeme se dnes věnovat těm syntaktickým obratům, na které se v minulých dílech nedostalo. Budou to hlavně skládání a rozklad sekvencí, anonymní lambda funkce a formátování řetězců.

Skládání a rozklad sekvencí

Co jsou sekvence, jsme si vysvětlili již v prvních dílech seriálu. Každá sekvence má konečný počet prvků. Proměnnými sekvenčními typy jsou seznamy, neměnnými pak tuple. Ke všemu si programátor může vytvořit vlastní třídy, které implementují rozhraní sekvenčních typů (čtení, nastavení a smazání prvku na určitém indexu). Sekvence jsou indexovány vzestupně čísly (první je podobně jako v C/C++ nula). Seznam vytvoříme pomocí výrazu, který se do češtiny nechá volně přeložit jako konstruktor seznamu (anglicky list display). Jeho nejjednodušší formou je výčet prvků oddělených čárkou a obklopený hranatými závorkami. Další možné formy zápisu si uvedeme později.

Tuple, jak již také víme, vytvoříme jako výčet prvků oddělených čárkou, volitelně uzavřený mezi kulaté závorky. Kulaté závorky můžeme vynechat, používají se v případech, kdy je třeba zabránit dvojznačnostem.

>>> 1, 2, 3
(1, 2, 3)
>>> (1, 2, 3)
(1, 2, 3)
>>> 1, 2, 3,
(1, 2, 3)

Toto vše jsou tuple o třech prvcích 1, 2 a 3. Vytváření tuple pomocí čárek se také nazývá tuple packing (skládání tuple). Opačnou operací je sequence unpacking (rozklad sekvencí). Ta využívá toho, že výčet prvků oddělených čárkou nemusí stát jen na pravé straně přiřazení, ale i na jeho levé straně:

>>> a, b, c = 1, 2, 3
>>> a, b = b, a
>>> a
2
>>> b
1

Toho se dá s výhodou využít pro přiřazení hodnot více proměnným najednou nebo pro záměnu hodnot dvou proměnných bez použití pomocné proměnné. Rozklad sekvencí, jak již napovídá název, se může aplikovat na libovolnou sekvenci. Na pravé straně přiřazení tedy může stát i seznam. Použití rozkladu sekvencí se neomezuje jen na přiřazení, ale s výhodou ho můžeme použít i například při definici funkce nebo ve větvi except konstrukce try..except:

>>> import math                                    # (1)
>>> def vzdalenost_bodu((x1, y1), (x2, y2)):       # (2)
...     return math.sqrt((x1 - x2)**2 + \          # (3)
...                      (y1 - y2)**2)             # (4)
...                                                # (5)
>>> bod1 = (1, 0)                                  # (6)
>>> bod2 = (4, 4)                                  # (7)
>>> print vzdalenost_bodu(bod1, bod2)              # (8)
5.0                                                # (9)

Všimněte si především řádku (2). Funkce vzdalenost_bodu přebírá dva argumenty, které musí být dvouprvkové tuple. Tyto argumenty reprezentují souřadnice x a y dvou bodů. Při volání funkce vzdalenost_bodu s proměnnými bod1 a bod2 jako argumenty dojde právě na řádku (2) k rozkladu těchto tuple na jednoduché proměnné x1, y1, x2 a y2. Je třeba zdůraznit, že výčet prvků na obou stranách přiřazení musí být při aplikování rozkladu sekvencí STEJNÝ. Toto volání funkce vzdalenost_bodu vede k výjimce ValueError:

>>> bod3 = (1, 2, 3)
>>> print vzdalenost_bodu(bod3, bod2)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 1, in vzdalenost_bodu
ValueError: unpack tuple of wrong size

Konstuktor seznamu

S konstruktorem seznamu jsme se již setkali. Byla to jeho nejjednodušší varianta, kterou jste poznali ve druhém dílu seriálu:

>>> s1 = [1, 2, 3, 4]                          # (1)
>>> s2 = []                                    # (2)
>>> s3 = [2]                                   # (3)

Jazyk Python ale nabízí i rozšířenou syntax, ve které máme přístupné zjednodušené konstrukce for a if. Jednoduché převedení tuple na seznam by se dalo provést třeba takto:

>>> tuple = (1, 2, 3, 4, 5)
>>> seznam = [i for i in tuple]
>>> seznam
[1, 2, 3, 4, 5]

V tomto případě je jako první v hranatých závorkách uveden výraz, jehož hodnoty budou tvořit prvky nově vzniklého seznamu. Tento konstruktor bere postupně prvky jeden za druhým z proměnné tuple a dosazuje je za řídící proměnnou i. Poté se vyhodnotí výraz před slovem for a z hodnot tohoto výrazu se nakonec složí nový seznam. Pro výpočet tabulky druhých mocnin čísel od 1 do 5 můžeme použít následující výraz:

>>> [i**2 for i in range(1, 6)]
[1, 4, 9, 16, 25]

Konstrukci for lze doplnit i o podmínku, kterou můžeme omezit prvky, jež se mají vyskytnout v novém seznamu. Pro více informací vám doporučuji nahlédout do dokumentace k Pythonu. Seznam sudých čísel od 0 do 10 můžeme vytvořit třeba takto.

>>> [i for i in range(11) if i % 2 == 0]
[0, 2, 4, 6, 8, 10]

Anonymní lambda funkce

Pro definování funkcí zná Python, kromě klíčového slova def, i klíčové slovo lambda, kterým lze vytvořit takzvanou anonymní funkci. Tělem této funkce musí být jediný výraz! Návratová hodnota lambda funkce je rovna hodnotě výrazu. Lambda funkce mohou mít také parametry. Vytvoření nové anonymní funkce je výraz, takže abychom k funkci mohli přistupovat, musíme této funkci přiřadit nějaké proměnné:

>>> to_upper = lambda str: str.upper()
>>> print to_upper('python - batteries included')
PYTHON - BATTERIES INCLUDED

Lambda funkce jsou pouze jakousi zkratkou a její tělo musí opravdu tvořit jediný výraz. Nelze tedy používat konstrukce jako if, for nebo print. Velice se ale hodí jako argument pro funkce, které vyžadují určitou zpětnou vazbu (příkladem mohou být funkce os.path.walk(), map() nebo reduce() – pro jejich popis nahlédněte prozatím do dokumentace, k jejich výkladu se dostaneme v některém z dalších dílů).

Formátování řetězců

Jazyk Python obsahuje operátor %, který normálně znamená zbytek po dělení (modulo). Pro řetezce, a to jak normální, tak Unicode, má tento operátor jiný význam. Jedná se totiž o operátor formátování řetězce, obdoba C funkce sprintf(). Pro formátování řetězců musíme nejprve sestavit formátovací řetězec, v němž pomocí speciálních sekvencí znaků vyznačíme místa, kam se mají vložit data, která se předají operátoru %:

>>> 'Dnes je %s, aktualni cas %d:%02d' % ('patek', 15, 2)
'Dnes je patek, aktualni cas 15:02'

Pro ty, kteří nevědí o čem je řeč, ve zkratce shrnu podstatu formátování řetězců. Ta spočívá v prohledávání formátovacího řetězce (první operand operátoru %) a náhrada každé řídící sekvence jí odpovídajícími daty (druhý operand). Řídící sekvence začíná znakem % a následující znak určuje typ konverze, která se má s odpovídajícím prvkem dat provést (např. %s znamená převedení aktuálního argumentu na řetězec, blíže viz dokumentace k jazyku). Po zpracování řídící sekvence se začne vyhodnocovat další řídící sekvence, spolu s dalším prvkem dat. Jakýkoli řetězec, který nepatří mezi řídící, je do výstupního řetězce zkopírován beze změny. Data jsou operátoru % předávána jako tuple, pouze v případě, kdy se jako data použije jediný výraz, je možné ho psát jako singleton.

Formátovací řetězce umožňují specifikovat i šířku jednotlivých polí, přesnost desetinné části, (ne)zobrazování znaménka + před kladnými čísly, zarovnání nalevo nebo napravo atd. Bližší popis by vystačil na samostatný díl seriálu. Protože jde ale o techniku všeobecně známou (právě z C/C++), nebudeme se jí dále věnovat. Případné zájemce odkáži do dokumentace k jazyku Python (protože tato stránka není uvedena v indexu dokumentace, hledejte v části Python Library Reference sekci číslo 2.2.6.2).

Příště

Další díl bude věnovaný jedné z nových vlastností, které zavádí Python verze 2.2 – iterátory a generátory. Probereme si hlavně syntaxi a funkci klíčového slova yield a zmíníme se o funkci iter() a jejím významu ve spojení s konstrukcí for.

Našli jste v článku chybu?
Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Vitalia.cz: Z tohoto konopí dělají léčivé masti

Z tohoto konopí dělají léčivé masti

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

120na80.cz: Co všechno ovlivňuje ženskou plodnost?

Co všechno ovlivňuje ženskou plodnost?

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

Vitalia.cz: Dáte si jahody s plísní?

Dáte si jahody s plísní?

Vitalia.cz: Říká amoleta - a myslí palačinka

Říká amoleta - a myslí palačinka

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

Lupa.cz: Seznam mění vedení. Pavel Zima v čele končí

Seznam mění vedení. Pavel Zima v čele končí

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

DigiZone.cz: ČRa DVB-T2 ověřeno: Hisense a Sencor

ČRa DVB-T2 ověřeno: Hisense a Sencor

Vitalia.cz: Znáte „černý detox“? Ani to nezkoušejte

Znáte „černý detox“? Ani to nezkoušejte