previous up next hi end end

7. Soubory a moduly

  1. Soubory
  2. Datový typ bytes, bytearray
  3. Práce s textovými soubory
  4. Práce s binárními soubory
  5. Adresáře
  6. Vytváření a import modulů
  7. Modul sys a proměnná argv
  8. Modul pydoc
  9. Glosář
  10. Cvičení

7.1 Soubory

Textový soubor je počítačový soubor (stream), složený ze znaků tisknutelných - které slouží k vyjádření obsahu a netisknutelných (řídících) - které slouží pro označení mezer, tabulátorů, konce řádku aj.

Cokoli máme v počítači uloženo v paměti na disku, je uloženo v binárním formátu. Při otevírání souboru v nějaké aplikaci (například v textovém editoru či v Průzkumníku souborů) je binární formát automaticky převeden do formátu, který lze číst nebo prohlížet. V prostředí Pythonu nám práci s binárním formátem umožňuje existence datového typu bytes.

Při práci s textovým i binárním souborem musíme znát dvě věci - kde je soubor uložen a v jakém kódování (UTF-8, ASCII, ...) byl textový soubor uložen, neboli převeden do binárního formátu.
Před vlastní manipulací s obsahem souboru musíme soubor otevřít funkcí open(~), po ukončení úprav musíme soubor zavřít funkcí close().


7.2 Datový typ bytes, bytearray

Entita typu bytes (bytearray) je neměnná (měnitelná) sekvence bitů. Tato binární serializace je nutná pro uložení dat do paměti počítače nebo pro jejich transport po síti.
Mnohá data (obrázky, zvuk, text) lze serializovat (kódovat - encode) na bytes či deserializovat (dekódovat - decode) z bytes s použitím vhodného protokolu, jako je PNG, WAW, JSON nebo UTF-8, ASCII, cp1250 aj.
Prezentaci objektu ve formátu bytes, bytearray lze provést dvojím způsobem a to literálovou formou nebo s použitím příslušných funkcí či metod.

Literálový zápis objektu typu 'bytes' vytvoříme předznamenáním literálu řetězce písmenem b:

>>> asci = "Za horami, za lesy"           # kódování ASCII
>>> utf8 = "Až na severní pól"            # kódování UTF-8

Literálová forma:
>>> lba = b'Za horami, za lesy'; lba
b'Za horami, za lesy'                  
>>> lbu = b'Až na severní pól'; lbu       # pro řetězce nelze použít
SyntaxError: bytes can only contain ASCII characters.
>>> lb = b'(1, 2, 237)'; lb
b'(1, 2, 237)'
>>>lbn = b'range(12)'; lbn, type(lbn)
(b'range(12)' <class 'bytes'>) 

Co k tomu dodat? Serializaci stringu literálovou formou lze provést jen tehdy když se formátovaný řetězec skládá pouze ze znaků, obsažených v kódování ASCII.

Převod řetězce na bytes pomocí funkce a metody

Převod na bytes lze provést pro všechny myslitelné znaky, ovšem patřičně ošetřené s použitím takzvané escape sekvence. Tu za nás při tvorbě objektu provede funkce bytes či bytearray, přijímající tři nepovinné parametry:

bytes([source[, encoding[, errors]]])
>>> bytes(asci, "utf-8")                    # kódování je povinné
b'Za horami, za lesy'          
>>> bytes(utf8, "utf-8")
b'A\xc5\xbe na severn\xc3\xad p\xc3\xb3l'   # kombinace s 'escape sekvencí' 

Znaky které patří do ASCII, jsou uvedeny normálně, znaky, které nejsou součástí ASCII, jsou vyjádřeny hexadecimálními čísly za zpětnými lomítky (což je ta escape sekvence). Na příkladě také vidíme, že znaky ž, í, ó jsou v UTF-8 vyjádřeny dvěma kódovými čísly.

Vedle funkce bytes(~) existuje také metoda encode(string, "coding"). Údaj o kódování lze vypustit, pokud souhlasíme s implicitně nastaveným utf-8. Pokud chceme použít jiné kódování, musíme jej uvést:

>>> "píšež".encode()                      # kódování utf-8 implicitně
b'p\xc3\xad\xc5\xa1e\xc5\xbe'             
>>> "píšež".encode('utf-16')
b'\xff\xfep\x00\xed\x00a\x01e\x00~\x01'   # jsme poněkud někde jinde 

Převod bytes na řetězce

