V minulém díle jste viděli...¶
Modul pathlib
a třída Path
¶
Pro zjednodušení práce s aresáři a se soubory vznikla knihovna pathlib
. Seznámili jsme se s třídou Path
a jejími metodami a vlastnostmi:
cwd()
- zjištění aktuálního adresářehome()
- zjištění domovského adresářejoinpath()
- spojování cest- aritmetika cest - využití operátoru
/
pro spojování cest
home = Path.home()
download = Path("Download")
file = Path("rickroll.mp4")
full_path = home / download / file
- zjišťování informací o cestě a souborech
.name
: Vrací jméno souboru bez cesty..stem
: Vrací jméno souboru bez přípony..suffix
: Vrací příponu.anchor
: Část cesty před složkami..parent
: Vrací složku, ve které je soubor, nebo nadřazenou složku dané složce..exists()
: Říká, jestli složka/soubor existují.is_dir()
vrátíTrue
, pokud se jedná o složku (adresář)..is_file()
vrátíTrue
, pokud se jedná o soubor..is_symlink()
vrátíTrue
, pokud se jedná o symbolický link.
- zápis a čtení souboru
.read_text()
otevře soubor v textovém režimu a načte obsah do stringu..read_bytes()
otevře soubor v binárním režimu a načte jeho obsah jako byty..write_text()
otevře soubor v textovém režimu a zapíše do něj text..write_bytes()
otevře soubor v binárním režimu a zapíše binární data..touch()
vytvoří prázdný soubor. Pokud existuje, změní čas modifikace na aktuální čas..mkdir()
vytvoří novou složku. Nelze vytvořit více zanořených podsložek najednou.
Práce se základními moduly standardní knihovny¶
Na dnešním cvičení se budeme podrobně zabývat klíčovým konceptem v jazyce Python Python – moduly.
Moduly vznikly z potřeby uchovávat definice funkcí a proměnných tak, aby byly dostupné i po ukončení běhu Python interpreteru. Když ukončíte a znovu spustíte Python interpreter, ztratíte všechny definice, které jste vytvořili. Pro psaní delších programů je tak lepší využít externích souborů a tím vytvořit skripty. A jak se váš program stává komplexnějším, může být výhodné rozdělit ho do několika souborů pro snazší údržbu a přehlednost.
V praxi to znamená, že můžete vytvářet moduly obsahující funkce, třídy nebo proměnné a následně je importovat do dalších modulů nebo skriptů. Tento přístup usnadňuje správu kódu a umožňuje opakované využití kódu bez kopírování definic do každého nového programu. To je zvláště užitečné při psaní funkcí, které chcete používat v různých projektech, aniž byste museli opisovat jejich definici do každého programu znovu.
Dnes se budeme zaměřovat na praktický pohled na několik standardních modulů, jako jsou math
, random
, sys
, os
, a další, abychom se s nimi naučili pracovat.
Příkaz import
¶
Příkaz import
je základním nástrojem, jak zavést moduly a jejich funkcionalitu do našeho kódu. Tento příkaz má několik variant.
Základní Import¶
import module_name
Tímto způsobem získáme přístup ke všem prvkům definovaným v module_name
. Používá se jednoduše přístupem k prvkům přes přes tečkovou notaci - module_name.element
Import konkrétních prvků¶
Pokud nepotřebujeme importovat celý modul, ale jen několik jeho prvků (funkcí, tříd, konstant), můžeme to udělat následujícím způsobem
from module_name import element1, element2
K těmto prvkům již můžeme přistupovat napřímo, bez tečkové notace a plného názvu modulu - element1
Alternativní způsoby importu¶
- Alternativní pojmenování - alias¶
Během importu je možné modul nebo jeho prvky (záleží, která varianta importu je použita) pojmenovat alternativním názvem a pod tímto názvem s ním dále pracovat. Hodí se to převážně, pokud název modulu nebo jeho prvků je příliš dlouhý nebo komplikovaný nebo pokud by daný název kolidoval s již jinými objekty v našem programu.
import module_name as alias
from another_module import element1 as el1, element2 as el2
- Import všech prvků z modulu (❗❗NEDOPORUČOVÁNO❗❗)¶
Existuje možnost importovat všechny prvky z daného modulu.
from module_name import *
Tento přístup není doporučován, protože může dojít ke konfliktům názvů (k zastínění starších objektů) a dalším nejasnostem a k "zaplevelení" aktuálního namespace. Je doporučeno být explicitní v tom, jaké moduly a prvky z nich potřebuji a importuji. Pro rychlé prototypování v interaktivním intepretu to může být užitečné, ale ve finálním programu by se to nemělo používat.
# ukázka ... konflikt názvů
pi = "ahoj"
print(pi)
from math import *
print(pi)
ahoj 3.141592653589793
# ukázka ... konflikt názvů
pi = "ahoj"
print(pi)
from math import pi
print(pi)
ahoj 3.141592653589793
# příklad
# Základní import
import math
from math import pi
# Import s aliasem
import numpy as np
# Import konkrétních prvků
from random import randint, choice as volba
# Použití importovaných prvků
print(math.sqrt(25), pi)
print(np.array([1, 2, 3]))
print(randint(1, 10))
print(volba(['a', 'b', 'c']))
5.0 3.141592653589793 [1 2 3] 3 a
Co se děje na pozadí příkazu import
¶
Kdyz se zavolá některá z variant příkazu import
, dojde k tomu, že importovaný objekt se stane součástí namespace, ve kterém je příkaz import
zavolán.
Nejčastěji import
voláme na začátku programu v globálním namespace a importované objekty tak jsou součástí tohoto globálního namespace a dostupné odkudkoli v programu. Je možné ale import volat i v lokálním namespace (například v těle funkce) a pak efekt příkazu import
je platný jen v tomto kontextu.
sys.modules
¶
Při provádění příkazu import
se Python nejprve podívá, jestli už se hledaný modul program nepokusil načíst již dříve (je jedno, jestli celý modul, nebo jen nějaký prvek z něj). Odkazy na moduly, které již program během svého běhu načetl, se nacházejí v sys.modules
. Je to slovník, kde klíče jsou názvy modulů a hodnoty jednotlivé moduly. Slouží jako cache.
Pokud se tedy hledaný modul najde v tomto slovníku, nemusí se modul již načítat (už je v paměti načten) a do aktuálního namespace se vloží odkazy na modul, nebo na prvky, které z tohoto modulu chceme používat.
Pokud není nalezen, Python prohledává určité cesty v souborovém systému na disku a snaží se najít odpovídající moduly. Když se modul podaří nalézt, načte se do paměti, uloží do sys.modules
a zveřejní v lokálním namespace.
Pokud není modul nalezen ani na souborovém systému, dojde k vyvolání výjimky ModuleNotFoundError
(existuje ještě výjimka ImportError
, která je rodičovská třída k třídě ModuleNotFoundError
, a ta může být také vyvolána, pokud import selže z nějakých jiných důvodů)
Ukázka sys.modules
¶
Pojďme se podívat na to, jak se import projevuje na aktuálním namespace a sys.modules
.
import sys
'math' in sys.modules
#sys.modules # je to slovník (hodně velký)
True
# print(locals()) # ... opět slovník, s podobnou strukturou
#print(locals().keys())
#print(globals().keys())
# nejprve musíme supustit buňku s definicí filter_keys()
print(filter_keys(locals().keys()))
print(filter_keys(globals().keys()))
['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys'] ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys']
a = 6
import math
from math import pi
print(filter_keys(locals().keys()))
print(filter_keys(globals().keys()))
['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys', 'a', 'math', 'pi'] ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys', 'a', 'math', 'pi']
# print(locals()) # je to opět dost velký slovník
print(locals().keys())
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__builtin__', '__builtins__', '_ih', '_oh', '_dh', 'In', 'Out', 'get_ipython', 'exit', 'quit', 'open', '_', '__', '___', '__session__', '_i', '_ii', '_iii', '_i1', '_i2'])
# pomocna funkce
def filter_keys(keys):
return [key for key in keys if not key.startswith('_')]
import sys
import turtle as zelva
from collections import Counter
# podivejme se na lokalni a globalni kontext - jsou stejne, jsme totiz v globalnim kontextu
# vypiseme pro prehlednost jen klice relevantni klice
print('GLOBAL', filter_keys(globals()), end='\n')
print('LOCAL ', filter_keys(locals()), end='\n\n')
print('jsou identicke?', globals() is locals(), end='\n\n')
# vidime zde moduly/funkce vsazene do namespace, aby byly k dispozici
print(Counter([1,1,2,3]), end='\n\n')
GLOBAL ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'sys', 'zelva', 'Counter', 'filter_keys'] LOCAL ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'sys', 'zelva', 'Counter', 'filter_keys'] jsou identicke? True Counter({1: 2, 2: 1, 3: 1})
# Podivejme se treba na modul turtle. Je nacteny v pameti a reference na nej se objevuje
# ve slovniku sys.modules pod jeho originalnim nazvem
print('Modul turtle je v sys.modules pod originalnim nazvem:', 'turtle' in sys.modules, end='\n\n')
print('V glob. ns je dostupny pod aliasem:', 'zelva' in globals(), end='\n\n')
print('Je to ten stejny modul?:', globals()['zelva'] is sys.modules['turtle'], end='\n\n')
Modul turtle je v sys.modules pod originalnim nazvem: True V glob. ns je dostupny pod aliasem: True Je to ten stejny modul?: True
# jak vypada samostatna funkce/trida, ktera byla importovana
print('Counter je dostupny v namespace:', 'Counter' in globals(), end='\n\n')
print('Counter je dostupny v cache - sys.module:', 'Counter' in sys.modules, end='\n\n')
print('V sys.modules je dostupny jeho modul, ne samotna fce:',
'collections' in sys.modules, end='\n\n')
print('je Counter v ns totez, jako Counter ukryty v modulu v sys.modules?:',
globals()['Counter'] is sys.modules['collections'].Counter, end='\n\n')
Counter je dostupny v namespace: True Counter je dostupny v cache - sys.module: False V sys.modules je dostupny jeho modul, ne samotna fce: True je Counter v ns totez, jako Counter ukryty v modulu v sys.modules?: True
Poznámka: operátor
is
je operátor identity - říká, jestli 2 proměnné odkazují na ten stejný objekt v paměti
import sys
# Podívejme se ještě na lokální namespace, například ve funkci
def import_test():
# naimportujeme neco, co jsme jeste dnes neimportovali
a = 6
import cmath
print('CMATH sqrt jde pouzit: ',cmath.sqrt(-1), end='\n\n')
print('GLOBAL ve funkci', filter_keys(globals().keys()), end='\n\n')
print('LOCAL ve funkci ', filter_keys(locals().keys()), end='\n\n')
print('jsou identicke?', globals() is locals(), end='\n\n')
print('GLOBAL', filter_keys(globals()), end='\n')
print('LOCAL', filter_keys(locals()), end='\n\n')
#zjistime jestli cmath je v sys.modules
print('Cmath in sys.modules', 'cmath' in sys.modules)
print('Cmath in globals()', 'cmath' in globals())
# spustime funkce
import_test()
print('GLOBAL', filter_keys(globals()), end='\n')
print('LOCAL', filter_keys(locals()), end='\n\n')
print('Cmath in sys.modules', 'cmath' in sys.modules)
print('Cmath in globals()', 'cmath' in globals())
# vykonavani spadne, v globalnim ns to neni importovane
print(cmath.sqrt(-1))
GLOBAL ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys', 'a', 'math', 'pi', 'import_test', 'sys'] LOCAL ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys', 'a', 'math', 'pi', 'import_test', 'sys'] Cmath in sys.modules False Cmath in globals() False CMATH sqrt jde pouzit: 1j GLOBAL ve funkci ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys', 'a', 'math', 'pi', 'import_test', 'sys'] LOCAL ve funkci ['a', 'cmath'] jsou identicke? False GLOBAL ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys', 'a', 'math', 'pi', 'import_test', 'sys'] LOCAL ['In', 'Out', 'get_ipython', 'exit', 'quit', 'open', 'filter_keys', 'a', 'math', 'pi', 'import_test', 'sys'] Cmath in sys.modules True Cmath in globals() False
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[6], line 27 25 print('Cmath in globals()', 'cmath' in globals()) 26 # vykonavani spadne, v globalnim ns to neni importovane ---> 27 print(cmath.sqrt(-1)) NameError: name 'cmath' is not defined
Výběr modulů standardní knihovny¶
math
¶
Modul math
poskytuje matematické funkce pro pokročilé výpočty. Obsahuje metody pro operace s čísly, trigonometrii, logaritmy a další matematické operace. Knihovna je velice bohatá a nabízí široké spektrum funkcí.
S touto knihovnou jsme se již seznámili v dřívějších cvičeních.
- Práce s integery a konverze
Funkce | Krátký popis |
---|---|
math.ceil(x) | Zaokrouhlení nahodu |
math.floor(x) | Zaokrouhlení dolu |
math.trunc(x) | Odříznutí desetinné části |
- Obecné výpočty
Funkce | Krátký popis |
---|---|
math.factorial(n) | Výpočet n! |
math.gcd(*integers) | Výpočet největšího společného dělitele čísel |
math.prod(iterable, *, start=1) | Výpočet produktu - vzájemné vynásobení všech čísel |
- Trigonometrické a běžné funkce
Funkce | Krátký popis |
---|---|
math.exp(x) | Výpočet e^x |
math.log(x[, base] ) | Výpočet logaritmu od základu base |
math.pow(x, y) | Výpočet mocniny x^y |
math.sqrt(x) | Výpočet odmocniny |
- Konstanty
Konstanta | Krátký popis |
---|---|
math.pi | Ludolfovo číslo pi - 3.14 |
math.e ) | Eulerovo číslo e |
math.inf | Hodnota reprezentující kladné nekonečno |
- Zjišťovací funkce
Funkce | Krátký popis |
---|---|
math.isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) | Zjistí, jestli jsou si čísla blízko za daných mezí (relativních nebo absolutních) |
Více podrobností v oficiální dokumentaci
cmath¶
Tento modul poskytuje funkce podobné, jako v modulu math
. Umí však počítat v komplexním prostoru.
Navíc nabízí nějaké funkce aplikovatelné jen v komplexní rovině.
Funkce | Krátký popis |
---|---|
cmath.phase(x) | Fáze komplexního čísla |
cmath.polar(x) | Konverze komplexního čísla do polárních souřadnic |
cmath.rect(r, phi) | Konverze komplexního čísla z polárních do kartézských souřadnic |
Více podrobností v oficiální dokumentaci
# ukázka **, sqrt,
import math
import cmath
print((-1)**0.5)
print(cmath.sqrt(-1)) # komplexní varianta umi vypočítat odmocninu záporných čísel
#print(math.sqrt(-1))
# ukázka isclose
x = (-1)**0.5
y = cmath.sqrt(-1)
print(x == y, cmath.isclose(x,y))
(6.123233995736766e-17+1j) 1j False True
random
¶
Modul random slouží k generování pseudo-náhodných čísel. Pomocí různých metod může být využit v různých situacích, například při hraní her nebo simulacích. Dostupné funkce se řadí do několika kategorií:
Sekce pro integery¶
Funkce | Krátký popis |
---|---|
random.randrange(stop) | Vrátí náhodný prvek z množiny hodnot, které by vygenerovala funkce range se stejnými parametry. Používá stejné parametry. |
random.randint(a, b) | Vrátí náhodný integer I tak, že a <= I <=b |
Sekce pro sekvence¶
Funkce | Krátký popis |
---|---|
random.choice(seq) | Vybere náhodný prvek ze sekvence |
random.shuffle(x) | Náhodně zamíchá (inplace) prvky modifikovatelné sekvence |
Sekce pro reálná čísla¶
Funkce | Krátký popis |
---|---|
random.random() | Vrátí náhodné číslo v r rozmezí 0.0 <= r < 1.0 |
random.uniform(a, b) | Vrátí náhodné číslo v r rozmezí a <= r <= b |
Seed¶
Někdy je velice užitečné být schopen zreplikovat posloupnost (pseudo)náhodných čísel, například kvůli ladění programu. Generátor náhodné sekvence funguje tak, že na základě aktuální hodnoty se generuje hodnota následující. Automatická volba počáteční hodnoty pak zajistí "náhodnost". Typicky se prvotní hodnota nastavuje například na aktuální čas nebo si bere počáteční hodnotu z nějakého systémového generátoru pseudo-náhodných čísel (/dev/random
, /dev/urandom
, ...).
Můžeme ale nastavit výchozí hodnotu na konkrétní číslo a tím zajistíme opakovatelnost - posloupnost náhodných čísel bude začínat vždy ze stejného bodu. Nezapomeňte vlastní seed pak odstranit před reálným použitím programu :)
Více podrobností v oficiální dokumentaci.
import random
# vygenerujeme nahodna cisla z mnoziny, kterou by vytvoril range(5, 50, 5)
#random.seed(156)
for i in range(5):
print(random.randrange(5, 50, 5))
25 40 25 15 20
TIP: Zkuste předchozí kód pouštět vícekrát - pokaždé dá jiné hodnoty.
# vybereme nahodny prvek ze sekvence
s = [1,2,3,4,5,6,7,8,9,10]
print(random.choice(s))
print(random.choice(s))
print(random.choice(s))
print(random.choice(s))
# ukázka shuffle
random.shuffle(s)
print(s)
3 7 3 8 [5, 3, 4, 6, 8, 2, 1, 9, 10, 7]
# vygenerujeme nahodne cislo z daneho rozsahu
print(random.uniform(100, 200))
print(random.random())
125.21726267441034
# zazalohuje me si aktualni stav random objektu
random_state = random.getstate()
# nastavime vlastni seed - uvidime, ze to vzdy generuje stejne posloupnosti pri kazdem behu, pokud nastavime vlastni seed
random.seed(2) # nejake konstantni cislo
for i in range(10):
print(random.random())
0.9560342718892494 0.9478274870593494 0.05655136772680869 0.08487199515892163 0.8354988781294496 0.7359699890685233 0.6697304014402209 0.3081364575891442 0.6059441656784624 0.6068017336408379
# obnovime random do puvodniho stavu
random.setstate(random_state)
TIP: zkuste měnit seed a pozorujte, jak se mění výstup.
sys
¶
Modul sys
poskytuje funkce a hodnoty, které Python interpreter využívá nebo ho ovlivňují. Umožňuje například manipulaci s cestami nebo předávání argumentů při spouštění skriptu.
Důležité funkce a hodnoty¶
Funkce | Krátký popis |
---|---|
sys.exit([arg]) | Ukončí běh skriptu s daným návratovým kódem |
sys.modules | Slovník obsahující aktuálně načtené moduly. Slouží jako cache pro jejich načítání |
sys.version_info | Poskytuje informace o aktuální verzi interpreteru Python |
sys.argv | Seznam argumentů, předaných skriptu při spuštění |
Více podrobností v oficiální dokumentaci.
import sys
# parametry, se kterymi byl tento skript spusten
print(sys.argv, end='\n\n')
print(sys.version_info)
['/usr/lib/python3.11/site-packages/ipykernel_launcher.py', '-f', '/home/reitezuz/.local/share/jupyter/runtime/kernel-17e58383-6ff7-4c46-b755-8378f31f06f9.json'] sys.version_info(major=3, minor=11, micro=6, releaselevel='final', serial=0)
Ukázka sys.exit, sys.argv na skriptu muj.py¶
Obsah souboru muj.py:
import sys
# parametry, se kterymi byl tento skript spusten
print(sys.argv, end='\n\n')
if len(sys.argv) > 1:
if sys.argv[1] == "0":
print("je tam")
sys.exit(1)
else:
print("není tam")
sys.exit(0)
print("příště zavolej s více argumenty.")
Ukázka spuštění skriptu z terminálu
1 reitezuz@jupyter:~/$ python3 muj.py
['muj.py']
příště zavolej s více argumenty.
0 reitezuz@jupyter:~/$ python3 muj.py 7 8 ahoj
['muj.py', '7', '8', 'ahoj']
není tam
0 reitezuz@jupyter:~/$ python3 muj.py 0 8 ahoj
['muj.py', '0', '8', 'ahoj']
je tam
1 reitezuz@jupyter:~/$ python3 muj.py 0
['muj.py', '0']
je tam
1 reitezuz@jupyter:~/$
os
¶
Modul os
poskytuje funkce pro interakci se systémovým prostředím, jako je manipulace s adresáři, spouštění příkazů nebo práce s proměnnými prostředí.
Slouží jako rozhraní ke komunikaci s operačním systémem.
Důležité funkce a hodnoty - práce s proměnnými prostředí a systémem¶
Funkce | Krátký popis |
---|---|
os.environ | Slovník obsahující proměnné prostředí a jejich hodnoty. Může být využit pro konfiguraci našeho skriptu |
os.getenv(key, default=None) | Funkce schopna vrátit hodnoty proměnnných prostřed (s možností definovat defaultní hodnoty v případě nenalezení daného klíče). Operuje nad os.environ |
os.system(command) | Spustí příkaz v command v terminálu |
Důležité funkce a hodnoty - práce se soubory¶
Funkce | Krátký popis |
---|---|
os.getcwd() | Zjistí aktuální adresář |
os.chdir(path) | Změní aktuální adresář na path |
os.mkdir(path) | Vytvoří nový adresář path . Neumí vytvořit více úrovní složek najednou |
os.makedirs(path) | Vytvoří nové adresáře. Umí vytvořit celou cestu adresářů. |
os.rmdir(path) | Smaže adresář path |
os.listdir(path='.') | Vrátí seznam adresářů a souborů v path , ve výchozím stavu v aktuálním adresáři |
os.replace(src, dst) | Přejmenuje/přesune soubor nebo složku src na dst |
os.remove(path) | Odstraní soubor path |
Více podrobností v oficiální dokumentaci.
import os
print(os.getenv("USER"))
# python funkce na vylistovani obsahu slozky
print(os.listdir(path="data"))
# zavolani alternativni funkce dostupne primo v terminalu operacniho systemu. Pouzijte dir pro windows OS.
# Ukazuje univerzalnost python funkci (vyse) a nezavislost na OS.
os.system('ls')
reitezuz ['data.txt', 'inventory.txt', 'rename.txt', 'text.txt', 'new_file.txt', '.ipynb_checkpoints', 'data_new.txt', 'cisla.txt', 'soubor.txt', 'binarni_soubor.bin', 'argparse_test.py', 'inventory.csv', 'example.csv', 'example.json', 'argparse_vypis.py'] cv21_poznamky.ipynb cv21_příklady.ipynb cv21_sk3.ipynb cv21_vzor.ipynb cv22_sk3.ipynb cv22_vzor.ipynb data example.csv modules muj.py mymodule.py __pycache__ Untitled.ipynb
0
# ukázka os.system(command) na skriptu .py
os.system('python muj.py op')
['muj.py', 'op'] není tam
0
os.system('python muj.py')
['muj.py'] příště zavolej s více argumenty.
0
os.system('python muj.py 0 1 ahoj -p')
['muj.py', '0', '1', 'ahoj', '-p'] je tam
256
pprint
¶
Modul pprint
(pretty-print) slouží k "krásnému" formátování výstupu, což je užitečné zejména při práci s komplexními datovými strukturami.
Důležité funkce a hodnoty¶
Funkce | Krátký popis |
---|---|
pprint.pprint(object) | Zajistí hezčí a přehlednějsí výpis komplikovaných datových struktur. |
Pro zjednodušení práce je možné funkcí pprint
nahradit původní funkci print
from pprint import pprint as print
Případně alternativně se zachováním původní funkce
import pprint
original_print = print
print = pprint.pprint
Více podrobností v oficiální dokumentaci.
import pprint
d = {i: i**2 for i in range(20)}
print("Standardni print")
print(d)
print("\nPretty print")
pprint.pprint(d)
Standardni print {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100, 11: 121, 12: 144, 13: 169, 14: 196, 15: 225, 16: 256, 17: 289, 18: 324, 19: 361} Pretty print {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100, 11: 121, 12: 144, 13: 169, 14: 196, 15: 225, 16: 256, 17: 289, 18: 324, 19: 361}
import pprint
# nahrazeni
original_print = print
print = pprint.pprint
print(d)
# vraceni
print = original_print
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100, 11: 121, 12: 144, 13: 169, 14: 196, 15: 225, 16: 256, 17: 289, 18: 324, 19: 361}
collections
¶
Modul collections
poskytuje alternativní datové typy k vestavěným typům jako seznamy nebo slovníky.
Tyto dodatečné datové typy mohou usnadnit práci při implementaci například některých algoritmů.
Důležité funkce a hodnoty¶
Funkce | Krátký popis |
---|---|
collections.Counter([iterable-or-mapping]) | Struktura typu slovník. Prvky původní posloupnosti jsou uloženy jako klíče, hodnoty značí počet výskyt§ |
collections.defaultdict() | Je to slovník s výchozí hodnotou pro neexistující prvky |
collections.namedtuple(typename, field_names) | Alternativa k tuple. Umožní pojmenovat jednotlivé pozice pro jednodušší a přehlednější použití |
Více podrobností v oficiální dokumentaci.
from collections import Counter
data = [1, 2, 3, 1, 2, 1, 4, 5]
data = "abrakadabra"
counter = Counter(data)
print(counter)
Counter({'a': 5, 'b': 2, 'r': 2, 'k': 1, 'd': 1})
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p.x, p.y) # Vytiskne hodnoty x a y
# funguje i originalni "tuple" přístup přes indexy
print(p[0], p[1])
1 2 1 2
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y', 'z'])
p = Point(1, 2, 3)
print(p.x, p.z, p.y) # Vytiskne hodnoty x a y
# funguje i originalni "tuple" přístup přes indexy
print(p[0], p[2])
1 3 2 1 3
from collections import defaultdict
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
# výhoda je v tom, že nemusíme ověřovat, jestli daný klíč je ve slovníku
# pro každý neexistující klíč se při přístupu automaticky vytvoří s danou defaultní hodnotou
# list v tomto případě
d = defaultdict(list)
for k, v in s:
d[k].append(v)
print(d.items())
# ukázka se sčítáním
d1 = defaultdict(int)
for k, v in s:
d1[k] +=v
print(d1.items())
# ukázka, jak by to bylo s obyčejným slovníkem:
d = {}
for k, v in s:
if k not in d:
d[k] = []
d[k].append(v)
print(d.items())
d = {}
for k, v in s:
if k not in d:
d[k]=0
d[k] += v
print(d.items())
dict_items([('yellow', [1, 3]), ('blue', [2, 4]), ('red', [1])]) dict_items([('yellow', 4), ('blue', 6), ('red', 1)]) dict_items([('yellow', [1, 3]), ('blue', [2, 4]), ('red', [1])]) dict_items([('yellow', 4), ('blue', 6), ('red', 1)])
itertools
¶
Modul itertools
poskytuje funkce pro vytváření efektivních iterátorů, které jsou užitečné jak samostatně, tak ve vzájemné kombinaci. Obsahuje funkce například pro slučování a kombinaci více zdrojů, opakování, nebo filtrování.
Důležité funkce a hodnoty¶
Funkce | Krátký popis |
---|---|
itertools.count(start=0, step=1) | Iterator určený k očíslování. Užitečný například u ZIPu nebo map funkci |
itertools.cycle(iterable) | Umožňuje nekonečnou iteraci přes nějakou posloupnost |
itertools.chain(*iterables) | Vytvoří iterátor, který postupně iteruje přes všechny posloupnosti |
itertools.product(*iterables, repeat=1) | Vygeneruje prvky kartézského součinu všech vstupních posloupností |
itertools.permutations(iterable, r=None) | Vygeneruje permutace o délce r |
itertools.combinations(iterable, r) | Vygeneruje kombinace o délce r |
itertools.combinations_with_replacement(iterable, r) | Vygeneruje kombinace s opakováním o délce r |
Více podrobností v oficiální dokumentaci.
import itertools
c = itertools.count()
for i in range(20):
print(next(c), end = " ")
print("")
# ukázka ... iterace přes count + break
for i in itertools.count():
print(i, end = " ")
if i > 10:
break
print("")
# Nekonecna smycka tisknouci 1,2,3,1,2,3,1,2,3,.....
j = 0
for i in itertools.cycle( [1,2,3]):
print(i, end = " ")
j += 1
if j > 10:
break
print("")
# ukázka: rozdej zadání testu A, B na střídačku studentům:
print(list(zip (range(20), itertools.cycle(["A","B"]))))
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 0 1 2 3 4 5 6 7 8 9 10 11 1 2 3 1 2 3 1 2 3 1 2 [(0, 'A'), (1, 'B'), (2, 'A'), (3, 'B'), (4, 'A'), (5, 'B'), (6, 'A'), (7, 'B'), (8, 'A'), (9, 'B'), (10, 'A'), (11, 'B'), (12, 'A'), (13, 'B'), (14, 'A'), (15, 'B'), (16, 'A'), (17, 'B'), (18, 'A'), (19, 'B')]
for i in itertools.product('abc', [1,2,3,4]):
print(i)
('a', 1) ('a', 2) ('a', 3) ('a', 4) ('b', 1) ('b', 2) ('b', 3) ('b', 4) ('c', 1) ('c', 2) ('c', 3) ('c', 4)
pole = [1,2,3,4,5]
# ukázka kombinací o delce 2
print(list(itertools.combinations(pole, 2)))
# ukázka kombinací o delce 3
print(list(itertools.combinations(pole, 3)))
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)] [(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5), (2, 4, 5), (3, 4, 5)]
csv
¶
Modul csv
poskytuje funkcionalitu pro práci s formátem CSV (Comma-Separated Values), což je často používaný formát pro ukládání tabulkových dat.
Důležité funkce a hodnoty¶
Funkce | Krátký popis |
---|---|
csv.reader(csvfile, dialect='excel', **fmtparams) | Vytvoří objekt pro čtení dat ze souboru CSV |
csv.writer(csvfile, dialect='excel', **fmtparams) | Vytvoří objekt pro zápis dat do souboru CSV. |
Více podrobností v oficiální dokumentaci.
# ukázka, nejprve načti pomocí open a podívej se na strukturu csv:
with open('data/inventory.csv', 'r') as file:
print(file.read())
#name,amount,price Kýbl,5,85 Pytel cementu,10,120 Cihla,65,25 Kladivo,3,150 Vrtačka,2,2000 Hřebík,560,0.5 Míchačka,1,5600 Hmoždinka,120,3
import csv
with open('data/inventory.csv', 'r') as file:
reader = csv.reader(file)
for row in reader:
print(row) # Vytiskne každý řádek ze souboru CSV
['#name', 'amount', 'price'] ['Kýbl', '5', '85'] ['Pytel cementu', '10', '120'] ['Cihla', '65', '25'] ['Kladivo', '3', '150'] ['Vrtačka', '2', '2000'] ['Hřebík', '560', '0.5'] ['Míchačka', '1', '5600'] ['Hmoždinka', '120', '3']
# ukázka navíc: zápis csv:
import csv
# Otevření souboru pro zápis CSV
with open('data/example.csv', 'w') as csvfile:
# Vytvoření objektu csv.writer
csv_writer = csv.writer(csvfile)
# Zápis prvního řádku - hlavičky
csv_writer.writerow(['#Jméno', 'Příjmení', 'Věk'])
# Zápis dat
csv_writer.writerow(['Jan', 'Novák', 25])
csv_writer.writerow(['Eva', 'Svobodová', 30])
csv_writer.writerow(['Petr', 'Dvořák', 22])
with open('data/example.csv', 'r') as file:
print(file.read())
#Jméno,Příjmení,Věk Jan,Novák,25 Eva,Svobodová,30 Petr,Dvořák,22
json
¶
Modul json
umožňuje práci s formátem JSON (JavaScript Object Notation), což je populární formát pro výměnu dat mezi aplikacemi.
Důležité funkce a hodnoty¶
Funkce | Krátký popis |
---|---|
json.dumps(obj) | Převede objekt na string ve formátu JSON (serializace). |
json.loads(json_str) | Převede JSON řetězec zpět na objekt (deserializace). |
Více podrobností v oficiální dokumentaci.
import json
json_str = '{"name": "John", "age": 30, "city": "New York"}' # vyzaduje dvojite uvozovky
loaded_data = json.loads(json_str) # nacteme string JSON a udelame z nej python objekt
print(type(loaded_data))
print(loaded_data) # vytiskne python objekt odpovidajici strukture JSON (dict)
print(data)
json_str = json.dumps(data) # vytvori json retezec z python objektu
print(json_str) # Vytiskne JSON řetězec
<class 'dict'> {'name': 'John', 'age': 30, 'city': 'New York'} abrakadabra "abrakadabra"
# ukázka navíc: zápis a načítání JSON do/ze souboru
import json
data = {"name": "John", "age": 30, "city": "New York"}
# Otevření souboru pro zápis JSON
with open('data/example.json', 'w') as json_file:
json.dump(data, json_file)
# Otevření souboru pro čtení JSON
with open('data/example.json', 'r') as json_file:
new_data = json.load(json_file)
print(new_data)
{'name': 'John', 'age': 30, 'city': 'New York'}
argparse
¶
argparse
je velmi užitečný modul v jazyce Python, který umožňuje jednoduché a efektivní zpracování příkazové řádky. Tento modul slouží k definování, konfiguraci a parsování argumentů a jejich hodnot spouštěného skriptu. To usnadňuje usnadňuje psaní rozsáhlejších Python skriptů.
Hlavní vlastnosti argparse¶
- umožňuje definovat, jaké argumenty může skript nebo aplikace přijímat. Argumenty mohou být povinné nebo volitelné.
- Každý argument může mít přidružené parametry, například typ dat, který očekává (řetězec, číslo, atd.), nebo zkrácenou a plnou verzi názvu argumentu
- postará se o správu chyb spojených s nevalidními vstupy nebo chybějícími argumenty
- generuje automaticky nápovědu a dokumentaci pro všechny definované argumenty, což zjednodušuje orientaci uživatelům.
- poskytuje možnost specifikovat vzájemné vztahy mezi argumenty, například vyžadování určitých kombinací argumentů nebo nastavení výchozích hodnot.
Stručné použití¶
Vytvoříme novou instanci parseru a nastavíme popis programu, případně dovětek dokumentace
import argparse
parser = argparse.ArgumentParser(
description='What the program does',
epilog='Text at the bottom of help')
Následně můžeme přidávat jednotlivé argumenty. Funkce add_argument
má velké množství konfiguračních parametru, viz doc
parser.add_argument('filename') # positional argument
parser.add_argument('-c', '--count') # option that takes a value
parser.add_argument('-v', '--verbose',
action='store_true') # on/off flag
Spustíme parser. Následně můžeme přistupovat k hodnotám jednotlivých argumentů
args = parser.parse_args()
print(args.filename, args.count, args.verbose)
Více k ukázce dole v příkladech.
Více podrobností v oficiální dokumentaci
Externí (nestandardní) balíčky a moduly¶
Kromě standardních modulů, které jsou součástí každé instalace Pythonu, existuje bohatý ekosystém externích modulů, nazývaných balíčky.
Tyto balíčky poskytují širokou škálu funkcionalit, které mohou být snadno integrovány do projektů.
Instalace externích balíčků je obvykle prováděna pomocí správce balíčků, například pip
.
Zde je několik příkladů externích balíčků:
requests
- Slouží k jednoduchému provádění HTTP requestůnumpy
- Poskytuje podporu pro efektivní manipulaci s multidimenzionálními poli a matematickými funkcemi.Pandas
- Nabízí vysokoúrovňové datové struktury a nástroje pro analýzu datDjango
- webový framework pro vývoj moderních webových aplikací v jazyce Python
TIP: Používání externích balíčků se věnuje navazující předmět 18PPY1.
Příklady¶
1) Vzdálenost bodů v rovině¶
Napište program, který který bude analyzovat vzdálenosti mezi body v rovině. Bude obsahovat nejméně 2 funkce:
def average_distance(points)
- spočítá průměrnou vzájemnou vzdálenost bodů. Vrátí tuto hodnotudef closest_points(points)
- zjistí, které 2 body jsou si nejblíže. Vrátí tuple, který bude obsahovat tyto 2 body
Může se hodit funkce itertools.combinations
.
Proměnná point
bude posloupnost bodů. Volbu toho, jak reprezentovat bod, nechám na Vás. Nabízím ale 2 možné varianty, které procvičí látku dnešní hodiny:
namedtuple('Point', ['x', 'y'])
- reprezentace pomocí komplexních čísel - tam se pak může hodit operátor mínus (
-
) a funkceabs
Sadu bodů, které budete testovat si vygenerujte náhodně. Pro začátek vyrobte 10 bodů tak, aby se nacházely v intervalu <0,100> pro souřadnici x
i y
. Bude se hodit funkce random.uniform
. Pro ladění programu se může hodit zafixovat generátor pseudonáhodných čísel na konkrétní počáteční hodnotě (random.seed(value)
)
# volné místo na program
import random
import collections
import itertools
random.seed(15)
print(random.uniform(0,100))
# body jako ntice
points = [ (random.uniform(0,100), random.uniform(0,100)) for i in range(10)]
print(points,"\n")
# body jako komplexní čísla
points = [ complex(random.uniform(0,100) , random.uniform(0,100)) for i in range(10)]
print(points,"\n")
# body jako pojmenované ntice
Point = collections.namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p.x, p.y) # Vytiskne hodnoty x a y
points = [ Point(random.uniform(0,100), random.uniform(0,100)) for i in range(10)]
print(points,"\n")
# kombinace
print(list(itertools.combinations("abcd",2)),"\n")
#print(list(itertools.combinations(points,2)))
96.52421415521229 [(1.1654693792141124, 73.59916197968755), (15.801272476474814, 98.63394516628233), (1.6880654207976242, 87.94912681346712), (68.13506644014146, 85.73423824815248), (99.98162341661194, 23.97151821637886), (33.807775725669984, 70.81943329851276), (28.058168584313727, 26.33142571474607), (22.860972534891623, 85.78370973942192), (87.45326053736207, 79.76159923774809), (22.339120734958705, 92.48382801310964)] [(51.13699467514997+23.13858686175163j), (45.55368113568211+41.98753274203939j), (7.89592896484349+56.46915867853098j), (35.99644485064033+56.9615709149503j), (93.02173681112063+64.55712501003462j), (40.510042590565064+86.35739893438311j), (99.5172910882823+49.025652527221276j), (94.50248095304838+1.8750050631989423j), (14.031812201393755+17.21945078227547j), (93.80647896600813+69.0484954745283j)] 1 2 [Point(x=71.90823407276066, y=28.661714144040385), Point(x=49.49850749350316, y=88.70647315350112), Point(x=9.987564304346552, y=11.6221773589949), Point(x=4.741616601935295, y=46.866158936586274), Point(x=84.04821971170922, y=55.49904800640159), Point(x=40.14593208032403, y=50.20565556911267), Point(x=17.92114641047492, y=94.81329582636897), Point(x=35.38014075034109, y=23.525993757036222), Point(x=31.12329778413885, y=82.4932714001499), Point(x=31.826756437787186, y=90.4806513164539)] [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
# Řešení pomocí namedtuple:
import random
import itertools
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
# Vygenerování bodů
random.seed(42)
points = [Point(random.uniform(0, 100), random.uniform(0, 100)) for _ in range(10)]
def distance(point1,point2):
import math
return math.sqrt((point1.x-point2.x)**2 + (point1.y-point2.y)**2)
# řešení pomocí generátorů:
def average_distance(points):
distances = [distance(x, y) for (x, y) in itertools.combinations(points, 2)]
return sum(distances) / len(distances)
# řešení pomocí generátorů:
def closest_points(points):
dist_and_points = min((distance(x, y), x, y) for (x, y) in itertools.combinations(points, 2))
return dist_and_points # vzdálenost a body
#return dist_and_points[1:] # jen body
# alternativní řešení pomocí cyklu:
def average_distance1(points):
sum_distance = 0
n = 0
for pair in itertools.combinations(points, 2):
sum_distance += distance(*pair) # rozbalovací hvzdička
# sum_distance += distance(pair[0], pair[1]) # totéž
n += 1
return sum_distance / n
# alternativní řešení pomocí cyklu:
def closest_points1(points):
min_distance = distance(points[0], points[1])
closest = (points[0], points[1])
for pair in itertools.combinations(points, 2):
d = distance(pair[0], pair[1])
if d < min_distance:
min_distance = d
closest = pair
return min_distance, *closest # vzdálenost a body
# return closest # jen body
print(average_distance(points))
print(*closest_points(points))
print(average_distance1(points))
print(*closest_points1(points))
51.868588435878344 8.3929756676442 Point(x=21.863797480360336, y=50.53552881033624) Point(x=22.044062204069668, y=58.92656838759087) 51.868588435878344 8.3929756676442 Point(x=21.863797480360336, y=50.53552881033624) Point(x=22.044062204069668, y=58.92656838759087)
# Řešení pomocí complex:
import random
import itertools
# Vygenerování bodů
random.seed(42)
points = [ complex(random.uniform(0,100) , random.uniform(0,100)) for i in range(10)]
def distance(point1, point2):
return abs(point1 - point2)
# zbytek je stejný :-)
# řešení pomocí generátorů:
def average_distance(points):
distances = [distance(x,y) for (x,y) in itertools.combinations(points,2)]
return sum(distances) / len(distances)
# řešení pomocí generátorů:
def closest_points(points):
dist_and_points = min((distance(x,y), x, y) for (x,y) in itertools.combinations(points, 2))
return dist_and_points # vzdálenost a body
#return dist_and_points[1:] # jen body
# alternativní řešení pomocí cyklu:
def average_distance1(points):
sum_distance = 0
n = 0
for pair in itertools.combinations(points, 2):
sum_distance += distance(*pair) # rozbalovací hvzdička
# sum_distance += distance(pair[0], pair[1]) # totéž
n += 1
return sum_distance / n
# alternativní řešení pomocí cyklu:
def closest_points1(points):
min_distance = distance(points[0], points[1])
closest = (points[0], points[1])
for pair in itertools.combinations(points, 2):
d = distance(pair[0], pair[1])
if d < min_distance:
min_distance = d
closest = pair
return min_distance, *closest # vzdálenost a body
# return closest # jen body
print(average_distance(points))
print(*closest_points(points))
print(average_distance1(points))
print(*closest_points1(points))
51.868588435878344 8.392975667644198 (21.863797480360336+50.53552881033624j) (22.044062204069668+58.92656838759087j) 51.868588435878344 8.392975667644198 (21.863797480360336+50.53552881033624j) (22.044062204069668+58.92656838759087j)
2) Hluboká adresářová struktura¶
Napište program, který ve vámi zvoleném adresáři vytvoří stromovou strukturu adresářů. Struktura je parametrizována její hloubkou (počet úrovní zanoření) a množstvím větvení (kolik nových podstromů je v každé úrovni).
Názvy adresářů záleží na Vás. Můžete používat například čísla nebo písmena. Ukázka pro faktor větvení 2 a hloubku 3.
├── 1
│ ├── 1
│ │ ├── 1
│ │ └── 2
│ └── 2
│ ├── 1
│ └── 2
└── 2
├── 1
│ ├── 1
│ └── 2
└── 2
├── 1
└── 2
Následně zkuste pomocí os.system
zavolat příkaz tree <cesta_k_root_directory>
pro vizualizaci vaší struktury. Nezapomeňte <cesta_k_root_directory>
nahradit skutečnou hodnotou.
Nakonec strukturu po sobě smažte.
# volné místo na program
def generate_tree(root_directory, branch_factor, depth):
assert depth <= 6, 'Structure too deep'
assert branch_factor <= 6, 'Structure too wide'
# your code here
3) Opilá želva¶
Naprogramujte opilou želvu. Taková želva se pohybuje po obrazovce náhodným způsobem. Náhodně se otáčí a chodí náhodnou vzdálenost.
Poznámka: želvu je potřeba spouštět v nativním Pythonu na vašem nebo školním počítači. Zde v Jupyteru to nelze.
# volné místo na program
4) Argparse testování¶
Otevřete si soubor argparse_test.py a prohlédněte si obsah. Můžete ho pustit přímo z terminálu, nebo níže pomocí os.system
Experimentujte s různými parametry, které skriptu předáte.
Dobrovolně zkuste program modifikovat tak, aby mohl přijmout neomezené množství čísel a všechna sečíst. Může se hodit action='append'
z dokumentace.
# Spustime tento soubor bez parametru parametry
import os
os.system("python3 data/argparse_test.py")
usage: argparse_test.py [-h] [-s] [-r] cislo1 cislo2 argparse_test.py: error: the following arguments are required: cislo1, cislo2
512
# výpis nápovědy
os.system("python3 data/argparse_test.py --help")
usage: argparse_test.py [-h] [-s] [-r] cislo1 cislo2 Program pro výpočet součtu a rozdílu. positional arguments: cislo1 První číslo pro výpočty cislo2 Druhé číslo pro výpočty options: -h, --help show this help message and exit -s, --soucet Spočítat součet čísel -r, --rozdil Spočítat rozdíl čísel
0
os.system("python3 data/argparse_test.py 1 2")
Namespace(cislo1=1, cislo2=2, soucet=False, rozdil=False) Není vybrána žádná operace.
0
os.system("python3 data/argparse_test.py 1 2 --soucet")
Namespace(cislo1=1, cislo2=2, soucet=True, rozdil=False) Součet: 3
0
os.system("python3 data/argparse_test.py 1 2 --rozdil")
Namespace(cislo1=1, cislo2=2, soucet=False, rozdil=True) Rozdíl: -1
0
os.system("python3 data/argparse_test.py 1 2 --r")
Namespace(cislo1=1, cislo2=2, soucet=False, rozdil=True) Rozdíl: -1
0
5) Argparse - program na modifikaci souborů¶
Napište program, který s použitím modulu argparse
bude očekávat argument --input-file
, kde mu předáme cestu k nějakému textovému souboru.
Program daný soubor načte a na obrazovku vypíše modifikovaný obsah - vše velkými písmeny.
Soubory na testování můžete nalézt například ve složce data
, která byla využívána během cvičení 19, kdy jsme se učili, jak pracovat se soubory.
Program napište do zvláštního souboru s příponou .py
. Můžete buď zde na JupyterHubu nebo na vašich počítačích v prostředí VSCodium. Spouštět takový program je nejlépe ručně z příkazové řádky, kdy můžete jednoduše specifikovat argumenty při spuštění. Terminál je dostupný i zde na Jupyteru.
# volné místo na program
os.system("python3 data/argparse_vypis.py --help")
usage: argparse_vypis.py [-h] --input-file INPUT_FILE [--output-file OUTPUT_FILE] Program pro práci se soubory. options: -h, --help show this help message and exit --input-file INPUT_FILE Název vstupního souboru --output-file OUTPUT_FILE Název výstupního souboru
0
# volné místo na program
os.system("python3 data/argparse_vypis.py --input-file data/data.txt")
Namespace(input_file='data/data.txt', output_file=None) NĚJAKÝ TEXTOVÝ SOUBOR, KTERÝ OBSAHUJE VÍCE ŘÁDKŮ.
0
6) Argparse - program na modifikaci souborů #2¶
Rozšiřte předchozí program tak, že bude obsahovat další volitelný parametr --output-file
. Pokud bude použit, program by měl výstup uložit do tohoto souboru.
Experimentujte s dalšími možnostmi argparse.
# volné místo na program
os.system("python3 data/argparse_vypis.py --input-file data/data.txt --output-file data/out.txt")
Namespace(input_file='data/data.txt', output_file='data/out.txt')
0
# volné místo na program
os.system("python3 data/argparse_vypis.py --input-file data/data.txt")
Namespace(input_file='data/data.txt', output_file=None) NĚJAKÝ TEXTOVÝ SOUBOR, KTERÝ OBSAHUJE VÍCE ŘÁDKŮ.
0