načítání...
nákupní košík
Košík

je prázdný
a
b

Python 3 - Mark Summerfield

Python 3
-14%
sleva

Kniha: Python 3
Autor:

Chcete se odlišit od davů dalších programátorů a zvolili jste Python jako prostředek? Výukový kurz vám nabídne široký záběr témat věnovaných poslednímu evolučnímu stupni Pythonu, ... (celý popis)
Titul doručujeme za 3 pracovní dny
Vaše cena s DPH:  690 Kč 593
+
-
rozbalKdy zboží dostanu
19,8
bo za nákup
rozbalVýhodné poštovné: 29Kč
rozbalOsobní odběr zdarma

ukázka z knihy ukázka

Titul je dostupný ve formě:
tištěná forma elektronická forma

hodnoceni - 71.2%hodnoceni - 71.2%hodnoceni - 71.2%hodnoceni - 71.2%hodnoceni - 71.2% 90%   celkové hodnocení
1 hodnocení + 0 recenzí

Specifikace
Nakladatelství: » Computer press
Médium / forma: Tištěná kniha
Rok vydání: 2010-04-29
Počet stran: 584
Rozměr: 167 x 225 mm
Úprava: 584 stran
Vydání: Vyd. 1.
Název originálu: Programming in Python 3
Spolupracovali: překlad Lukáš Krejčí
Vazba: brožovaná lepená
ISBN: 9788025127377
EAN: 9788025127377
Ukázka: » zobrazit ukázku
Popis

Chcete se odlišit od davů dalších programátorů a zvolili jste Python jako prostředek? Výukový kurz vám nabídne široký záběr témat věnovaných poslednímu evolučnímu stupni Pythonu, se kterým zvládnete vyřešit drtivou většinu obvyklých zadání. Pronikněte i vy do světa krátkých a efektivních programů. Zkušený autor vás provede Pythonem od prvních jednoduchých programů až po komplexní projekty, které pracují se sítí, databázemi nebo ve více vláknech. Pro rychlé osvojení nových informací jsou v knize odkazy na podobná témata, která souvisejí s aktuálně probíranou látkou. Na konci každé kapitoly najdete příklady, krátké shrnutí a cvičení, které pomůže upevnit nově nabyté poznatky. Publikace vás mimo jiné naučí, jak: - Vytvářet vlastní balíčky a moduly - Zpracovávat soubory různých typů - Rozložit zátěž do procesů a vláken - Využít spolupráci s databázemi - Efektivně ladit a testovat vyvíjené projekty - Využít v programech sílu regulárních výrazů - Vytvořit grafické uživatelské rozhraní O autorovi: Mark Summerfield je nezávislý školitel a konzultant specializující se na Python, C++, Qt a PyQt. Je autorem a spoluautorem několika programátorských knih zaměřených na jazyky, které vyučuje. (výukový kurz)

Předmětná hesla
Python (programovací jazyk)
Programování
Kniha je zařazena v kategoriích
Mark Summerfield - další tituly autora:
Recenze a komentáře k titulu
Zatím žádné recenze.