Při deserializaci (decoding) objektu typu bytes na řetězec musíme vědět, jaké kódování bylo při serializaci použito. To není vždy spolehlivě zjistitelné. Jeden způsob je popsán zde.
Pro převod použijeme metodu bytes.decode("coding"):
>>> bczstr = bytes("píšež", "utf-8")       # objekt typu bytes     
>>> bczstr.decode("utf-8")                 # kódování je povinné
'píšež' 

Lze také použít funkci str(bytes-obj, 'coding'):

>>> str(bczstr, "utf-8")                   # kódování je povinné
'píšež' 

Bytearray

Jediná odlišnost typu bytearray od typu bytes spočívá v tom, že bytearray podporuje měnitelnost.

>>> bs = bytes('souznění', 'utf-8'); bs        # objekt typu bytes
b'souzn\xc4\x9bn\xc3\xad'                      # nejde změnit
>>> ba = bytearray('souznění', 'utf-8'); ba       
bytearray(b'souzn\xc4\x9bn\xc3\xad')           # objekt typu bytearray
>>> ba[0] = 108                                # ord("l") = 108
>>> aba = bytearray("b", "utf-8") + ba; aba
bytearray(b'blouzn\xc4\x9bn\xc3\xad')
>>> str(aba, "utf-8")                          # převod na řetězec
'blouznění'

Jak vidno, objekt typu bytearray je vlastně objekt typu bytes, dekorovaný slovem bytearray.


7.3 Práce s textovými soubory

Otevření souboru funkcí open(~) vytváří souborový objekt (file_object), označovaný také jako stream:

file_object = open('file_name' [, 'access_mode'] [, coding] [, buffering])
                        # hranaté závorky označují nepovinný argument
file_name   název souboru včetně přípony
access_mode přístupový režim pro manipulaci se souborem
coding      žádané kódování např. coding="utf-8" či "cp1250" (nebo "ASCII")
buffering   nastavení velikosti vyrovnávací paměti - nebudeme používat
 

Přístupové režimy

Přístupový režim (mód) určuje, jakou manipulaci lze s otevřeným souborem provádět. Není-li režim zadán, je implicitně nastaven režim read. Zároveň určuje polohu interního 'ukazovátka', označujícího počáteční místo pro případnou manipulaci.

'r' (read)  pouze pro čtení; ukazovátko na začátku souboru
'w' (write) pouze pro psaní; ukazovátko na začátku souboru; přepisuje existující soubor, neexistující vytvoří 
'a'  (append) pro připojení textu; ukazovátko na konci existujícího souboru; neexistující soubor vytvoří
'rb', 'wb', 'ab'  totéž co 'r', 'w', 'a' ale pro binární soubor
'r+', 'rb+' pro čtení i psaní - pozor, přepisuje existující soubor
Těmto režimům je lépe se vyhnout:
'w+', 'wb+' pro psaní i čtení; přepisuje existující soubor, neexistující vytvoří
'a+', 'ab+' pro připojení textu i čtení; neexistující soubor vytvoří  

Manipulaci se souborovým objektem (streamem) si ukážeme na několika příkladech.

>>> myfile = open('test.dat', 'w')       # zde vytváříme nový soubor
>>> print(myfile)
<_io.TextIOWrapper name='test.dat' mode='w' encoding='cp1250'>

Příkaz print nám vrátil typ objektu, jméno souboru, použitý mód a kódování souboru.

Neexistuje-li soubor se jménem test.dat, bude vytvořen v aktuálním adresáři. Jestliže takový soubor v režimu "w" již existuje, bude jeho text nahrazen textem, který případně zapíšeme.

Pro vkládání dat do souboru použijeme metodu souborového objektu write. Pokud proceduru 'write' provádíme v jedné seanci opakovaně, k přepisu stávajícího textu nedojde. K přepisu dojde u nově aktivovaného souborového objektu.

>>> myfile.write("Nyní je čas")                    --> 11 znaků
>>> myfile.write(" zavřít soubor.")                --> 15 znaků

Zavření souboru říká systému, že jsme skončili zapisování a soubor je možné zavřít:

>>> myfile.close()

Nyní můžeme soubor opět otevřít, tentokrát pro čtení a načíst jeho obsah do řetězce v našem programu.

>>> myfile = open('test.dat', 'r')

Pokusíme-li se otevřít soubor, který neexistuje, dostaneme chybové hlášení:

