Styl zápisu kódu

O čem si budeme povídat?

Komentáře

V kapitole Další posloupnosti jsme se již o komentářích bavili. Nicméně, s komentáři lze dělat i další věci. O některých z nich se zde zmíním.

Informace o historii verzí

Bývá dobrým zvykem vytvořit na začátku každého souboru hlavičku. Měly by v ní být uvedeny takové detaily, jako je datum vytvoření, jméno autora, datum poslední změny, verze a obecný popis, týkající se obsahu. Často se uvádí seznam záznamů o změnách. Takový blok textu se uvádí formou komentáře:


# -*- coding: cp1250 -*- 
#############################
# Modul: Spam.py
# Autor: A.J.Gauld
# Datum: 1999/09/03
# Verze: Draft 0.4
u'''
Tento modul definuje třídu Spam, kterou můžeme kombinovat
s kteroukoliv jinou variantou třídy Jidlo, abychom vytvořili
zajímavé  pokrmy.
'''
###############################
# Log:
# 1999/09/01 AJG - Vytvoření souboru.
# 1999/09/02 AJG - Opravena chyba v cenové strategii.
# 1999/09/02 AJG - Tentokrát už jsem to udělal správně!
# 1999/09/03 AJG - Přidána grilovací metoda (viz požadavek #1234)
################################
import sys, string, food
...

Takže když soubor poprvé otevřete, měli byste na začátku uvidět souhrnnou informaci o tom, k čem soubor slouží, co se během času změnilo, kdo a kdy změnu provedl. Důležité je to zejména tehdy, když je soubor součástí týmového projektu, a vy potřebujete zjistit, koho se máte zeptat na věci kolem návrhu a změn. Existují nástroje pro správu verzí, které vám mohou pomoci vytváření takové dokumentace zautomatizovat, ale jejich vysvětlování přesahuje rámec této učebnice[1].

Povšimněte si, že jsem popis modulu vložil mezi dvě posloupnosti tvořené trojicí apostrofů. Jde o pythonovský trik známý jako dokumentační řetězec. Za chvíli si ukážeme, jak můžeme jeho obsah zpřístupnit prostřednictvím zabudované funkce help()

Poznámka překladatele: Proti anglickému originálu se tato ukázka liší ve dvou detailech. Na prvním řádku je uveden komentář ve speciálním tvaru:

# -*- coding: cp1250 -*- 

Tento řádek pythonovskému překladači říká, že zdrojový text byl zapsán s využitím znakové sady cp1250 (známé také pod normalizovanou zkratkou windows-1250). Pokud tedy překladač narazí na znak s kódem, který leží mimo definici kódu podle normy ASCII, může ověřit, zda jde o znak z uvedené sady (zda je v ní definován) a podle potřeby jej může převést do jiného kódování.

Druhá odlišnost spočívá v tom, že úvodní trojici apostrofů předchází písmeno u. To znamená, že se dokumentační řetězec v době překladu uloží v takzvaném unicode kódování. Zjednodušeně řečeno jde o to, že se pro jeden znak vyhradí větší prostor, než pouhý jeden bajt. To umožní jedním kódem rozlišit mnohem více různých znaků. Typicky se pro uložení používají dva bajty, které umožňují rozlišit přibližně 65 tisíc možností (různých znaků). Při 8bitovém kódování znaků se dá rozlišit pouze 256 možností, přičemž mnohé mají již historickými okolnostmi pevně přidělený význam.

Praktický dopad z obecného pohledu je ten, že při zápisu řetězců v kódování unicode vystačíme pro všechny nám blízké (i méně blízké) jazyky s jediným systémem kódování znaků. Pro budoucí verze Pythonu se počítá s tím, že se unicode stane jediným používaným způsobem kódování řetězců uvnitř interpretu.

Praktický dopad z pohledu běhu našeho programu je ten, že v případě důsledného používání kódování unicode budou zobrazované texty vypadat stejně při běhu v anglicky mluvících zemích, v Německu, v Řecku, v Rusku... Případná databáze aplikace bude moci dohromady bez omezení kombinovat texty v libovolném jazyce. V jednom řetězci můžeme uvést anglický text, jeho český ekvivalent, ruskou podobu zapsanou azbukou, atd.

Uvědomte si, že při zápisu zdrojového textu v 8bitovém kódování musí dojít k převodu kódování na unicode. To je možné pouze tehdy, když se ví, jaké 8bitové kódování je při zápisu zdrojového textu použito. Právě proto je první řádek velmi důležitý. Pokud není uveden, pak si novější verze Pythonu budou stěžovat v případě, že naleznou znak s kódem větším, než 127.

