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

je prázdný
a
b

Kniha: Python 3 -- Výukový kurz - Mark Summerfield

Python 3 -- Výukový kurz
-15%
sleva

Kniha: Python 3 -- Výukový kurz
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č 586
+
-
rozbalKdy zboží dostanu
19,5
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 / resumé

Průvodce programováním v multiplatformním jazyce Python. Program napsaný v tomto jazyku lze spustit ve Windows i v unixových systémech.

Popis nakladatele

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í
Programování
Kniha je zařazena v kategoriích
Mark Summerfield - další tituly autora:
Zákazníci kupující knihu "Python 3 -- Výukový kurz" mají také často zájem o tyto tituly:
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 jenezá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é arobustní. 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ší částknihovny 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 jenepodstatné, 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 tehdy, když experimentujeme s různýmiimplementacemi 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 anakonec 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ýmyspecifikují 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 ktomuto 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 chcemezjistit, 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 sknihov

ní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 vyhnemekonflik

tů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řívepodí

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á posoubo

ru 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íPYTHONOPTIMI

ZE), 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 aspus

tit. 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ámeprázd

ný 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ž jenejpo

zoruhodně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 vsamot

né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řebypro

gramá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ímvysta

vujeme 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 jeobvykle 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ž nafunkce 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 naprázd

ný ř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-lipočíta

dlo 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 modulimpor

tovat 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.pyumís

tit do stejného adresáře, ve kterém se nachází daný program. Pokud chceme modul TextUtilzpří

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ářesiteackages. 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žepod

mí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__ anasta

ví 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éúryv

ky 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 napříkazo

vé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 čimeto

dy), 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(doc

tests). 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řípa

dy, 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 zdoku

mentač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éhohor

ní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íkvypl

ně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é, alenor

mální, a proto dojde k vyvolání vlastní výjimky.

Nyní prostudujeme několik ilustrativních a klíčový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 zachytitspecific

kou 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ípod

trží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á vdefino

vá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ě jakokterá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 zatributů 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 navelikost 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, budechybovou 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íchpromě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 vyvolatvýjim

ku. 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ýpustekzname

nají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íkon

troly 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ůsobpro

gramová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 bychomnemu

seli 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íchbalíč

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 čisystema

tickou 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 knihovnyode

brány a nyní jsou udržovány nezávisle na ní. To znamená, že pro Python je k dispozici řadaskvě

lých modulů třetích stran, které (bez ohledu na svoji kvalitu a užitečnost) nejsou součástístandard

ní 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ý sipodrobně prostudujeme v lekci 13.

Třída io.StringIO nabízí objekty podobné řetězcům, které se chovají jako textový souborumí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. (Pythonautomaticky 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í jakojaký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 jakospojitou 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 typykomrimovaný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íhod

notou 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ímatema

tické 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íalgeb

ry 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 dispozicizdar

ma 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 vjednotli


213

vých místech a časech liší, den netrvá přesně 24 hodin, 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ážepora

dit 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ám

ky 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ážeanalyzo

vat ř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’<



       
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