>>> myfile = open('test.cat', 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'test.cat'

Pokusíme-li se otevřít soubor s českým textem, dostaneme toto chybové hlášení:

>>> fruten = open("cz_fruits.txt")
>>> next(fruten)
...
UnicodeDecodeError: 'charmap' codec can't decode 
byte 0x88 in position 27: character maps to <undefined>
... kodek 'charmap' neumí dekódovat bajt 0x88 (136) na pozici 27

Náprava spočívá v tom, že zadáme rovněž parametr 'coding':

>>> fruten = open("cz_fruits.txt", encoding="utf-8")
>>> next(fruten)

Metoda read bez argumentů načte celý obsah do jediného řetězce:

>>> print(myfile.read())
Nyní je čas zavřít soubor.
>>> myfile.close()

Metoda read může také přijmout argument, který říká kolik znaků má být čteno:

>>> myfile = open('test.dat')       # nutno znovu "naládovat"
>>> print(myfile.read(7))
Nyní je

Zadáme-li číslo větší než je počet znaků v souboru, vrátí read jen zbývající znaky. Došlo-li se na konec souboru, vrátí read prázdný řetězec:

>>> print(myfile.read(726))
 čas zavřít soubor.
>>> print(myfile.read())
                                    # nemáme "naládováno"
>>>

Podivné chování metody read() je důsledkem toho, že souborový objekt je také iterátorem a když opět nahlédneme do kap. 4.6, tak si připomeneme, že iterátorový objekt vlastní funkci next(), která posouvá interní index objektu a jejíž použití si nyní opět ukážeme.
Otevřeme si soubor unsorted_fruits.txt a jeho obsah vložíme do souboru "fruits.txt", který vložíme do složky, v níž následně aktivujeme konzolu interpreta Pythonu. Ze souboru vytvoříme souborový objekt (neboli iterátor):

>>> fru = open("fruits.txt")
>>> next(fru)
'papaya\n'                 # \n označuje konec řádku
>>> next(fru)
'kiwifruit\n'
...
>>> next(fru)
StopIteration              # vyčerpali jsme celý seznam
>>> fru.read()            
''                         # potvrzeno, vrabci vyklobali

Potřebujeme-li z objektu znovu číst, musíme přesunout jeho ukazovátko (pointer) na začátek - a to nejlépe metodou seek(offset[, from]):

>>> fru.seek(0, 0)          # jsme opět na začátku!
>>> print(fru.readline())   # vrátí obsah aktuálního řádku
papaya
>>> print(fru.readlines())  # vrátí seznam řetězců, obsahujících zbývající řádky
papaya
>>> print(fru.tell())       # sdělí pozici ukazovátka
8
>>> fru.close()             # zavřít objekt se vřele doporučuje

Metoda readline() přečte všechny znaky z prvního řádku včetně znaku newline:

Metoda readlines() vrátí všechny zbyvající řádky jako seznam řetězců:

Automatické zavření objektu nám zajistí použití idiomu with :

with open("week.txt", "w") as dny:
   dny.write("pondělí\núterý\nstředa\nčtvrtek\npátek\nsobota\nneděle\n")

Soubor je zavřen, pro novou manipulaci jej musíme opět otevřít

with open("week.txt") as ven:
   for line in ven.readlines():
      print(line, end='') 

Skript vytvořil v aktuálním adresáři soubor 'week.txt' (pokud již neexistoval) a vložil do něho dny týdnu. Při dalším otevření souboru (implicitně v režimu 'read') jsme předepsali jejich postupný výtisk v konzole. Po ukončení práce se soubor sám zavřel.
Ověřte si to v aplikaci IDLE Pythonu.

Následující funkce kopíruje soubor tak, že přečte a zapíše nejvíce 50 znaků najednou. První argument je jméno původního souboru, druhý argument je jméno nového souboru:

Soubor copy_file.py

def copy_file(oldfile, newfile):       # názvy souborů v uvozovkách
    infile = open(oldfile, 'r')
    outfile = open(newfile, 'w')
    while True:
        text = infile.read(50)
        if text == "":
            break
        outfile.write(text)
    infile.close()
    outfile.close()
    return

Tato funkce cyklicky čte 50 znaků z infile a zapisuje je do outfile až je dosaženo konce a text je prázdný řetězec, čímž se vyvolá provedení příkazu break.
Soubor copy_file.py uložte do složky, kde máte soubor oldfile. Používáte IDLE Pythonu.


7.4 Práce s binárními soubory

Soubory, které obsahují fotografie, obrázky, videa, zvukový záznam, zipové a spustitelné soubory - se nazývají binární soubory. Tyto soubory nejsou organizovány do řádků a nelze je (užitečně) otevřít normálním textovým editorem.

V Pythonu tyto soubory regulerně otevřeme již popsanou funkcí open v režimu rb (read binary) a wb (write binary). V následující ukázce vytvoříme binární kopii velikonočního pozdravu:

# copy-easter.py

f = open("easter_328kb.jpg", "rb")   # existující kopírovaný soubor
g = open("easter_copy.jpg", "wb")    # nový (prázdný) soubor tamtéž

while True:
    buff = f.read(3300)              # pomocný objekt 3300 bitů
    if len(buff) == 0:
         break
    g.write(buff)

f.close(); g.close()	

Soubor easter_328kb.jpg si prohlédnete zde , otevřený obrázek si v otevřeném kontextovém menu uložíte volbou "Save image as...". Pro potěšení si posléze ve svém adresáři otevřete také easter_copy.jpg

V následující ukázce si vytvoříme nový soubor a vložíme do něho text v kódování utf-8. Následně si tento soubor otevřeme jako objekt typu bytes:

# with-open.py

with open("cat.txt", "w", encoding="utf-8") as catt:
    catt.write("Kočička")

with open("cat.txt", "rb") as catt:
    data = catt.read()
>>> data
b'Ko\xc4\x8di\xc4\x8dka'
>>>

Ve výstupu vidíme, že písmeno "č" se v utf-8 vyjádří pomocí dvou bajtů, což se v zápisu binárního řetězce (který je implicitně kódován v ASCII) projeví aplikací "escape sekvence".


7.5 Adresáře

Soubory uložené na trvalých paměťových nosičích jsou uspořádány podle souboru pravidel, známého jako souborový systém (file system). Tento systém se skládá ze souborů a složek (folders) neboli adresářů (directories), což jsou kontejnery jak pro soubory, tak pro další složky.

Nově vytvořený soubor se po otevření a zápisu uloží do aktuálního adresáře (to jest do toho, ve kterém se nalézáme při provádění programu). Nebo naopak, otevíráme-li soubor pro čtení, hledá jej Python v aktuálním adresáři.

Chceme-li otevřít soubor někde jinde, musíme k němu určit cestu, například:

>>> wordsfile = open('/usr/share/dict/words.txt', 'r')
>>> wordlist = wordsfile.readlines()
>>> print(wordlist[:5])
['\n', 'A\n', "A's\n", 'AOL\n', "AOL's\n", 'Aachen\n']

Tento příklad otevírá soubor se jménem words.txt, který je uložený v adresáři se jménem dict jenž se nalézá v adresáři share, kterýžto je uložen v adresáři usr, jenžto sídlí v nejvyšším systémovém adresáři, označeném /. Program potom načítá jednotlivé řádky do seznamu se jménem wordlist s použitím metody readlines a posléze vytiskne prvních pět položek vytvořeného seznamu.

Znak / nelze použít jako součást jména souboru; je vyhrazen jako vymezovač mezi jmény adresářů a souborů.

Soubor /usr/share/dict/words.~ by měl existovat na unixových systémech a obsahovat abecedně uspořádaný seznam slov.


7.6 Vytváření a import modulů

Velké množství užitečných příkazů a funkcí je uloženo v takzvaných modulech, což jsou prosté soubory s příponou .py. Vestavěné (built-in) moduly jsou psány v jazyce C a jsou součástí interpreta Pythonu.

Příkladem vestavěných modulů jsou moduly math, string, random, sys ,   se kterými se postupně seznámíme.

K vytvoření vlastního modulu nám stačí textový soubor s příponou .py. Název souboru nesmí být rozdělen pomlčkou, přípustné je podtržítko.

# Text souboru mojevoje.py

def mocnina(m, n=3):            # Jen deklarace funkce           
    print(m**n)

print("Quo vadis?")             # Přímo proveditelný příkaz

def print_twice(spam):          # Jen deklarace funkce
    print(spam, spam)

Tento skript můžeme realizovat přímo, voláním ze systémové konzoly (nebo přes F5 v IDLE):

F:\Codetest\HowTo\ch-07> python mojevoje.py
Quo vadis?             

Ve spuštěném souboru se ihned provede přímo proveditelný text. Bohužel, k této aktivitě dochází i při importu modulu.

Máme-li soubor:

# tvojevoje.py
import mojevoje

můžeme jej aktivovat z konzoly:

F:\Codetest\HowTo\ch-07> python tvojevoje.py
Quo vadis?             # výstup realizovaného textu z importu

Import modulu lze provést trojím způsobem (konzolu Pythonu otevřeme ve složce, která obsahuje soubory mojevoje.py a tvojevoje.py):

a)