Zakomentování nadbytečného kódu

Tato technika se často používá k izolaci chybného úseku kódu. Předpokládejme například, že program čte nějaká data, zpracovává je, tiskne výstup a potom ukládá výsledek zpět do datového souboru. Pokud výsledky neodpovídají našemu očekávání, pak bychom rádi zabránili zpětnému ukládání (chybných) dat, abychom tento soubor neporušili. Odpovídající kód bychom mohli jednoduše odstranit. Méně radikální přístup spočívá v tom, že dané řádky jednoduše změníme na komentář, například takto:

data = ctiData(soubor)
for polozka in data:
    vysledky.pridej(vypoctiVysledek(polozka))
tiskniVysledky(vysledky)
######################
# Následující kód zakomentujeme až do doby,
# kdy bude opravena chyba ve funkci vypoctiVysledek,
# která vyhodnocuje výslednou položku.
#
# for polozka in vysledky:
#     soubor.ulozit(polozka)
######################
print 'Konec programu'

Jakmile je chyba odstraněna, můžeme jednoduše smazat komentářové značky a kód se tím stane znovu aktivním. Některé nástroje pro editaci zdrojových textů, včetně IDLE, definují v menu akce pro zakomentování vybraného úseku kódu, případně k jeho pozdějšímu odkomentování.

Poznámka překladatele: U některých editorů lze k této akci využít vlastností editace sloupcových bloků. Například volně dostupný editor jEdit vám umožní definovat sloupcový blok o nulové šířce. Jakmile začnete něco psát, začne se chovat jako sada pod sebou umístěných kurzorů pro vepisování textu — vše se opisuje na všech řádcích v místě, kde je sloupcový blok označen. Vepsáním jediného znaku '#' tedy zakomentujete celý úsek, před který jste takový sloupcový blok umístili.

Dokumentační řetězce

Komentáře, které dokumentují, co daná funkce nebo modul dělají, můžeme použít ve všech jazycích. Ale jen pár jazyků — jako je Python a Smalltalk — jdou o krok dále a umožňují nám dokumentovat funkci takovým způsobem, že mohou být použity v integrovaném prostředí pro realizaci interaktivní nápovědy během programování. V jazyce Python toho dosáhneme použitím """dokumentačních řetězců""":

class Spam:
    """Maso určené ke kombinování s ostatními potravinami.
 
    Ve spojení s jinými potravinami se dají vytvořit zajímavá jídla.
    Obsahuje mnoho živin a může být připraveno mnoha různými způsoby."""
    
    def __init__(self):
        ...

print Spam.__doc__

Poznámka překladatele k českým znakům v ukázce: Pokud si bude Python stěžovat, že používáte nepovolené znaky, zkuste je nahradit česká písmenka ceskymi (bez diakritiky). K tomuto problému se ještě vrátíme na jiných místech.

Poznámka: Dokumentační řetězec můžeme vytisknout jako obsah speciální proměnné __doc__. Dokumentační řetězce mohou být definovány pro moduly, funkce, třídy a metody tříd. Vyzkoušejte například:

import sys
print sys.__doc__

Od verze 2.2 definuje Python i zabudovanou funkci help(), která vyhledá a zobrazí veškerou dostupnou dokumentaci k objektu, který je zadán parametrem. Pokud například chceme něco zjistit o sys.exit, můžeme na pythonovském vyzývacím řádku napsat:

>>> import sys
>>> help(sys.exit)
Help on built-in function exit:

exit(...)
    exit([status])
    
    Exit the interpreter by raising SystemExit(status).
    If the status is omitted or None, it defaults to zero (i.e., success).
    If the status is numeric, it will be used as the system exit status.
    If it is another kind of object, it will be printed and the system
    exit status will be one (i.e., failure).

>>>

Pokud tento příkaz napíšete v interaktivním režimu Pythonu v DOSovém okně a výpis zabírá více, než jednu obrazovku, zobrazuje se další text až po stisku mezerníku. Pokud chcete režim výpisu nápovědy ukončit, stiskněte 'q' (jako quit). Pokud příkaz help napíšete v interaktivním režimu v IDLE nebo v jiném integrovaném prostředí, pak se výpis po stránce nezastavuje. Vypíše se jednoduše celý text, protože se ke všem řádkům výpisu můžete dostat pomocí posouvací lišty na pravé straně okna.