Ukázka / obsah
Přepis ukázky
LEKCE 5 Moduly V této lekci: Moduly a balíčky Přehled standardní knihovny Pythonu ‹ ‹ 194 Lekce 5: Moduly Zatímco pomocí funkcí můžeme rozdělit části kódu tak, aby je bylo možné opětovně použít v rámci daného programu, moduly poskytují prostředky pro shromažďování skupin funkcí (a jak uvidíme v následující lekci také vlastních datových typů) tak, aby je bylo možné použít v libovolném počtu programů. Python dále nabízí možnost vytvářet balíčky, což jsou skupiny modulů seskupené dohromady, obvykle z toho důvodu, že tyto moduly poskytují související funkční prvky, nebo proto, že na sobě vzájemně závisejí. První část této lekce popisuje syntaxe pro importování funkčních prvků z modulů a balíčků, ať už se standardní knihovny nebo z našich vlastních modulů a balíčků. Ve druhé části se posuneme dále a podíváme se, jak vytvářet vlastní balíčky a moduly. Ukážeme si dva vlastní moduly, z nichž první bude seznamovací a druhý bude demonstrovat, jak vyřešit řadu praktických problémů, jako je nezávislost na platformě a testování. Druhá část nabízí stručný přehled standardní knihovny Pythonu. Je důležité mít na paměti, co tato knihovna obsahuje, protože používání předem definovaných funkčních prvků značně zrychluje programování. Mnohé moduly standardní knihovny je široce rozšířené, dobře otestované a robustní. Kromě přehledu si pomocí malých příkladů ukážeme několik běžných případů užití. U modulů probíraných v jiných lekcích budou navíc uvedeny křížové odkazy. Moduly a balíčky Modul jazyka Python je jednoduše řešeno soubor s příponou .py. Modul může obsahovat libovolný kód jazyka Python. Všechny programy, které jsme dosud napsali, byly obsažené v jediném souboru .py, a proto se jedná o moduly i programy. Podstatným rozdílem je to, že programy jsou navržené pro spouštění, kdežto moduly jsou navržené pro importování a použití v programech. Ne všechny moduly mají přidružené soubory .py. Například modul sys je vestavěný do Pythonu a některé moduly jsou napsané v jiných jazycích (povětšinou v jazyku C). Nicméně větší část knihovny Pythonu je napsána v jazyku Python. Pokud tedy například napíšeme import collections, můžeme voláním collections.namedtuple() vytvářet pojmenované n-tice a funkčnost, k níž přistupujeme, se nachází v souboru modulu collections.py. Z hlediska našeho programu je nepodstatné, ve kterém jazyku je daný modul napsán, protože všechny moduly se importují a používají stejným způsobem. Pro importování lze použít několik syntaxí: import importovatelný_prvek import importovatelný_prvek1, importovatelný_prvek2, ..., importovatelný_prvekN import importovatelný_prvek as preferovaný_název Zde je importovatelný_prvek obvykle modulem, jako je collections, může však jít také o balíček nebo modul v balíčku, přičemž se každá část odděluje tečkou (.), například os.path. První dvě syntaxe používáme v rámci této knihy. Jsou nejjednodušší a také nejbezpečnější, protože nehrozí možnost konfliktu názvů, což je dáno tím, že musíme vždy používat plně kvalifikované názvy. Webová doku- mentace ¾ 171 Balíčky ¾ 197 195 Třetí syntaxe nám umožňuje dát importovanému balíčku nebo modulu název dle vlastní volby. To sice může teoreticky vést ke kolizi názvů, ovšem v praxi se tato syntaxe používá právě proto, aby k ní nedocházelo. Přejmenování je užitečné zejména tehd y, když experimentujeme s různými implementacemi nějakého modulu. Pokud máme například dva moduly MyModuleA a MyModuleB, které mají stejné rozhraní API (Application Programming Interface – aplikační programovací rozhraní), mohli bychom v programu napsat import MyModuleA as MyModule a později hladce přejít k druhému modulu příkazem import MyModuleB as MyModule. Kde bychom měli příkazy import umisťovat? Běžně se všechny příkazy import umisťují na začátek souborů .py, za řádek shebang a před dokumentaci modulu. Jak jsme si již řekli v lekci 1, doporučujeme nejdříve importovat moduly standardní knihovny, poté moduly knihoven třetích stran a nakonec naše vlastní moduly. Zde je několik dalších syntaxí příkazu import: from importovatelný_prvek import objekt as preferovaný_název from importovatelný_prvek import objekt1, objekt2, ..., objektN from importovatelný_prvek import (objekt1, objekt2, objekt3, objekt4, objekt5, objekt6, ..., objektN) from importovatelný_prvek import * Tyto syntaxe mohou způsobovat konflikty názvů, poněvadž činí importované objekty (proměnné, funkce, datové typy nebo moduly) přímo přístupné. Pokud chceme použít syntaxi from ... import pro importování velkého množství objektů, můžeme použít více řádků, a to buď tak, že každý nový řádek kromě posledního potlačíme nebo názvy objektů uzavřeme do závorek, jak ukazuje třetí syntaxe. Hvězdička (*) v poslední syntaxi znamená „importuj vše, co není soukromé“, což v praxi znamená buď to, že se importuje každý objekt v modulu kromě těch, jejichž název začíná podtržítkem, nebo že se importují všechny objekty, jejichž názvy jsou obsaženy v seznamu __all__ definovaném jako globální proměnná daného modulu. Zde je několik příkladů použití příkazu import: import os print(os.path.basename(filename)) # bezpečný, plně kvalifikovaný přístup import os.path as path print(path.basename(filename)) # riziko kolize názvů s path from os import path print(path.basename(filename)) # riziko kolize názvů s path from os.path import basename print(basename(filename)) # riziko kolize názvů s basename from os.path import * print(basename(filename)) # riziko kolize spousty názvů __all__ ¾ 198 Moduly a balíčky 196 Lekce 5: Moduly Syntaxe from importovatelný_prvek import * importuje všechny objekty z daného modulu (nebo všechny moduly z daného balíčku), což může znamenat stovky názvů. V případě příkazu from os.path import * se importuje téměř 40 názvů, mezi něž patří i dirname, exists a split, což mohou být názvy, které bychom raději použili pro naše vlastní proměnné nebo funkce. Pokud například napíšeme příkaz from os.path import dirhame, pak můžeme přímo zavolat dirname() bez kvalifikace. Pokud poté ale ve svém kódu napíšeme dirname = „.“, bude nyní odkaz na objekt dirname místo funkce dirname() svázán s řetězcem “.”, takže když se pokusíme zavolat dirname(), obdržíme výjimku TypeError, protože dirname nyní ukazuje na řetězec a řetězce nejsou volatelné. Z hlediska případných kolizí názvů vytvářených syntaxí import * některé vývojářské týmy specifikují ve svých směrnicích, že se může používat pouze syntaxe import importovatelný_prvek. Nicméně určité rozsáhlé balíčky, zvláště pak knihovny GUI, se často importují tímto způsobem, protože obsahují obrovské množství funkcí a tříd (vlastních datových typů), jejichž ruční vypisování by bylo velice pracné. Přirozeně zde vyvstává otázka, jak Python ví, kde importované moduly a balíčky hledat? Vestavěný modul sys obsahuje seznam sys.path, který uchovává seznam adresářů, které představují cestu Pythonu (Python path). První adresář je adresářem, který obsahuje samotný program, a to i tehdy, pokud byl program vyvolán z jiného adresáře. Je-li nastavena proměnná prostředí PYTHONPATH, jsou v ní specifikované další cesty v seznamu. Poslední cesty jsou ty, které jsou nezbytné pro přístup k standardní knihovně Pythonu – nastavují se při instalaci Pythonu. Upozornění: Při prvním importu vestavěného modulu se Python po tomto modulu podívá postupně v každé cestě uvedené v seznamu sys.path. Jedním z důsledků tohoto postupu je to, že pokud vytvoříme modul nebo program se stejným názvem, jako má jeden z knihovních modulů Pythonu, najde se ten náš jako první, což nevyhnutelně způsoby problémy. Aby k tomuto nedošlo, nikdy nevytvářejte program či modul se stejný názvem, jako má některý z knihovních adresářů či modulů Pythonu nejvyšší úrovně. Výjimkou je samozřejmě situace, kdy vytváříte svou vlastní implementaci takovéhoto modulu a záměrně jej přepisujete. (Modul nejvyšší úrovně je modul, jehož soubor .py je umístěn v jednom z adresářů v cestě Pythonu, a ne v jednom z jejich podadresářů.) Například v systému Windows obsahuje cesta Pythonu obvykle adresář s názvem C:Python31Lib, takže na této platformě bychom neměli vytvářet modul s názvem Lib.py ani modul se stejným názvem, jako má kterýkoliv modul v adresáři C:Python31Lib. Pro rychlý způsob kontroly, zda se nějaký název modulu již používá, stačí vyzkoušet příkaz import s tímto názvem. To lze provést v konzole zavoláním interpretu s volbou příkazového řádku –c („execute code“ – proveď kód), za níž umístíme příslušný příkaz import. Pokud například chceme zjistit, zda existuje modul s názvem Music.py (nebo adresář nejvyšší úrovně v cestě Pythonu s názvem Music), pak můžeme do konzoly napsat následující příkaz: python -c „import Music“ Pokud obdržíme výjimku ImportError, víme, že se žádný modul nebo adresář nejvyšší úrovně tohoto jména nepoužívá. Jakýkoliv jiný výstup (nebo žádný) znamená, že toto jméno je již zabráno. Tento postup ale naneštěstí nezaručuje, že daný název bude vždy bez problémů, poněvadž můžeme později nainstalovat balíček či modul Pythonu od třetí strany, který obsahuje konfliktní název, i když v praxi se jedná o velmi ojedinělý problém. 197 Pokud bychom například vytvořili soubor modulu s názvem os.py, došlo by ke konfliktu s knihovním modulem os. Pokud ale vytvoříme modul s názvem path.py, bude to v pořádku, protože bude importován jako modul path, kdežto knihovní modul se importuje jako os.path. V této knize je v názvech souborů našich vlastních modulů první písmeno vždy velké, čímž se vyhneme konfliktům názvů (alespoň na Unixu), protože názvy souborů modulů standardní knihovny obsahují jen malá písmena. Program může importovat některé moduly, které následně importují své vlastní moduly, včetně některých, které již byly importovány. To však nezpůsobí žádné problémy. Kdykoliv je totiž nějaký modul importován, tak Python nejdříve zkontroluje, zda již nebyl importován dříve. Pokud nebyl, tak Python spustí zkompilovaný bajt-kód modulu, čímž vytvoří příslušné proměnné, funkce a další objekty daného modulu a interně si poznačí, že tento modul již byl importován. Při každém dalším importu tohoto modulu Python detekuje, že již byl importován, a neudělá nic. Když Python potřebuje zkompilovaný bajt-kód modulu, automaticky jej vygeneruje. Tím se liší třeba od Javy, kde se kompilace do bajt-kódu musí provést explicitním způsobem. Python se nejdříve podívá po souboru se stejným názvem jako má soubor .py daného modulu, ale s příponou .pyo, což je optimalizovaná verze se zkompilovaným bajt-kódem modulu. Pokud žádný soubor .pyo neexistuje (nebo pokud je starší než soubor .py, což znamená, že není aktuální), Python se podívá po souboru s příponou .pyc, což je neoptimalizovaná verze se zkompilovaným bajt-kódem modulu. Pokud Python najde aktuální verzi se zkompilovaným bajt-kódem modulu, tak ji načte. V opačném případě načte soubor .py a zkompiluje verzi se zkompilovaným bajt-kódem. Tak jako tak bude mít nakonec Python modul v paměti ve formě zkompilovaného bajt-kódu. Pokud by Python musel zkompilovat soubor .py, uloží jej do souboru .pyc (nebo .pyo, pokud je na příkazovém řádku uvedena volba -O nebo pokud je nastavena proměnná prostředí PYTHONOPTIMIZE), ovšem za předpokladu, že do příslušného adresáře lze zapisovat. Ukládání bajt-kódu lze zamezit volbou příkazového řádku -B nebo nastavením proměnné prostředí PYTHONDONTWRITEBYTECODE. Používání souborů se zkompilovaným bajt-kódem vede k rychlejšímu spouštění, protože interpret nemusí kód načítat, kompilovat, ukládat (je-li to možné) a spouštět, ale stačí mu jen kód načíst a spustit. Je však třeba poznamenat, že na samotný běh kódu to žádný vliv nemá. Při instalaci Pythonu se moduly standardní knihovny obvykle zkompilují do bajt-kódu v rámci instalačního procesu. Balíčky Balíček je obyčejným adresářem, který obsahuje skupinu modulů a soubor s názvem __init__.py. Představte si, že máme smyšlenou skupinu souborů modulů pro čtení a zapisování nejrůznějších formátů grafických souborů, jako jsou například moduly Bmp.py, Jpeg.py, Png.py, Tiff.py a Xpm. py, z nichž každý nabízí funkce load(), save() a tak podobně. * Moduly bychom mohli nechat ve stejném adresáři, v němž je náš program, ale u větších programů, které používají množství vlastních modulů, by se grafické moduly úplně ztratily. Jejich umístěním do samostatného podadresáře (např. Graphics) je budeme mít pěkně pohromadě. A pokud k nim do adresáře Graphics přidáme prázdný soubor __init__.py, stane se z tohoto adresáře balíček: * Rozsáhlou podporu pro práci s grafickými soubory poskytuje spousta modulů třetích stran, z nichž je nejpozoruhodnější knihovna Python Imaging Library (www.pythonware.com/products/pil). Moduly a balíčky 198 Lekce 5: Moduly Graphics/ __init__.py Bmp.py Jpeg.py Png.py Tiff.py Xpm.py Dokud bude adresář Graphics podadresářem uvnitř adresáře našeho programu nebo bude uveden v cestě Pythonu, můžeme libovolný z těchto modulů importovat a používat. Musíme ale myslet na to, aby název zastřešujícího modulu (Graphics) nebyl stejný jako kterýkoliv z názvů nejvyšší úrovně ve standardní knihovně, jinak by došlo ke konfliktu názvů. (Na systému Unix stačí, když budou mít názvy našich modulů první písmeno velké, neboť všechny moduly standardní knihovny mají názvy s malými písmeny.) Náš modul můžeme importovat a používat takto: import Graphics.Bmp image = Graphics.Bmp.load(“bashful.bmp”) U krátkých programů můžeme používat kratší názvy, což lze v Pythonu provést dvěma malinko odlišnými způsoby. import Graphics.Jpeg as Jpeg image = Jpeg.load(“doc.jpeg”) Zde jsme importovali modul Jpeg z balíčku Graphics a řekli jsme Pythonu, že se na něj chceme místo plně kvalifikovaného jména Graphics.Jpeg odkazovat jen jako na Jpeg. from Graphics import Png image = Png.load(“dopey.png”) V tomto úryvku kódu importujeme modul Png přímo z balíčku Graphics. Při použití této syntaxe (from ... import) je modul Png přímo přístupný. Nikdo nás nenutí používat v našem kódu názvy používané v balíčku: from Graphics import Tiff as picture image = picture.load(“grumpy.tiff”) Zde používáme modul Tiff, který jsme ale ve svém programu přejmenovali na modul picture. V některých situacích je výhodné načíst všechny moduly balíčku pomocí jediného příkazu. K tomu je nutné upravit soubor __init__.py daného balíčku tak, aby obsahoval příkaz, který stanoví, které moduly se mají načíst. Tento příkaz musí přiřadit seznam názvů modulů do speciální proměnné __ all__. Zde je například požadovaný řádek pro soubor Graphics/__init__.py: __all__ = [„Bmp“, „Jpeg“, „Png“, „Tiff“, „Xpm“] Nic víc není třeba, i když do souboru __init__.py samozřejmě můžeme umístit libovolný další kód. Nyní můžeme použít další typ příkazu import: 199 from Graphics import * image = Xpm.load(„sleepy.xpm“) Syntaxe from balíček import * přímo importuje všechny moduly uvedené v seznamu __all__. Po provedení tohoto příkazu je přímo přístupný nejen modul Xpm, ale také všechny ostatní moduly. Jak jsme si řekli již dříve, tuto syntaxi lze aplikovat také na modul (tj. from modul import *) při tom se importují všechny funkce, proměnné a další objekty definované v zadaném modulu (kromě těch, jejichž název začíná podtržítkem). Pokud chceme mít kontrolu nad tím, co přesně se má při použití syntaxe from modul import * importovat, můžeme definovat seznam __all__ i v samotném modulu. V takovém případě importuje příkaz from modul import * pouze ty objekty, jejichž názvy jsou uvedeny v seznamu __all__. Dosud jsme si ukázali pouze jednu úroveň zanoření, Python nám však umožňuje vnořovat balíčky tak hluboko, jak potřebujeme. Můžeme tak mít v adresáři Graphics třeba podadresář Vector a v něm soubory modulů, například Eps.py a Svg.py: Graphics/ __init__.py Bmp.py Jpeg.py Png.py Tiff.py Vector/ __init__.py Eps.py Svg.py Xpm.py Adresář Vector se stane balíčkem v okamžiku, kdy do něj umístíme soubor __init__.py, a jak jsme si již řekli, tento soubor může být prázdný nebo může obsahovat seznam __all__ pro potřeby programátorů, kteří chtějí provést import pomocí příkazu from Graphics.Vector import *. Pro přístup k vnořenému balíčku vycházíme ze syntaxe, kterou jsme již používali: import Graphics.Vector.Eps image = Graphics.Vector.Eps.load(“sneezy.eps”) Plně kvalifikovaný název je poněkud delší, čemuž se snaží někteří programátoři zamezit tím, že se snaží udržovat hierarchie svých modulů docela ploché. import Graphics.Vector.Svg as Svg image = Svg.load(“snow.svg”) Pro modul můžeme vždy použít náš vlastní krátký název, jak jsme to provedli zde, i když se tím vystavujeme vyššímu riziku konfliktu názvů. Všechny importy, které jsme dosud používali (a které budeme používat i ve zbývající části knihy), se označují jako absolutní importy, což znamená, že každý námi importovaný modul je v některém Moduly a balíčky 200 Lekce 5: Moduly z adresářů uvedených v proměnné sys.path (nebo podadresářů, pokud název v příkazu import obsahuje jednu či více teček, které slouží v podstatě jako oddělovače v cestě). Při vytváření rozsáhlých balíčků s více moduly a adresáři je často užitečné importovat další moduly, které jsou součástí stejného balíčku. Například v souboru Eps.py nebo Svg.py můžeme získat přístup k modulu Png pomocí konvenčního nebo relativního importu: import Graphics.Png as Png from ..Graphics import Png Tyto dva úryvky kódu jsou ekvivalentní, protože oba přímo zpřístupňují modul Png uvnitř modulu, kde se používají. Všimněte si ale, že relativní importy, což jsou importy, které používají syntaxi from modul import s tečkami před názvem modulu (každá tečka představuje jeden krok směrem nahoru v hierarchii adresářů), můžeme použít pouze v modulech, které jsou uvnitř nějakého balíčku. Relativní importy usnadňují přejmenování zastřešujícího balíčku a uvnitř balíčků zamezují nechtěnému importování standardních modulů místo našich vlastních. Vlastní moduly Moduly jsou obyčejné soubory s příponou .py, a proto je lze vytvářet bez dalších formalit. V této části se podíváme na dva naše vlastní moduly. První modul TextUtil (v souboru TextUtil.py) obsahuje jen tři funkce: is_balanced(), která vrací hodnotu True, má-li zadaný řetězec vyvážené závorky nejrůznějších druhů, shorten() (viz dříve – strana 175) a simplify(), která dokáže z řetězce odříznout nežádoucí bílé místo a další znaky. Při probírání tohoto modulu se podíváme také na to, jak spouštět kód v dokumentačních řetězcích jako testy jednotek. Druhý modul CharGrid (v souboru CharGrid.py) uchovává znakovou mřížku a umožňuje do této mřížky „kreslit“ čáry, obdélníky a text a celou mřížku vykreslit do konzoly. V tomto modulu si ukážeme několik technik, se kterými jsme se dosud nesetkali a které jsou typické pro rozsáhlejší a komplexnější moduly. Modul TextUtil Struktura tohoto modulu (a většiny dalších) se odlišuje od struktury programu. Prvním řádkem je řádek shebang a poté zde máme komentáře (obvykle copyright a informace o licenci). Dále je obvykle uváděn řetězec s trojitými uvozovkami, který poskytuje přehled obsahu modulu často doplněný ukázkovými příklady – jedná se o dokumentační řetězec modulu. Zde je začátek souboru TextUtil. py (ovšem bez řádků s informacemi o licenci): #!/usr/bin/env python3 # Copyright (c) 2008-9 Qtrac Ltd. All rights reserved. „““ Tento modul nabízí několik funkcí pro manipulaci s řetězci. >>> is_balanced(“(Python (není (jako (lisp))))”) True >>> shorten(“Velká křižovatka”, 10) ‘Velká k...’ 201 >>> simplify(“ nějaký text s nadbytečnými mezerami “) ‘nějaký text s nadbytečnými mezerami’ “”” import string Dokumentační řetězec modulu je k dispozici programům (nebo dalším modulům), které tento modul importují, jako TextUtil.__doc__. Za dokumentačním řetězcem modulu následují importy a poté zbytek modulu. Funkci shorten() jsme již viděli, a proto ji zde nebudeme opakovat. A protože se spíše než na funkce zaměřujeme na moduly, ukážeme si kromě funkce simplify(), kterou si ukážeme celou včetně dokumentačního řetězce, pouze kód funkce is_balanced(). Takto vypadá funkce simplify() rozdělená na dvě části: def simplify(text, whitespace=string.whitespace, delete=““): r“““Vrátí text s vícenásobnými mezerami zredukovanými do jediné mezery Parametr whitespace je řetězec znaků, z nichž každý je považován za mezeru. Není-li parametr delete prázdný, měl by obsahovat řetězec, jehož znaky se vyhledají ve výsledném řetězci a odstraní. >>> simplify(“ tohle a také tamto”) ‘tohle a také tamto’ >>> simplify(“ Vejce a.s. ”) ‘Vejce a.s.’ >>> simplify(“ Vejce a.s. ”, delete=”,;:.”) ‘Vejce as’ >>> simplify(“ nesamohláskový “, delete=”aáeiouyý”) ‘nsmhlskv’ “”” Po řádku s příkazem def následuje dokumentační řetězec funkce se známou strukturou: na jednom řádku popis, prázdný řádek, podrobnější popis a pak několik příkladů napsaných tak, jako by byly zadávány interaktivně. Řetězce v uvozovkách jsou v dokumentačním řetězci, a proto je nutné buď potlačit v nich uvedená zpětná lomítka, nebo dokumentační řetězec uzavřít do trojitých uvozovek, což jsme udělali my. result = [] word = „“ for char in text: if char in delete: continue elif char in whitespace: if word: shorten() ¾ 175 Holé řetězce ¾ 72 Moduly a balíčky 202 Lekce 5: Moduly result.append(word) word = „“ else: word += char if word: result.append(word) return „ „.join(result) Seznam result používáme pro uchovávání „slov“, což jsou řetězce, jež nemají mezery nebo vyškrtnuté znaky (parametr delete). Zadaný text procházíme po jednotlivých znacích, přičemž přeskakujeme vyškrtnuté znaky. Narazíme-li na znak považovaný za bílé místo (parametr whitespace) a současně vytváříme slovo (proměnná word), přidáme toto slovo do seznamu result a nastavíme jej na prázdný řetězec. V opačném případě bílé místo přeskočíme. Jakýkoliv jiný znak přidáme do vytvářeného slova. Nakonec vrátíme jediný řetězec všech slov v seznamu result spojených jedinou mezerou. Funkce is_balanced() je zapsána podobným způsobem: nejdříve je řádek s příkazem def, poté dokumentační řetězec s jednořádkovým popisem, prázdný řádek, podrobnější popis, několik příkladů a pak samotný kód. Zde je kód bez dokumentačního řetězce: def is_balanced(text, brackets=“()[]{}<>“): counts = {} left_for_right = {} for left, right in zip(brackets[::2], brackets[1::2]): assert left != right, “znaky závorek se musejí lišit” counts[left] = 0 left_for_right[right] = left for c in text: if c in counts: counts[c] += 1 elif c in left_for_right: left = left_for_right[c] if counts[left] == 0: return False counts[left] -= 1 return not any(counts.values()) V této funkci sestavujeme dva slovníky. Klíči slovníku counts jsou otevírací znaky („(“, „[“, „{“ a „<“) a jeho hodnotami celá čísla. Klíči slovníku left_for_right jsou uzavírací znaky („)“, „]“, „}“ a „>“) a jeho hodnotami odpovídající otevírací znaky. Jakmile jsou slovníky připraveny, procházíme text znak po znaku. Jakmile narazíme na otevírací znak, zvýšíme odpovídající počítadlo (slovník counts). A podobně, jakmile narazíme na uzavírací znak, vyhledáme odpovídající uzavírací znak. Je-li počítadlo pro tento znak 0, znamená to, že jsme narazili na uzavírací znak bez odpovídajícího otevíracího znaku, a proto okamžitě vrátíme hodnotu False. V opačném případě snížíme příslušné počítadlo. Na konci by mělo mít každé počítadlo hodnotu 0, jsou-li všechny dvojice vyvážené, takže pokud je některé z nich nenulové, funkce vrátí hodnotu False. Jinak vrátí hodnotu True. 203 Až dosud bylo vše podobné jako v kterémkoliv jiném souboru .py. Pokud by byl soubor TextUtil. py programem, jistě by obsahoval několik dalších funkcí a na konci by bylo jediné volání některé z těchto funkcí, které by zahájilo zpracování. Avšak vzhledem k tomu, že se jedná o modul, který má být importován, jsou definované funkce dostačující. Nyní může libovolný program či modul importovat modul TextUtil a používat jej: import TextUtil text = “ záhadný hlavolam “ text = TextUtil.simplify(text) # text == ‘záhadný hlavolam’ Pokud chceme modul TextUtil zpřístupnit určitému programu, musíme soubor TextUtil.py umístit do stejného adresáře, ve kterém se nachází daný program. Pokud chceme modul TextUtil zpřístupnit všem svým programům, pak máme k dispozici několik možností. Jednou z nich je umístit modul do podadresáře s balíčky v rámci distribuce Pythonu. V systému Windows se obvykle jedná o adresář C:Python31Libsite-packages, v případě systémů Mac OS X a Unix však může být jeho umístění různé. Tento adresář se nachází v cestě Pythonu, takže libovolný v něm umístěný modul bude vždy nalezen. Druhá možnost spočívá ve vytvoření adresáře speciálně pro náš vlastní modul, který chceme používat ve všech svých programech, a v nastavení proměnné prostředí PYTHONPATH na tento adresář. Třetí možností je umístit modul do lokálního podadresáře site-packages. Jedná se o adresář, který je umístěn v cestě Pythonu a který má v systému Windows podobu %APPDATA% PythonPython31site-packages a v systému Unix (včetně Mac OS X) podobu ~/.local/lib/ python3.1/site-packages. Druhá a třetí možnost má tu výhodu, že máme náš kód oddělený od oficiální instalace. Mít modul TextUtil je sice skvělé, ale pokud jej bude používat spousta programů, pak si chceme být jisti, že funguje tak, jak je uvedeno. Jeden skutečně jednoduchý způsob spočívá v provedení příkladů v dokumentačním řetězci a v kontrole, zda obdržíme očekávané výsledky. To můžeme provést přidáním pouhých třech řádků na konec souboru .py tohoto modulu: if __name__ == „__main__“: import doctest doctest.testmod() Kdykoliv je nějaký modul importován, Python pro něj vytvoří proměnnou s názvem __name__ a uloží název modulu do této proměnné. Název modulu je prostý název souboru .py bez přípony. V tomto případě bude mít tedy proměnná __name__ po importu modulu hodnotu „TextUtil“, takže podmínka if nebude splněna, a proto se poslední dva řádky neprovedou. To znamená, že tyto tři řádky nemají prakticky žádný význam, je-li modul importován. Kdykoliv je nějaký soubor .py spuštěn, Python pro něj vytvoří proměnnou s názvem __name__ a nastaví ji na řetězec „__main__“. Pokud tedy spustíme soubor TextUtil.py jako by se jednalo o program, Python nastaví proměnnou __name__ na hodnotu „__main__“ a podmínka if se vyhodnotí na True, takže se poslední dva řádky provedou. Funkce doctest.testmod() použije introspektivní prvky Pythonu pro vyhledání všech funkcí v daném modulu a jejich dokumentačních řetězců a pokusí se provést všechny v nich umístěné úryvky kódu. Když modul takto spustíme, obdržíme výstup pouze v případě výskytu nějakých chyb. To Moduly a balíčky 204 Lekce 5: Moduly může být na první pohled znepokojující, protože to vypadá, že se nic nestalo. Pokud ale na příkazovém řádku předáme příznak -v, obdržíme výstup podobný následujícímu: Trying: is_balanced(“(Python (není (jako (lisp))))”) Expecting: True ok ... Trying: simplify(“ nesamohláskový “, delete=”aáeiouyý”) Expecting: ‘nsmhlskv’ ok 4 items passed all tests: 3 tests in __main__ 5 tests in __main__.is_balanced 3 tests in __main__.shorten 4 tests in __main__.simplify 15 tests in 4 items. 15 passed and 0 failed. Test passed. Místo množství vynechaných řádků je uveden výpustek. Jsou-li v modulu funkce (nebo třídy či metody), které nemají testy, pak jsou při použití volby -v taktéž uvedeny. Všimněte si, že modul doctest nalezl testy v dokumentačním řetězci modulu i v dokumentačních řetězcích funkcí. Příklady v dokumentačních řetězcích, které lze spouštět jako testy, se nazývají dokumentační testy (doctests). Je třeba poznamenat, že při psaní dokumentačních testů můžeme zavolat funkci simplify() a ostatní funkce bez nutnosti kvalifikace (k dokumentačním testům totiž dochází uvnitř samotného modulu). Vně tohoto modulu musíme za předpokladu, že jsme použili příkaz import TextUtil, používat kvalifikované názvy, například TextUtil.is_balanced(). V následující podčásti si ukážeme, jak provádět více důkladných testů – konkrétně testovací případy, v nichž očekáváme selhání, například neplatná data způsobující výjimky. (Testování se budeme podrobně věnovat v lekci 9.) Kromě toho se podíváme na několik dalších problémů, k nimž dochází při vytváření modulu, jako je inicializace modulu, ohled na rozdíly mezi platformami a zajištění, aby se při použití syntaxe from modul import * do programu či modulu skutečně importovaly pouze ty objekty, které chceme zveřejnit. Modul CharGrid Modul CharGrid uchovává v paměti znakovou mřížku. Nabízí funkce pro „kreslení“ čar, obdélníků a textu do mřížky a pro vykreslení této mřížky do konzoly. Zde jsou dokumentační testy z dokumentačních řetězců: 205 >>> resize(14, 50) >>> add_rectangle(0, 0, *get_size()) >>> add_vertical_line(5, 10, 13) >>> add_vertical_line(2, 9, 12, „!“) >>> add_horizontal_line(3, 10, 20, „+“) >>> add_rectangle(0, 0, 5, 5, „%“) >>> add_rectangle(5, 7, 12, 40, „#“, True) >>> add_rectangle(7, 9, 10, 38, „ „) >>> add_text(8, 10, „Tohle je náš modul CharGrid“) >>> add_text(1, 32, “Pěkně odporný”, “@”) >>> add_rectangle(6, 42, 11, 46, fill=True) >>> render(False) Funkce CharGrid.add_rectangle() přijímá nejméně čtyři argumenty: řádek a sloupec levého horního rohu a řádek a sloupec pravého spodního rohu. Znak použitý pro nakreslení obrysu lze zadat jako pátý argument a jako šestý argument logickou hodnotu signalizující, zda má být obdélník vyplněn (stejným znakem jako obrys). Při prvním zavolání předáme třetí a čtvrté argumenty rozbalením n-tice se dvěma prvky (šířka, výška) vrácené funkcí CharGrid.get_size(). Funkce CharGrid.render() ve výchozím nastavení vymaže obrazovku před vypsáním mřížky, čemuž lze zamezit předáním hodnoty False, jak jsme zde učinili také my. Níže je uvedena mřížka, která je výsledkem výše uvedených dokumentačních testů: %%%%%********************************************* % % @@@@@@@@@@@@@@@ * % % @Pěkně odporný@ * % % ++++++++++ @@@@@@@@@@@@@@@ * %%%%% * * ################################# * * ################################# **** * * ## ## **** * * ## Tohle je náš modul CharGrid ## **** * * ! ## ## **** * * ! | ################################# **** * * ! | ################################# * * | * ************************************************** Modul začíná stejným způsobem jako modul TextUtil: řádkem shebang, komentářem s copyrightem a informacemi o licenci a dokumentačním řetězcem, který popisuje modul a obsahuje výše uvedené dokumentační testy. Řádný kód pak začíná dvěma importy, z nichž prvním je modul sys a druhý modul subprocess. Modulu subprocess se budeme věnovat v lekci 10. Modul se řídí dvěma zásadami pro ošetření chyb. Několik funkcí definuje parametr char, jehož aktuálním argumentem musí být vždy řetězec obsahující přesně jeden znak. Porušení tohoto požadavku je považováno za fatální chybu programování, takže ke kontrole délky používáme příkazy assert. Moduly a balíčky 206 Lekce 5: Moduly Na druhou stranu předání čísla řádku či sloupce mimo rozsah je považováno za chybové, ale normální, a proto dojde k vyvolání vlastní výjimky. Nyní prostudujeme několik ilustrativních a klíčo vých částí kódu tohoto modulu, přičemž začneme vlastními výjimkami: class RangeError(Exception): pass class RowRangeError(RangeError): pass class ColumnRangeError(RangeError): pass Žádná z funkcí v modulu, která vyvolává výjimku, nikdy nevyvolá chybu RangeError, ale vždy vyvolá specifickou výjimku v závislosti na tom, zda hodnota zadaná mimo rozsah představuje řádek nebo sloupec. Avšak tím, že používáme hierarchii, dáváme uživatelům modulu možnost zachytit specifickou výjimku nebo zachytit kteroukoliv z nich zachycením bázové třídy RangeError. Všimněte si také, že uvnitř dokumentačních testů používáme názvy výjimek tak, jak jsou zde uvedeny, ale při importu modulu příkazem import CharGrid je samozřejmě nutné psát CharGrid.RangeError, CharGrid. RowRangeError a CharGrid.ColumnRangeError. _CHAR_ASSERT_TEMPLATE = („je nutné zadat jediný znak: ‘{0}‘ „ “je příliš dlouhý”) _max_rows = 25 _max_columns = 80 _grid = [] _background_char = „ „ Zde definujeme několik soukromých dat pro interní použití v modulu. Identifikátory začínají podtržítkem, takže pokud se modul importuje příkazem from CharGrid import *, neimportuje se žádná z těchto proměnných. (Další možností by bylo zřízení seznamu __all__.) Řetězec _CHAR_ASSERT_ TEMPLATE se používá v souvislosti s metodou str.format() pro vytvoření chybové zprávy v příkazech assert. K ostatním proměnným se vrátíme, jakmile se dostaneme k jejich použití v kódu. if sys.platform.startswith(„win“): def clear_screen(): subprocess.call([“cmd.exe”, “/C”, “cls”]) else: def clear_screen(): subprocess.call([“clear”]) clear_screen.__doc__ = “””Vymaže obrazovku pomocí příkazu pro vymazání obrazovky aktuálně používaného systému””” Prostředek k vymazání obrazovky je nezávislý na platformě. V systému Windows musíme spustit program cmd.exe s příslušnými argumenty a na většině unixových systémů spustíme program clear. Funkce subprocess.call() modulu subprocess umožňuje spuštění externího programu, takže ji můžeme použít k vymazání obrazovky způsobem vhodným pro používanou platformu. Řetězec sys.platform uchovává název operačního systému, na kterém daný program běží (např. „win32“ nebo „linux2“). Jeden ze způsobů pro překlenutí rozdílů mezi platformami tedy spočívá v definování jediné funkce: 207 def clear_screen(): command = ([“clear”] if not sys.platform.startswith(“win”) else [“cmd.exe”, “/C”, “cls”]) subprocess.call(command) Nevýhodou tohoto postupu je, že i když víme, že se platforma za běhu programu nezmění, provádíme kontrolu platformy při každém volání funkce. Abychom zamezili kontrole, na které platformě program běží, při každém zavolání funkce clear_ screen(), vytvořili jsme funkci clear_screen() s ohledem na používanou platformu jedenkrát při importu modulu a od tohoto okamžiku ji vždy používáme. To je možné díky tomu, že příkaz def je příkazem jazyka Python úplně stejně jako kterýkoliv jiný. Jakmile interpret dorazí k příkazu if, provede buď první, nebo druhý příkaz def, čímž se dynamicky vytvoří první nebo druhá funkce clear_screen(). Vzhledem k tomu, že tato funkce není definována uvnitř jiné funkce (nebo uvnitř třídy, jak uvidíme v následující lekci), jedná se o globální funkci, která je přístupná stejně jako kterákoli jiná funkce v modulu. Po vytvoření funkce explicitně nastaví její dokumentační řetězec. Díky tomu nemusíme psát stejný dokumentační řetězec na dvou místech a také vidíme, že dokumentační řetězec je jen jedním z atributů funkce. Mezi další atributy patří modul funkce a její název. def resize(max_rows, max_columns, char=None): “””Změní velikost mřížky, přičemž zahodí obsah a změní pozadí, nemá-li znak představující pozadí hodnotu None “”” assert max_rows > 0 and max_columns > 0, “příliš malé” global _grid, _max_rows, _max_columns, _background_char if char is not None: assert len(char) == 1, _CHAR_ASSERT_TEMPLATE.format(char) _background_char = char _max_rows = max_rows _max_columns = max_columns _grid = [[_background_char for column in range(_max_columns)] for row in range(_max_rows)] Tato funkce používá příkaz assert pro vynucení zásady, že pokus o změnu velikosti mřížky na velikost menší než 1 x 1 představuje chybu programování. Je-li zadán znak pro pozadí, použije se příkaz assert pro zajištění, že se jedná o řetězec s přesně jedním znakem. Není-li tomu tak, bude chybovou zprávou tvrzení text konstanty _CHAR_ASSERT_TEMPLATE se zástupným symbolem {0} nahrazeným zadaným řetězcem char. Naneštěstí musíme použít příkaz global, protože potřebujeme aktualizovat několik globálních proměnných uvnitř této funkce. Jak uvidíme v lekci 6, v tomto ohledu nám výrazně pomůže objektově orientovaný přístup. Proměnnou _grid vytváříme pomocí seznamové komprehenze uvnitř seznamové komprehenze. Použití replikace seznamu ([[char] * columns] *) by zde nefungovalo, protože vnitřní seznam bude sdílený (mělce zkopírovaný). Mohli bychom ale použít vnořené cykly for ... in: Seznamové kom- prehenze ¾ 120 Moduly a balíčky 208 Lekce 5: Moduly _grid = [] for row in range(_max_rows): _grid.append([]) for column in range(_max_columns): _grid[-1].append(_background_char) Tento kód je pravděpodobně méně srozumitelný než seznamová komprehenze a je také mnohem delší. Nyní se podíváme jen na jednu z kreslicích funkcí, abychom získali ponětí o tom, jak se takové kreslení provádí, protože naším hlavním zájmem je implementace modulu. Zde je funkce add_horizontal_ line() rozdělená na dvě části: def add_horizontal_line(row, column0, column1, char=“-“): “””Přidá do mřížky vodorovnou čáru s použití zadaného znaku >>> add_horizontal_line(8, 20, 25, “=”) >>> char_at(8, 20) == char_at(8, 24) == “=” True >>> add_horizontal_line(31, 11, 12) Traceback (most recent call last): ... RowRangeError “”” Dokumentační řetězec obsahuje dva testy, z nichž první by měl fungovat a druhý by měl vyvolat výjimku. Když v dokumentačních testech pracujeme s výjimkami, stačí uvést řádek „Traceback“, protože ten je vždy stejný a říká modulu doctest, že očekáváme výjimku, pak následuje výpustek znamenající další řádky (které se mění) a nakonec řádek s výjimkou, kterou čekáme, že obdržíme. Funkce char_at() patří mezi funkce tohoto modulu. Vrací znak na zadaném řádku a sloupci v mřížce. assert len(char) == 1, _CHAR_ASSERT_TEMPLATE.format(char) try: for column in range(column0, column1): _grid[row][column] = char except IndexError: if not 0 <= row <= _max_rows: raise RowRangeError() raise ColumnRangeError() Kód začíná stejnou kontrolou délky argumentu char jako ve funkci resize(). Místo explicitní kontroly argumentů row a column funguje funkce na základě předpokladu, že argumenty jsou platné. Pokud dojde k výjimce IndexError kvůli přístupu k neexistujícímu řádku nebo sloupci, výjimku zachytíme a vyvoláme místo ní příslušnou výjimku specifickou pro tento modul. Tento způsob programování se neformálně označuje jako „je snazší žádat o prominutí než o dovolení“ a ve srovnání se způsobem „dívej se, než skočíš“, kde se kontroly provádějí předem, je pro jazyk Python obecně považován za vhodnější. Spoléhání na vyvolání výjimky spíše než na předem provedenou kontrolu 209 je efektivnější v případech, kdy je výskyt výjimek vzácný. (Tvrzení se do oblasti „dívej se, než skočíš“ nepočítají, protože v kódu nasazeném do ostrého provozu by k nim nikdy nemělo dojít – proto jsou také často deaktivovány komentářem.) Téměř na konci modulu je za definicemi všech funkcí jediné volání funkce resize(): resize(_max_rows, _max_columns) Toto volání inicializuje mřížku na výchozí velikost (25 x 80) a zajistí, aby kód, který importuje modul, mohl tento modul bezpečně a okamžitě používat. Bez tohoto volání by importující program či modul musel při každém importu tohoto modulu zavolat funkci resize() pro inicializaci mřížky, což by si programátoři museli pamatovat a mohlo by to navíc vést k vícenásobným inicializacím. if __name__ == „__main__“: import doctest doctest.testmod() Poslední tři řádky modulu jsou standardní pro moduly, které používají modul doctest pro kontrolu svých dokumentačních testů. (Testování se budeme podrobně věnovat v lekci 9.) Modul CharGrid má jeden podstatný nedostatek: podporuje pouze jediný mřížkový znak. To se dá vyřešit například uchováváním kolekce mřížek v modulu, což by ale znamenalo, že uživatelé modulu budou muset při volání každé funkce uvádět klíč nebo index označující, na kterou mřížku odkazují. V případech, kdy je vyžadováno více instancí nějakého objektu, je lepším řešením vytvořit modul, který definuje třídu (vlastní datový typ), protože můžeme vytvářet tolik instancí třídy (objektů daného datového typu), kolik jen chceme. Další výhoda vytvoření třídy spočívá v tom, že bychom nemuseli pro ukládání (statických) dat třídy používat příkaz global. Způsob vytváření tříd si ukážeme v další lekci. Přehled standardní knihovny Pythonu Standardní knihovna Pythonu je obecně popisována jako „včetně baterií“. K dispozici je skutečně pestrá paleta funkčních prvků rozprostřených do přibližně dvou stovek balíčků a modulů. Ve skutečnosti bylo pro jazyk Python v průběhu let vyvinuto tolik vysoce kvalitních modulů, že pokud bychom je všechny začlenili do standardní knihovny, vzrostla by velikost distribučních balíčků Pythonu přinejmenším o jeden řád. Moduly umístěné do této knihovny jsou tedy spíše odrazem historického vývoje Pythonu a zájmů jeho hlavních vývojářů než jakkoli koordinovanou či systematickou snahou o vytvoření „vyvážené“ knihovny. Kromě toho se některé moduly ukázaly jako velmi obtížně udržovatelné v rámci knihovny – zvláště modul Berkeley DB – a proto byly z knihovny odebrány a nyní jsou udržovány nezávisle na ní. To znamená, že pro Python je k dispozici řada skvělých modulů třetích stran, které (bez ohledu na svoji kvalitu a užitečnost) nejsou součástí standardní knihovny. (Na dva takovéto moduly se později podíváme: moduly PyParsing a PLY použijeme v lekci 14 pro vytvoření analyzátorů.) V této části se podíváme na obsáhlejší přehled toho, co vše máme dispozici. Výklad rozdělíme dle tematických okruhů a vynecháme ty balíčky a moduly, které jsou silně specializované, a také ty, které jsou určeny pro konkrétní platformu. V mnoha případech si ukážeme malý příklad, abychom si mohli Přehled standardní knihovny Pythonu 210 Lekce 5: Moduly některé balíčky a moduly přímo „osahat“. U balíčků a modulů probíraných v jiných částech knihy jsou k dispozici křížové odkazy. Práce s řetězci Modul string nabízí několik užitečných konstant, mezi něž patří string.ascii_letters a string. hexdigits. Dále nabízí třídu string.Formatter, z níž můžeme odvodit třídu poskytující přizpůsobené formátování řetězců. * Modul textwrap lze použít k zalomení řádků textu na zadanou šířku a k minimalizaci odsazení. Modul struct poskytuje funkce pro zabalení, resp. rozbalení, čísel, logických hodnot a řetězců do (resp. z) objektů typu bytes s použitím jejich binární reprezentace. To může být užitečné při práci s daty, která se mají odeslat nebo přijmout z nízkoúrovňových knihoven napsaných v jazyku C. Moduly struct a textwrap používá program convert-incidents.py, na který se podíváme v lekci 7. Modul difflib nabízí třídy a metody pro porovnávání posloupností, jako jsou kupříkladu řetězce. Tento modul je schopen vytvořit výstup ve standardních formátech „diff “ i v jazyku HTML. Nejvýkonnějším modulem Pythonu pro práci s řetězci je modul re (regulární výrazy), který si podrobně prostudujeme v lekci 13. Třída io.StringIO nabízí objekty podobné řetězcům, které se chovají jako textový soubor umístěný v paměti. To může být užitečné, chceme-li pro zápis do řetězce použít stejný kód, který zapisuje do souboru. Příklad: Třída io.StringIO Python nabízí dva odlišné způsoby zápisu textu do souborů. První spočívá v použití metody write() objektu souboru a druhý v použití funkce print() s klíčovým argumentem file nastaveným na objekt souboru, který je otevřený pro zápis: print(„Chybová zpráva“, file=sys.stdout) sys.stdout.write(“Chybová zpráva ”) Oba řádky textu se vypíšou do objektu sys.stdout, což je objekt souboru, který představuje „standardní výstupní proud“. Tento proud je obvykle směrován do konzoly a od objektu sys.stderr („chybový výstupní proud“) se liší pouze v tom, že je ukládán do mezipaměti. (Python automaticky vytváří a otevírá proudy sys.stdin, sys.stdout a sys.stderr při spuštění programu.) Funkce print() přidává standardně nový řádek, což můžeme potlačit zadáním klíčového argumentu end, který nastavíme na prázdný řetězec. V některých situacích je užitečné mít možnost zachytit do řetězce výstup, který má jít do nějakého souboru. To lze realizovat pomocí třídy io.StringIO, jež poskytuje objekt, který je možné používat stejně jako objekt souboru, přičemž se všechna zapsaná data uchovají v řetězci. Objektu typu io.StringIO můžeme předat počáteční řetězec, takže z něj lze také číst jako ze souboru. * Výraz odvození třídy (nebo též specializace) se používá tehdy, když vytváříme vlastní datový typ (tj. třídu) založený na jiné třídě. Tomuto tématu se budeme plně věnovat v lekci 6. typ bytes ¾ 286 modul struct ¾ 288 211 Ke třídě io.StringIO můžeme přistupovat po importu modulu io a můžeme ji použít k zachycení výstupu určeného pro objekt souboru, jako je například sys.stdout: sys.stdout = io.StringIO() Pokud tento řádek umístíme na začátek programu za příkazy import, ale před jakékoliv použití proudu sys.stdout, odešle se veškerý text posílaný do proudu sys.stdout do objektu io.StringIO, který jsme vytvořili na tomto řádku a který nahradil standardní objekt souboru sys.stdout. Když se nyní provedou výše uvedené řádky print() a sys.stdout.write(), nepůjde jejich výstup do konzoly, ale do objektu io.StringIO. (Původní proud sys.stdout můžeme kdykoliv obnovit příkazem sys. stdout = sys.__stdout__.) Všechny řetězce, které byly zapsány do objektu io.StringIO, můžeme získat pomocí funkce io.StringIO.getvalue(), což v našem případě znamená voláním funkce sys.stdout.getvalue(). Její návratovou hodnotou je řetězec obsahující všechny řádky, které byly dosud zapsány. Tento řetězec můžeme vypsat nebo uložit do souboru protokolu nebo poslat přes síťové připojení jako jakýkoliv jiný řetězec. S dalším příkladem použití třídy io.StringIO se setkáme v pozdější části této lekce (strana 233). Programování na příkazovém řádku Pokud potřebujeme, aby náš program byl schopen zpracovat text, který mohl být přesměrován z konzoly nebo který mohl být v souborech uvedených na příkazovém řádku, pak můžeme použít funkci fileinput.input() modulu fileinput. Tato funkce prochází všechny řádky přesměrované z konzoly (jsou-li nějaké) a všechny řádky v souborech uvedených na příkazovém řádku jako spojitou posloupnost řádků. Modul umí prostřednictvím funkcí fileinput.filename() a fileinput. lineno() ohlásit aktuální název souboru a číslo řádku a dále dokáže pracovat s některými typy komprimovaných souborů. Pro práci s volbami příkazového řádku jsou k dispozici dva samostatné moduly. Modul getopt je populární, protože jej lze jednoduše používat a je již delší dobu součástí knihovny. Modul optparse je novější a výkonnější. Příklad: Modul optparse V lekci 2 jsme si popsali program csv2html.py. Ve cvičeních druhé lekce jsme navrhli rozšíření tohoto programu spočívající v přijímání argumentů z příkazového řádku („maxwidth“ jako celé číslo a „format“ jako řetězec). Modelové řešení (csv2html2_ans.py) má pro zpracování argumentů funkci o velikosti 26 řádků. Zde je začátek funkce main() programu csv2html2_opt.py, což je další verze programu, která pro zpracování argumentů příkazového řádku nepoužívá vlastní funkci, ale modul optparse: def main(): parser = optparse.OptionParser() parser.add_option(“-w”, “--maxwidth”, dest=”maxwidth”, type=”int”, help=(“maximální počet znaků, které lze “ “vypsat do řetězcových polí [výchozí: %default]”)) parser.add_option(“-f”, “--format”, dest=”format”, příklad csv2html. py ¾ 100 Přehled standardní knihovny Pythonu 212 Lekce 5: Moduly help=(“formát pro výpis čísel “ “[výchozí: %default]”)) parser.set_defaults(maxwidth=100, format=”.0f”) opts, args = parser.parse_args() Stačí pouze devět řádků kódu plus příkaz import optparse. Kromě toho nepotřebujeme explicitně řešit volby -h a --help, o něž se postará modul optparse, který vypíše vhodnou zprávu o použití programu pomocí textů z klíčových argumentů help, v nichž nahradí text „%default“ výchozí hodnotou příslušné volby. Dále si všimněte, že volby nyní používají standardní unixový styl krátkých a dlouhých názvů začínajících pomlčkou. Krátké názvy jsou vhodné pro interaktivní použití v konzole, zatímco dlouhé názvy jsou srozumitelnější při použití ve skriptech shellu. Například pro nastavení maximální šířky na 80 můžeme použít -w80, -w 80, --maxwidth=80 nebo --maxwidth 80. Po analýze příkazového řádku jsou volby k dispozici prostřednictvím atributů s příslušnými názvy, například opts.maxwidth a opts.format. Všechny argumenty, které nebyly zpracovány (obvykle názvy souborů), jsou v seznamu args. Pokud během analýzy příkazového řádku dojde k nějaké chybě, zavolá modul optparse funkci sys. exit(2). To vede k čistému ukončení programu, při němž operační systém obdrží jako návratovou hodnotu programu číslo 2. Návratová hodnota 2 standardně označuje chybu při použití, 1 označuje jakýkoliv jiný druh chyby a 0 znamená úspěch. Pokud funkci sys.exit() zavoláme bez argumentů, vrátí operačnímu systému hodnotu 0. Matematika a čísla Kromě vestavěných čísel typu int, float a complex nabízí knihovna čísla typu decimal.Decimal a fractions.Fraction. K dispozici máme tři numerické knihovny: math pro standardní matematické funkce, cmath pro matematické funkce pracující s komplexními čísly a random poskytující řadu funkcí pro generování náhodných čísel. Tyto moduly jsme si představili v lekci 2. Numerické abstraktní bázové třídy jazyka Python (tj. třídy, od nichž lze odvozovat další třídy, ale které nelze použít přímo) se nacházejí v modulu numbers. Tyto třídy jsou užitečné pro kontrolu, zda daný objekt x představuje libovolný druh čísla (např. isinstance(x, numbers.Number)) nebo zda je specifickým druhem čísla (např. isinstance(x, numbers.Rational) nebo isinstance(x, numbers.Integral)). V oblasti vědeckého a inženýrského programová ní přijde vhod balíček třetí strany s názvem NumPy. Tento modul nabízí vysoce efektivní n-dimenzionální pole, základní funkce z oblasti lineární algebry a Fourierových transformací a nástroje pro integraci kódu napsaného v jazyku C, C++ a Fortran. Balíček SciPy obsahuje modul NumPy, který rozšiřuje o moduly pro statistické výpočty, zpracování signálu a obrázků, genetické algoritmy a pro řadu dalších oblastí. Oba balíčky jsou k dispozici zdarma na adrese www.scipy.org. Datum a čas Moduly calendar a datetime nabízejí funkce a třídy pro práci s datem a časem. Jsou ovšem založeny na idealizovaném gregoriánském kalendáři, takže nejsou vhodné pro práci s předgregoriánskými kalendářními daty. Práce s datem a časem je velice složité téma. Používané kalendáře se v jednotli- 213 vých místech a časech liší, den netrvá přesně 24 hodi n, rok nemá přesně 365 dnů, odlišný je též letní čas i časová pásma. Třída datetime.datetime (ne však třída datetime.date) si sice dokáže poradit s časovými pásmy, ale ne sama od sebe. Tento nedostatek napravují moduly třetích stran, například dateutil z www.labix.org/python-dateutil a mxDateTime z www.egenix.com/products/python/ mx-Base/mxDateTime. Modul time pracuje s časovými známkami. Jedná se o prostá čísla, která uchovávají počet vteřin od začátku jisté epochy (1. 1. 1970 00:00:00 na Unixu). Tento modul lze použít pro získání časové známky aktuálního času na daném stroji v UTC (Coordinated Universal Time – koordinovaný světový čas) nebo jako místní čas, který bere v potaz letní čas. Dále jej lze použít pro vytváření nejrůznějším způsobem naformátovaných řetězců s datem, časem a datem i časem. Kromě toho dokáže analyzovat řetězce obsahující kalendářní data a časy. Příklad: Moduly calendar, datetime a time Objekty typu datetime.datetime se obvykle vytvářejí programově, kdežto objekty, jež uchovávají data a časy v UTC, se obvykle získávají z externích zdrojů, jako jsou časové známky souborů. Zde je několik příkladů: import calendar, datetime, time moon_datetime_a = datetime.datetime(1969, 7, 20, 20, 17, 40) moon_time = calendar.timegm(moon_datetime_a.utctimetuple()) moon_datetime_b = datetime.datetime.utcfromtimestamp(moon_time) moon_datetime_a.isoformat() # vrátí: ‘1969-07-20T20:17:40’ moon_datetime_b.isoformat() # vrátí: ‘1969-07-20T20:17:40’ time.strftime(„%Y-%m-%dT%H:%M:%S“, time.gmtime(moon_time)) Proměnná moon_datetime_a je typu datetime.datetime a uchovává datum a čas přistání vesmírné lodi Apollo 11 na Měsíci. Proměnná moon_time je typu in a uchovává počet vteřin od začátku epochy po přistání na Měsíci – toto číslo poskytuje funkce calendar.timegm(), která přijímá objekt typu time_struct získaný od funkce datetime.datetime.utctimetuple() a vrací počet vteřin reprezentovaných objektem typu time_struct. (K přistání na Měsíci došlo před unixovou epochou, a proto je výsledné číslo záporné.) Proměnná moon_datetime_b je typu datetime.datetime a vytváříme ji z celého čísla moon_time, abychom si ukázali převod z počtu vteřin od začátku epochy na objekt typu datetime.datetime.


       
Knihkupectví Knihy.ABZ.cz - online prodej | ABZ Knihy, a.s.
ABZ knihy, a.s.
 
 
 

Knihy.ABZ.cz - knihkupectví online -  © 2004-2018 - ABZ ABZ knihy, a.s. TOPlist