F:\Codetest\HowTo\ch-07> python
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, ... 
Type "help", "copyright", "credits" or ...
>>> 
>>> from mojevoje import mocnina
Quo vadis?
>>> mocnina(5)
125

b)

>>> from mojevoje import *            # importuje se vše z modulu
Quo vadis?
>>> mocnina(5, 2)
25
>>> print_twice("hola ")
hola hola

c)

>>> import mojevoje
Quo vadis?
>>> mojevoje.mocnina(4)               # evokace tečkovou notací
64

V prvním příkladě má být importována pouze funkce mocnina ale jak vidíme, importuje se rovněž realizovatelný text modulu.

V druhém případě jsme importovali vše z označeného modulu. Tento způsob nebývá doporučován, protože může vést ke kolizi jmen.

Ve třetím příkladě jsme importovali celý objekt modulu a pro použití některého jeho atributu (zde funkce) musíme uplatnit tečkovou notaci, to jest sekvenci:

<název modulu>.<název atributu>

Samostatně proveditelný příkaz print("Quo vadis?") se opět provedl bez našeho přičinění, což je vlastně svého druhu problém.
Eliminovat jej lze tím, že ze souborů, kde se "povalují" samostatně proveditelné příkazy, nebudeme nic importovat nebo tyto příkazy umístíme za karanténní bariéru:

# Text souboru mojevoje_alt.py

def mocnina(m, n=3):               # Jen deklarace funkce           
    print(m**n)
	
if __name__ == "__main__":         # idiom Pythonu
    print("Quo vadis?")            # Přímo proveditelný příkaz


Připojení cesty k modulu

Importujeme-li modul, musíme mít k němu zajištěnou cestu tím, že:

  1. se modulový soubor nachází ve stejném adresáři jako zdrojový soubor - tento způsob jsme dosud předpokládali
  2. v záhlaví zdrojového souboru uvedeme cestu k modulovému souboru (například 'mojeVoje.py') ve složce 'F/Codetest/Howto/ch-07/'. Je-li IDLE otevřen ve složce 'F/Codetest/Howto/', doplníme zbytek cesty:
    >>> import sys
    >>> sys.path.append("ch-07/")
    
    >>> import mojevoje
    Quo vadis?          # importovaný soubor se v možném rozsahu
                          ihned realizuje
    
  3. máme-li soubor, který můžeme často používat jako modul, můžeme jej vložit do instalační složky Pythonu ../Lib/site-packages; umístění této složky zjistíme (z jiného místa) dotazem:
    >>> import sys
    >>> print(sys.path)
    
    Takto uložený soubor můžeme importovat odkudkoli.
    Poznámka
    Stejného účinku dosáhneme, jestliže máme v Console2 nastaveno aby se konzola Python spouštěla v téže složce, kde odkládáme své modulové soubory.

Import modulu z paketu

Paket (package) je adresář, který obsahuje povinně soubor (třeba prázdný) __init__.py, spolu s potřebnými soubory (moduly) ~ .py.

Mějme například složku intext/ se soubory __init__.py a foo.py.

# Text souboru ch-07/intext/foo.py

class Foo:                  # deklarace třídy (viz kap. 12)
    def ukul(self):         # metoda (funkce) třídy           
        print("Ukulele")

Ukulele si můžeme vytisknout v konzole, otevřené ve složce ch-07:

>>> import intext.foo           # deklarace cesty k modulu
>>> inst = intext.foo.Foo()     # vytvoření instance třídy
>>> inst.ukul()                 # volání metody třídy
Ukulele

7.7 Modul sys a proměnná argv

Modul sys obsahuje funkce a proměnné, které poskytují přístup k prostředí operačního systému, ve kterém běží překladač Pythonu. Následující příklad ukazuje výstupní hodnoty několika příkazů, zadaných na některém z našich počítačů:

>>> import sys
>>> sys.platform
'win32'