Poznámka překladatele: Výše zmíněné chování při výpisu nápovědy příkazem help() si můžete vyzkoušet například na dlouhém výpisu k modulu array:

>>> import array
>>> help(array)

Příkaz help() není v Pythonu nijak utajen. Spíše naopak. Po interaktivním spuštění Pythonu verze 2.3.4 můžete číst výzvu k tomu, že máte napsat "help":

Python 2.3.4 (#53, May 25 2004, 21:17:02) [MSC v.1200 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Když napíšeme help bez závorek, Python nám napoví:

>>> help
Type help() for interactive help, or help(object) for help about object.
>>>

Odtud vidíme, že zabudovanou funkci help() (tj. se závorkami) můžeme volat i bez parametrů. V takovém případě vstoupíme do interaktivního režimu nápovědy. Povšimněte si, že výpis končí vyzývací posloupností 'help>':

>>> help()

Welcome to Python 2.3!  This is the online help utility.

If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://www.python.org/doc/tut/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".

To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics".  Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".

help> 

Jak nám Python napovídá, interaktivní režim můžeme ukončit napsáním slova quit (stačí i jediné písmeno q):

help> quit

You are now leaving help and returning to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)".  Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
>>> 

Jak vidíte, Python nás informuje o tom, že se dostáváme opět do interaktivního příkazového režimu.

Odsazování bloku

Jde o jedno z nejžhavějších témat, o kterém se mezi programátory debatuje. Skoro se zdá, že každý programátor má svou vlastní představu o nejlepším způsobu odsazování kódu. Byly vypracovány některé studie, které ukazují, že přinejmenším některé z faktorů mají význam větší, než kosmetický — usnadňují nám pochopení kódu.

Důvody pro debatu jsou jednoduché. Ve většině programovacích jazyků má odsazování čistě kosmetický význam; jde o pomůcku pro čtenáře. (Pokud se týká jazyka Python, zde je odsazování nutné a má zásadní vliv na správnou funkčnost programu!) Takže například:

<script type="text/vbscript">
For I = 1 To 10
    MsgBox I
Next
</script>

Tento zápis je interpretem jazyka VBScript chápán jako naprosto shodný se zápisem:

<script type="text/vbscript">
For I = 1 To 10
MsgBox I
Next
</script>

Zápis s odsazením se nám prostě lépe čte.

Podstatné je, že odsazování by mělo odrážet logickou strukturu kódu. Mělo by vizuálně odrážet tok řízení v programu. Tady nám pomáhá, když bloky kódu vypadají jako bloky (v geometrickém smyslu)

XXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXX

… což se čte lépe než následující zápis…

XXXXXXXXXXXXXXXXXXXXX
  XXXXX
    XXXXXXXXXXXX
    XXXXXXXXXXXX
    XXXXXXXXXXXX
  XXXXX

protože je lépe vidět, co k bloku patří. Studie prokázaly výrazné zlepšení srozumitelnosti v případech, kdy odsazování odráží strukturu logických bloků. V malých příkladech, se kterými jsme se dosud setkali, se to nemusí zdát důležité. Ale jakmile začnete psát programy se stovkami a tisíci řádků, důležitost vhodného odsazování výrazně vzroste.

Jména proměných

Jména proměných, která jsme dosud používali, nevyjadřovala žádný význam. Důvodem bylo především to, že jsme je použili jen pro ilustraci použitých technik. Obecně je ale mnohem lepší, kdy jména vašich proměnných vyjadřují to, co jimi chcete reprezentovat. Například v naší ukázce programu pro generování tabulek násobků jsme použili proměnnou nasobitel, která určovala, která z tabulek se tiskne. Je to určitě smysluplnější, než kdybychom použili jenom n — fungovalo by to stejně a ušetřili bychom si psaní.

Jde o kompromis mezi srozumitelností a úsilím. Obecně se dá říct, že nejlepší je volit krátká, ale výstižná jména. Příliš dlouhá jména by nás mátla a opakované zápisy jejich správné podoby by byly obtížné. Místo proměnné nasobitel jsme mohli použít například proměnnou tabulka_kterou_tiskneme, ale takové jméno je mnohem delší a přitom není o nic jasnější.

Ukládání vašich programů

Použití příkazového řádku interpretu jazyka Python v interaktivním režimu (>>>)je velmi vhodné pro rychlé vyzkoušení nápadů. Ale jakmile činnost interpretu ukončíme, vše je ztraceno. Z dlouhodobého hlediska chceme umět napsat programy, které budeme opakovaně spouštět. Dosáhneme toho vytvořením textového souboru s připonou .py. (Jde pouze o konvenci — můžete použít jakoukoliv jinou příponu. Ale podle mého názoru je dobré takové konvence dodržovat.) Poté můžeme program spustit tím že na příkazový řádek operačního systému napíšeme:

$ python spam.py

kde spam.py je jméno našeho souboru s pythonovským programem a '$' je vyzývacím znakem příkazového řádku operačního systému. (Znak '$' se používá v unixových systémech. V systémech MS Windows se jako vyzývací znak používá '>'.)

Další výhoda ukládání programů do souborů spočívá v tom, že můžete opravovat chyby, aniž byste museli znovu napsat celý fragment nebo, to se týká IDLE, aniž byste museli kurzor přesunovat nahoru, nad chybová hlášení za účelem opakovaného výběru kódu. IDLE umožňuje otevření souboru pro editaci a jeho současné spuštění prostřednictvím menu Edit|Run module.

Od této chvíle v příkladech obvykle nebudu ukazovat vyzývací posloupnost >>>. Budu předpokládat, že program zapisujete do souboru a soubor spouštíte buď z IDLE nebo z příkazového řádku shellu nebo DOSového okna, což je můj oblíbený způsob.

Poznámka pro uživatele systému Windows

Pod Windows lze v aplikaci Průzkumník nastavit vazbu pro soubory s příponou .py tak, abyste mohli pythonovské programy spouštět jednoduše poklepáním na ikonu souboru. Instalátor systému Python by to měl udělat již dříve za vás. Můžete si to ověřit tím, že naleznete nějaký soubor s příponou .py a zkusíte ho takto spustit. Pokud k jeho spuštění dojde (a to i v případě, že se objeví pythonovské chybové hlášení), je vazba pro příponu nastavena. Problém, se kterým se v takovém případě pravděpodobně setkáte, spočívá v tom, že se program spustí v DOSovém okně, které se po dokončení programu hned zavře. Někdy to proběhne tak rychle, že si vytvoření DOSového okna stěží všimnete. Problém lze vyřešit takto:

Poznámka pro uživatele systému Unix

Systém Unix se k pythonovským souborům chová jako k ostatním skriptům, proto by první řádek pythonovského skriptového souboru měl obsahovat posloupnost #! následovanou plnou cestou k aplikaci python — do místa, kde ji máte nainstalovanou ve vašem systému. Plnou cestu můžete nalézt tak, že na příkazovém řádku shell napíšete:

$ which python

Na mém systému to pak vypadá takto:

#! /usr/local/bin/python

To vám umožní soubor spouštět aniž byste museli přímo volat Python. Souboru ještě musíte příkazem chmod přidělit příznak spustitelnosti, ale jsem si jistý, že tohle jste již věděli:

$ spam.py

Na moderních unixových systémech (včetně všech distribucí systému Linux) můžete dokonce použít ještě šikovnější trik, kdy zápis cesty k aplikaci můžeme nahradit zápisem /usr/bin/env/python takto:

#! /usr/bin/env/python

Tím se zajistí automatické vyhledání Pythonu mezi cestami v path. Jediná nepříjemnost, se kterou byste se pak mohli potkat, by nastala v případě, kdy máte v systému nainstalovaných více verzí Pythonu a skript funguje pouze při použití jedné z nich. (Může například využívat zcela nový jazykový rys, který je podporován jen v poslední verzi Pythonu.) V takovém případě je výhodnější zůstat u použití plné cesty k aplikaci.

Řádek #! nezpůsobí žádný problém ani při spouštění pod Windows nebo Mac. Vypadá prostě jako komentář. To znamená, že tento řádek mohou do svých skriptů uvádět i uživatelé systémů Windows nebo Mac pokud předpokládají, že by jejich skript mohl být užitečný a použitelný i v unixových systémech.

VBScript a JavaScript

Pokud chcete používat pouze VBScript a JavaScript, pak výše uvedený text můžete ignorovat. Vaše programy jste museli ukládat do souborů již dříve, protože to byla jediná možnost, jak je spustit.

Zapamatujte si

Pokud vás napadne, co by se dalo na překladu této kapitoly vylepšit, zašlete e-mail odklepnutím Tím budou do dopisu automaticky vloženy informace o tomto HTML dokumentu.

$Id: cztutstyle.html,v 1.9 2005/03/09 21:09:24 petr Exp $