>>> sys.path
['', 'G:\\Python\\python36.zip', 'G:\\Python\\DLLs', 'G:\\Python\\lib', 'G:\\Python', 'G:\\Python\\lib
\\site-packages']

>>> sys.version
'3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)]'

Úplný obsah modulu sys nám vrátí funkce:

>>> dir(sys)                         

Proměnná argv obsahuje seznam argumentů, načtených z příkazového řádku při spuštění skriptu. Prvním načteným argumentem (s indexem 0) je název souboru.

Vytvořme skript demo_argv.py

# f:/codetest/howto/ch-07/demo_argv.py

import sys

print(sys.argv[0])        # --> prázdný řádek
print(sys.argv)           # --> ['']

Spustíme jej z příkazového řádku zároveň s argumenty (viz) a obdržíme:

F:\Codetest\HowTo\ch-07 > python demo_argv.py this and that 1 2 3
demo_argv.py
['demo-argv.py', 'this', 'and', 'that', '1', '2', '3']

Argumenty, mezi něž patří i název skriptu, jsou odděleny pouze mezerou. Chceme-li zadat argumenty s uskupením, použijeme uvozovky:

F:\Codetest\HowTo\ch-07 > python demo_argv.py "this and that"  "1 2" 3
['demo_argv.py', 'this and that', '1 2', '3']

Pomocí argv můžeme psát užitečné programy, které přijímají vstupy přímo z příkazového řádku. Zde je například program, který určí součet zadané řady čísel:

# sum.py

from sys import argv

nums = argv[1:]           # index '0' je vyhrazen pro název souboru

# Funkce enumerate(~) vytváří z objektu 'nums' iterátor - viz 4.9.
for index, value in enumerate(nums):
    nums[index] = float(value)

print(sum(nums))

V tomto programu používáme způsob importu from <module> import <attribute>, při kterém je proměnná argv přenesena do jmenného prostoru modulu.

Nyní můžeme spouštět program z příkazové řádky takto:

>>> F:\Codetest\HowTo\ch-07 > python sum.py 3.5 5 11 100
119.5

7.8 Modul pydoc

Modul pydoc použijeme k prohledávání knihoven Pythonu, instalovaných na počítači. Na příkazový řádek napíšeme:

F:\HowTo> python -m pydoc -b
Server ready at http://localhost:52142/
Server commands: [b]rowser, [q]uit
server> 

Příkaz spustí libovolný nepoužitý port v počítači a otevře stránku ve webovém počítači. Seanci ukončíme zavřením stránky a zápisem q za poslední port v konzole.

Je to výčet všech knihoven Pythonu na vašem počítači. Klikem na jméno modulu otevřeme novou stránku s dokumentací o vybraném modulu. Například, klik na slovu keyword otevře následující stánku:

Dokumentace pro většinu modulů obsahuje tři barevně označené sektory:

Modul keyword obsahuje jedinou funkci iskeyword, která - jak její jméno naznačuje - je booleovskou funkcí, vracející True je-li zadaný řetězec klíčovým slovem:

>>> from keyword import *
>>> iskeyword('for')
True
>>> iskeyword('all')
False
>>>

Datový prvek kwlist obsahuje seznam všech současných klíčovych slov Pythonu:

>>> from keyword import *
>>> print(kwlist)
['and', 'as', 'assert', 'break', 'class', 'continue', 'def',
'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from',
'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not',
'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield',
'False', 'None', 'True']
>>>

Doporučujeme časté používání služby pydoc ke zkoumání rozsáhlých knihoven Pythonu. Mnoho pokladů čeká na své objevení!


7.9 Glosář

modul (module)
Soubor obsahující definice a příkazy Pythonu určené pro použití v jiných pythonovských programech. Obsah modulu je zpřístupněn použitím příkazu import .
standardní knihovna (standard library)
Knihovna je kolekce programů, používaných jako nástroje při vytváření jiných programů. Knihovny jsou nedílnou součástí programovacích jazyků. Python má bohatou standardní knihovnu.
pydoc
Generátor dokumentace, který je součástí standardní knihovny Pythonu.
příkaz k importu (import statement)
Příkaz, který zpřístupní objekty ze zadaného souboru - např. mymod.py. Jsou tři formy tohoto příkazu:
import mymod
importuje celý modul mymod,
from mymod import *
importuje vše z modulu mymod,
from mymod import f1, v1
importuje z modulu mymod jen objekt f1 a v1.
jmenný prostor (namespace)
Syntaktický kontejner, který umožňuje aby totéž jméno mohlo být součástí různých jmenných prostor bez víceznačností. Jmenné prostory v Pythonu se tvoří pro moduly, třídy, funkce a metody.
jmenná kolize (naming collision)
Situace, při které nelze od sebe rozlišit dvě nebo více jmen v daném jmenném prostoru. Použítím
import string
# a posléze s použitím tečkové notace
string.method_name() 
místo
from string import *
zabráníme jmenné kolizi.
atribut (attribute)
Proměnná či funkce, která je definovaná uvnitř modulu (nebo třídy či instance, jak uvidíme později). Atributy modulů jsou přistupné s použitím tečkového operátoru (.).
metoda (method)
Funkce, definovaná uvnitř třídy. Metody se pro objekt evokují s použitím tečkového operátoru, například:
>>> s = "this is a string"
>>> s.upper()
'THIS IS A STRING'
>>>

Říkáme, že metoda upper je volána pro řetězec s.

nestálá paměť (volatile memory)
Paměť, která k zachování stavu potřebuje stálý příkon elektrické energie. Hlavní paměť počítače, neboli RAM je nestálá. Informace, uložená v paměti RAM se ztratí při vypnutí počítače.
trvalá paměť (non-volatile memory)
Paměť, která svůj stav udržuje bez elektrické energie. Pevné disky, měnitelné disky a přepisovatelné kompaktní disky (CD-RW) jsou příklady nosičů s trvalou pamětí.
mód (mode)
Určitý způsob operace v počítačovém programu. Soubory v Pythonu mohou být otevřeny v jednom ze tří módů: číst~read ('r'), psát~write ('w'), připojit~append ('a').
textový soubor (text file)
Soubor, který obsahuje tisknutelné znaky uspořádané do řádků oddělených znaky newline.
adresář či složka (directory or folder)
Pojmenovaná kolekce souborů či dalších adresářů. Adresáře uvnitř adresářů jsou označovány jako podadresáře (subdirectories).
argv
Zkratka pro argument vector a proměnná modulu sys, do které se uloží argumenty příkazového řádku, použité později při běhu programu.

7.10 Cvičení

  1. Napište program mean.py, který na příkazovém řádku konzoly přijme číselné pořadí a vrátí jeho střední hodnotu. Nejde o doctesty.
    >>> python mean.py 3 4
    3.5
    >>> python mean.py 3 4 5
    4.0
    >>> python mean.py 11 15 94.5 22
    35.625
    
    Vztah mezi vstupy a výstupy u vašeho programu by měl být stejný jako v uvedené ukázce.
    Při řešení použijete vestavěnou funkci sum:
    sum(iterable[, start])            
    
    iterable je sekvence číselných hodnot - viz kap. 4.6
    [, start] je nepovinná hodnota, která se přičte k součtu
    
  2. Napište program median.py který na příkazovém řádku přijme číselné pořadí a vrátí jeho prostřední hodnotu. Řešení bude mít nejspíš větev 'if' a 'else'. Budete mít otevřený textový editor a systémovou konzolu, kde budete ověřovat program v souboru plus konzolu Pythonu, kde si budete ověřovat krátká dílčí řešení. Console2 vám ušetří místo na monitoru.
    >>> python median.py 3 7 11
    7
    >>> python median.py 19 85 121
    85
    >>> python median.py 11 15 16 22
    15.5
    
  3. Proveďte následující:
    • Spusťte server pydoc příkazem & pydoc -b případně > python -m pydoc -b z příkazového řádku.
    • Vyberte modul calendar.
    • Ze sektoru Funkctions vyberte a vyzkoušejte:
      >>> import calendar
      >>> year = calendar.calendar(2020)
      >>> print(year)  
      
    • Experimentujte s funkcí calendar.isleap(~). Co očekává jako argument? Co vrací jako výsledek? O jaký druh funkce se jedná?
    Zapište si poznatky, získané z tohoto cvičení.
  4. Alternativně se lze k webové stránce s nápovědou Pydoc dostat příkazem:

    > python -m pydoc -p 7464
    

    To aktivuje webový server pydoc na portu 7464. Jeho stránku ve vašem webovém prohlížeči aktivuje příkaz:

    > [b]rowser
    
    Spuštěný server deaktivuje příkaz:
    > [q]uit
    

    Použijte tento postup ke spuštění pydoc a vyhledejte modul math.

    1. Kolik funkcí je v modulu math?
    2. Co dělá math.ceil? A co dělá math.floor? (nápověda: jak floor tak ceil očekávají argument v desetinném formátu.)
    3. Popište, jak jsme počítali odmocninu vlastní funkcí sqrt bez použití modulu math.
    4. Jaké jsou datové konstanty v modulu math?

    Dělejte si podrobné poznámky o svém zkoumání v tomto cvičení.

  5. Vytvořte modul mymodule1.py. Přidejte atribut myage se zadaným vlastním věkem a year se zadaným současným letopočtem. Vytvořte další modul mymodule2.py. Přidejte atribut myage s nastavenou nulou a year s rokem svého narození.

    Nyní vytvořte soubor namespace.py. Importujte oba výše uvedené moduly a napište následující příkaz:
    print((mymodule1.myage - mymodule2.myage)
                    == (mymodule1.year - mymodule2.year))
    

    Spustíte-li namespace.py, dostanete jako výstup buď True nebo False podle toho, zda jste letos již narozeniny měl nebo neměl.

  6. V prostředí interpretační konzoly si vykoušejte následující:
    >>> import this
    
    Co říká Tim Peter o jmenných prostorech?
  7. Použijte pydoc k vyhledání a vyzkoušení dalších funkcí z modulu string. Porovnejte se seznamem, evokovaným příkazy:
    >>> import string
    >>> dir(string)
    
  8. Použijte dir(str) a dir(list) k nalezení nejméně tří metod na řetězci a seznamu, které nebyly dosud uvedeny. Prozatím ignorujte všechno, co začíná dvojitým podtržítkem (__). Pečlivě si zapisujte své poznatky včetně jmen nových metod a příkladů jejich použití.

    Nápověda: Vytiskněte si dokumentační řetězec funkce, kteru chcete zkoumat. Například, abychom zjistili, jak pracuje str.join, zadáme příkaz print(str.join.__doc__)

  9. V prostředí konzoly vyvolávejte odezvy k následujícím příkazům:
    1. >>> s = "If we took the bones out, \
               it wouldn't be crunchy, would it?"
      >>> s.split()
      
    2. >>> type(s.split())
      
    3. >>> s.split('o')
      
    4. >>> s.split('i')
      
    5. >>> '0'.join(s.split('o'))
      
    Je důležité, abyste každému výsledku porozuměl.
  10. Získané poznatky použijte při doplnění následující funkce s použitím metod split a join na objektech str:
    def myreplace(old, new, s ):
        """
        Nahraď všechny argumenty 'old' argumenty 'new'
        v řetězci 's'.
    
        >>> myreplace(',', ';', 'this, that, and, some, other, thing')
        'this; that; and; some; other; thing'
    
        >>> myreplace(' ', '**', 'Words will now be separated by stars.')
        'Words**will**now**be**separated**by**stars.'
        """
    
    Vaše řešení má projít oběma doctesty. Tutéž úlohu řešte také přímo s použitím metody replace.
  11. Vytvořte modul wordtools.py s následujcím ukončením:
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
    
    Vysvětlete jak tento příkaz usnadňuje užití a testování vytvořeného modulu. Jaká bude hodnota __name__ při importu wordtools.py z jiného modulu? A jaká bude při spuštění wordtools.py jako hlavního programu? Ve kterém případě budou aktivovány doctesty?
  12. Nyní do tohoto souboru postupně přidejte těla ke každé z následujících funkcí tak, aby bylo vyhověno doctestům:
    def cleanword(word):
        """
        >>> cleanword('what?')
        'what'
        >>> cleanword('"now!"')
        'now'
        >>> cleanword('?+="word!,@$()"')
        'word'
        """
    
    def has_dashdash(s):
        """
        >>> has_dashdash('distance--but')
        True
        >>> has_dashdash('several')
        False
        >>> has_dashdash('critters')
        False
        >>> has_dashdash('spoke--fancy')
        True
        >>> has_dashdash('yo-yo')
        False
        """
    
    def extract_words(s): """ >>> extract_words('Now is the time!"Now", is the time? Yes, now.') ['now', 'is', 'the', 'time', 'now', 'is', 'the', 'time', 'yes', 'now'] >>> extract_words('she tried to curtsey as she spoke--fancy') ['she', 'tried', 'to', 'curtsey', 'as', 'she', 'spoke', 'fancy'] """
    def wordcount(word, wordlist): """ >>> wordcount('now', ['now', 'is', 'time', 'is', 'now', 'is', 'is']) ['now', 2] >>> wordcount('is', ['now', 'is', 'time', 'is', 'now', 'is', 'the', 'is']) ['is', 4] >>> wordcount('time', ['now', 'is', 'time', 'is', 'now', 'is', 'is']) ['time', 1] >>> wordcount('frog', ['now', 'is', 'time', 'is', 'now', 'is', 'is']) ['frog', 0] """
    def wordset(wordlist): """ >>> wordset(['now', 'is', 'time', 'is', 'now', 'is', 'is']) ['is', 'now', 'time'] >>> wordset(['I', 'a', 'a', 'is', 'a', 'is', 'I', 'am']) ['I', 'a', 'am', 'is'] >>> wordset(['or', 'a', 'am', 'is', 'are', 'be', 'but', 'am']) ['a', 'am', 'are', 'be', 'but', 'is', 'or'] """
    def longestword(wordset): """ >>> longestword(['a', 'apple', 'pear', 'grape']) 5 >>> longestword(['a', 'am', 'I', 'be']) 2 >>> longestword(['this', 'that', 'supercalifragilisticexpialidocious']) 34 """
    Modul si uložte pro použití jeho procedur v jiných programech.
  13. Upravte program countLetters_acc.py ze cvičení 6.19.2 tak aby jméno souboru a potřebné argumenty mohly být přijaty z příkazového řádku. Řešení si uložte do souboru countLetters_cli.py.

previous up next hi end end