Prednáška 3: Funkcie, pokročilé funkcie, výnimky a práca so súbormi¶
Obsah¶
- Pravidlá pre formátovanie
- Základné funkcie
- Pokročilejšie funkcie
- Výnimky (exceptions)
- Práca so súbormi (File I/O)
- Zhrnutie
1. Pravidlá pre formátovanie¶
Ak nebudete dodržiavať odsadzovanie, interpreter vypíše chybu a program nebude spustený. Aby ste zlepšili čitateľnosť vášho kódu, je dobré dodržiavať nasledujúce konvencie:
- Rozhodnite sa, ako budete ohraničovať reťazce a dodržiavajte jeden spôsob v celom kóde (ohraničenia môžete meniť, ak reťazec obsahuje
'
alebo"
). - Premenné a funkcie označujte názvami s malými písmenami. Viacslovné názvy oddeľujte
_
(napr.process_data
). - Konštanty (premenné, ktoré sa nebudú pri spustení meniť) pomenujte veľkými písmenami s
_
, napr.DEFAULT_VALUE
. - Vždy oddeľte operátory
=
,+=
,-=
,==
,!=
,<
,>
,<=
,>=
,is
,in
a boolovské spojkyor
,and
,not
medzerami (napr.x < 10
, niex<10
). - Vyhnite sa vkladaniu medzier hneď za/pred
[/]
,(/)
, alebo{/}
(napr.x[10]
namiestox[ 10 ]
,f(x)
namiestof( x )
,{'x': 'y'}
namiesto{ 'x' : 'y' }
).
Ďalšie odporúčania nájdete tu (v angličtine).
def print_value(value):
if value is None:
return # ‘return’ ukončí funkciu, nasledujúci print sa nevykoná
print(value)
# Zavoláme definovanú funkciu a predáme jej parameter value = 123
print_value(123)
- Táto funkcia nič nevracia (implicitná návratová hodnota je
None
). - Ak chceme, aby funkcia vrátila hodnotu:
def sum_squares(data):
"""
Computes sum of squares of values in the specified sequence.
"""
if len(data) == 0: # pre prázdny zoznam vrátime None
return None
sumsq = 0
for x in data:
sumsq += x * x
return sumsq # na konci vrátime sumu štvorcov
result = sum_squares([1, 2, 3]) # = 14
print(result)
2.2 Dokumentačné reťazce (docstring)¶
- Na prvý riadok funkcie môžeme umiestniť docstring:
def sum_squares(data): """ Computes sum of squares of values in the specified sequence. """ # ...
- Tieto reťazce využíva funkcia
help(...)
a nástroje na generovanie dokumentácie.
help(sum_squares)
help(sum_squares)
2.3 Prednastavené hodnoty parametrov¶
Môžeme definovať parametre s prednastavenou hodnotou. Všetky takéto parametre musia byť za nepovinnými parametrami.
def print_operation(x, y, opr="+", none_value="?"):
val_x = none_value if x is None else str(x)
val_y = none_value if y is None else str(y)
print(val_x + " " + opr + " " + val_y)
print_operation(1, None, "*", "[none]") # 1 * [none]
print_operation(1, None, "*") # 1 * ?
print_operation(x=10, y=20, opr="-") # 10 - 20
(Nepovinné parametre spravidla nepíšeme s medzerou okolo =
.)
2.4 Premenný počet parametrov (*args
, **kwargs
)¶
*args
slúži na ľubovoľný počet pozičných argumentov.- **
**kwargs
** slúži na ľubovoľný počet menovaných argumentov.
def print_list(name, *args):
print(name + ": [" + ", ".join(args) + "]")
print_list("basket") # basket: []
print_list("basket", "apple", "orange") # basket: [apple, orange]
(Tu args
bude n-tica. Ak by tam bolo **kwargs
, dostaneme slovník.)
def user_profile(id, **kwargs):
print("id =", id)
print("Other info:", kwargs)
user_profile(10, name="Adam", country="SK")
3. Pokročilejšie funkcie¶
V tejto časti si ukážeme anonymné funkcie (lambda
), rekurziu a vysvetlíme si, ako funguje scoping (rozsah platnosti premenných).
3.1 Anonymné funkcie (lambda
)¶
lambda
vytvorí krátku, bezmennú funkciu “za behu”.- Typicky sa používa pri triedení (ako
key
), mapovaní, filtrovaní.
words = ["banana", "Apple", "pear", "BANANA", "Cherry", "grape", "apricot"]
words.sort() # Štandardné zoradenie v Pythone
print(words)
words = ["banana", "Apple", "pear", "BANANA", "Cherry", "grape", "apricot"]
# anonymná funkcia: lambda x: x.lower()
words.sort(key=lambda x: x.lower())
print(words) # ['apple', 'banana', 'pear']
(Ak potrebujeme dlhú logiku, radšej napíšeme normálnu funkciu def
.)
3.2 Rekurzia¶
- Funkcia, ktorá volá samú seba.
- Musí mať základný prípad (base case), aby nezostala vo “večnom” volaní.
def factorial(n):
if n < 0:
raise ValueError("n must be >= 0")
if n <= 1:
return 1
return n * factorial(n-1)
print(factorial(5)) # 120
(Rekurzia sa hodí pri algoritmoch, ktoré sa prirodzene rozkladajú na menšie podproblémy, napr. prehľad stromov, rekurzívne výpočty.)
3.3 Rozsah platnosti premenných (scoping)¶
- Python hľadá premenné podľa LEGB pravidla: Local, Enclosing, Global, Built-in.
- Lokálne premenné sú definované vo vnútri funkcie.
- Globálne premenné môžeme čítať, ale ak ich chceme meniť, potrebujeme kľúčové slovo
global
. To sa však často neodporúča.
x = 10 # globálna premenná
def outer():
x = 5 # lokálna pre outer
def inner():
print("From inner:", x)
inner()
outer()
print("From global:", x) # 10
(Buďme opatrní s používaním globálnych premenných – radšej parametre funkcií.)
def divide(a, b):
try:
return a / b
except :
print("Chyba: Delenie nulou!")
return None
print(divide(10, 2)) # 5.0
print(divide(10, 0)) # None a "Chyba: Delenie nulou!"
Ak chceme zachytiť všetky chyby, môžeme použiť except Exception:
, ale zvyčajne je lepšie byť konkrétnejší.
4.2 Bloky else
a finally
¶
else
sa vykoná, ak vtry
nenastala výnimka.finally
sa vykoná vždy (aj pri výnimke, aj bez nej).
try:
f = open("data.txt", "r")
except FileNotFoundError:
print("Súbor neexistuje!")
else:
content = f.read()
f.close()
print("Načítaný obsah má dĺžku:", len(content))
finally:
print("Toto sa vykoná vždy.")
4.3 Vyvolanie vlastnej výnimky (raise
)¶
Funkcia môže v prípade neplatných vstupov sama vyvolať výnimku:
def set_age(age):
if age < 0:
raise ValueError("Age must be >= 0")
print(f"Vek: {age}")
set_age(-1)
5. Práca so súbormi (File I/O)¶
V tejto sekcii sa rozšírime aj o čítanie/zápis JSON a načítanie obrázkov (alebo iných binárnych súborov).
5.1 Základné otváranie súborov¶
Najlepšie je použiť kontextový manažér with open(...) as f:
. Po skončení bloku sa súbor automaticky zatvorí, aj keby nastala výnimka.
with open("data/example.txt", "r") as f:
content = f.read()
print(content)
# po skončení bloku with je f automaticky zatvorené
- Mód
"r"
: čítanie, - Mód
"w"
: zápis (vymaže existujúci obsah), - Mód
"a"
: pridanie na koniec, - Mód
"rb"
: čítanie v binárnom režime (vhodné pre obrázky, PDF...), - Mód
"wb"
: zápis v binárnom režime.
5.2 Čítanie a zápis textu¶
# ČÍTAJ:
with open("data/example.txt", "r") as f:
lines = f.readlines()
for line in lines:
line = line.strip()
print(">", line)
with open("data/example.txt", "r") as f:
for line in f: # Iterujeme cez riadky bez načítania celého súboru do pamäte
line = line.strip() # Odstránime medzery a nový riadok
print(">", line)
# ZAPISUJ:
with open("data/output.txt", "w") as f:
f.write("Riadok 1\n")
f.write("Riadok 2\n")
Rozdiely medzi týmito prístupmi:¶
Metóda | Popis | Pamäťová efektivita | Kedy použiť |
---|---|---|---|
f.readline() |
Číta jeden riadok po druhom. | Efektívna na veľké súbory | Keď chceš spracovať riadky postupne. |
f.read() |
Prečíta celý obsah súboru naraz. | Môže vyčerpať pamäť | Keď potrebuješ celý obsah naraz ako reťazec. |
for line in f: |
Iteruje cez riadky postupne bez načítania celého súboru do pamäte. | Najefektívnejšie | Na postupné čítanie veľkých súborov. |
5.3 Práca s JSON¶
Čo je JSON?¶
- JSON (JavaScript Object Notation) je formát na ukladanie a výmenu dát.
- Bol navrhnutý pre JavaScript, ale je nezávislý od konkrétneho jazyka.
- V Pythone sa veľmi jednoducho pracuje s JSON pomocou modulu
json
.
Využitie JSON-u¶
- V API – pri komunikácii medzi serverom a klientom (napr. webové aplikácie).
- Ukladanie nastavení alebo konfigurácií v rámci projektu.
- Dátová výmena medzi rôznymi programami a platformami.
Formát JSON vs. Python štruktúry¶
JSON | Python | Príklad |
---|---|---|
Objekt (object) | Slovník (dict) | {"name": "Peter"} |
Pole (array) | Zoznam (list) | ["Ahoj", "Hello"] |
Reťazec (string) | Reťazec (str) | "Ahoj" |
Číslo (number) | int / float | 21 alebo 3.14 |
Boolean | bool (True , False ) |
true / false (v JSON) |
null |
None |
null (v JSON) |
Praktická ukážka v Pythone¶
Predpokladajme, že máme súbor data.json
s týmto obsahom (pozor – musí byť v platnom JSON formáte, takže používame dvojité úvodzovky okolo kľúčov a reťazcov):
{
"students": [
{
"name": "Ján Novák",
"age": 21,
"subjects": ["Matematika", "Fyzika", "Programovanie"],
"average_grade": 1.5
},
{
"name": "Mária Kováčová",
"age": 22,
"subjects": ["Biológia", "Chémia", "Angličtina"],
"average_grade": 1.7
}
],
"course": {
"name": "Základy Pythonu",
"duration_weeks": 10,
"instructor": "Ing. Viera Krešňáková, PhD."
},
"schedule": [
{"day": "Pondelok", "time": "9:00-11:00"},
{"day": "Streda", "time": "14:00-16:00"}
]
}
Krok 1: Načítanie JSON súboru¶
import json
with open("data/data.json", "r", encoding="utf-8") as f:
data = json.load(f)
data
print(json.dumps(data, ensure_ascii=False, indent=4))
- json.load(f): Načíta JSON zo súboru a prevedie ho na Pythonovskú štruktúru.
- json.dumps(...): Slúži na prevod Python objektu na formátovaný reťazec JSON (tu len pre ukážku).
Krok 2: Prístup k údajom¶
# Názov kurzu
print("Názov kurzu:", data["course"]["name"])
# Počet študentov
print("Počet študentov:", len(data["students"]))
# Predmety prvého študenta
print("Predmety prvého študenta:", data["students"][0]["subjects"])
# Rozvrh
for item in data["schedule"]:
print(f"{item['day']}: {item['time']}")
- Tu pracujeme s
data
ako so slovníkom (dict) a zoznamami (list).
Krok 3: Manipulácia s dátami¶
# 1. Pridanie nového študenta
new_student = {
"name": "Peter Horváth",
"age": 23,
"subjects": ["Matematika", "Programovanie"],
"average_grade": 1.3
}
data["students"].append(new_student)
# 2. Aktualizácia rozvrhu
data["schedule"].append({"day": "Piatok", "time": "10:00-12:00"})
data
- Vďaka tomu, že
data["students"]
je zoznam, môžeme naň použiť bežné metódy akoappend()
. - Podobne aktualizujeme rozvrh vo vnorenom zozname
data["schedule"]
.
Krok 4: Uloženie zmien do nového JSON súboru¶
# Uloženie výsledných dát do súboru
with open("data/updated_data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
print("Dáta boli uložené do súboru 'updated_data.json'")
- json.dump(obj, f): Zapíše Python objekt
obj
do súboruf
vo formáte JSON. ensure_ascii=False
zachová diakritiku,indent=4
zabezpečí “pekné” odsadenie.
Výsledok (skrátená ukážka)¶
{
"students": [
{
"name": "Ján Novák",
"age": 21,
"subjects": ["Matematika", "Fyzika", "Programovanie"],
"average_grade": 1.5
},
{
"name": "Mária Kováčová",
"age": 22,
"subjects": ["Biológia", "Chémia", "Angličtina"],
"average_grade": 1.7
},
{
"name": "Peter Horváth",
"age": 23,
"subjects": ["Matematika", "Programovanie"],
"average_grade": 1.3
}
],
"course": {
"name": "Základy Pythonu",
"duration_weeks": 10,
"instructor": "Ing. Viera Krešňáková, PhD."
},
"schedule": [
{"day": "Pondelok", "time": "9:00-11:00"},
{"day": "Streda", "time": "14:00-16:00"},
{"day": "Piatok", "time": "10:00-12:00"}
]
}
Tipy a dôležité poznámky¶
Štruktúra JSON je podobná Python slovníkom a zoznamom, ale:
- V JSON sa kľúče a reťazce píšu do dvojitých úvodzoviek.
True
/False
aNone
musia byť v JSON formátetrue
/false
anull
.
Ošetrenie chýb
- Pri načítavaní dát môže nastať chyba, ak súbor neexistuje (
FileNotFoundError
) alebo je JSON poškodený (json.JSONDecodeError
). - Preto je vhodné používať blok
try/except
:
try: with open("data.json") as f: data = json.load(f) except FileNotFoundError: print("Súbor neexistuje!") except json.JSONDecodeError: print("Neplatný JSON formát!")
- Pri načítavaní dát môže nastať chyba, ak súbor neexistuje (
Zápis a čítanie
- Na zápis do súboru sa používa
json.dump()
. - Na vytvorenie JSON reťazca (napr. na posielanie cez sieť) sa používa
json.dumps()
.
- Na zápis do súboru sa používa
Použitie
ensure_ascii=False
- Ak nechceš mať v JSON “pseudounicode” zápisy (napr.
\u2019
), použi parameterensure_ascii=False
. - Pri potrebe formátovaného JSON použijeme
indent=2
aleboindent=4
.
- Ak nechceš mať v JSON “pseudounicode” zápisy (napr.
Zhrnutie¶
- JSON je univerzálny formát na ukladanie a výmenu dát.
- V Pythone stačí
import json
a môžeš pohodlne načítať aj zapisovať JSON. - Pre prácu s načítanými dátami je dôležité vedieť, že JSON objekt je v Pythone najčastejšie premenený na slovník (dict) a polia na zoznamy (list).
- Výhodou JSON je jednoduchosť a široká podpora v rôznych jazykoch a nástrojoch.
5.4 Binárne súbory (obrázky, PDF...)¶
1. Čo sú binárne súbory?¶
- Binárne dáta (obrázky *.jpg/*.png, PDF, MP3, atď.) sa líšia od textových súborov tým, že neobsahujú čitateľný (textový) obsah, ale bajty v špecifickom formáte.
- Pri čítaní textových súborov sa Python stará o dekódovanie (encoding). Pri binárnych súboroch nič také neprebieha – len číta alebo zapisuje surové bajty.
2. Ako čítať binárne súbory?¶
- Pri čítaní binárnych dát zvyčajne otvárame súbor v móde
"rb"
(read binary). - Výsledok čítania je dátový typ
bytes
, ktorý obsahuje surové binárne dáta.
Príklad: načítanie obrázka¶
with open("data/obrazok.jpg", "rb") as f:
data = f.read()
print(type(data)) # <class 'bytes'>
# Tu môžeš robiť napr. ďalšie spracovanie alebo odoslať dáta po sieti
3. Ako zapisovať binárne súbory?¶
- Pri zápise binárnych dát použijeme mód
"wb"
(write binary). - Očakáva sa, že budeme zapisovať bytes objekty.
data = b"toto su binarne data" # reťazec typu bytes (ukážka)
with open("data/novy_subor.bin", "wb") as f:
f.write(data)
4. Čítanie/zápis po blokoch¶
Pri práci s veľkými súbormi je efektívnejšie čítať alebo zapisovať postupne po blokoch (napr. 1 MB) namiesto načítania celého súboru naraz do pamäte.
block_size = 1024 # Veľkosť bloku v bajtoch (napr. 1 kB)
with open("data/obrazok.jpg", "rb") as source, open("kopiu_obrazok.jpg", "wb") as dest:
while True:
chunk = source.read(block_size)
if not chunk: # Ak nič nebolo načítané, končíme
break
dest.write(chunk)
5. Zhrnutie¶
- Binárny mód (
"rb"
,"wb"
) je nevyhnutný pri práci so súbormi, ktoré obsahujú iné dáta ako obyčajný text. - Výsledkom čítania je objekt typu
bytes
, ktorý môžeme:- Kopírovať,
- Posielať po sieti,
- Kódovať/dekódovať podľa potreby,
- Ďalej spracovávať špecifickými knižnicami (napr. knižnica na čítanie PDF).
- Pri manipulácii s veľkými súbormi čítame a zapisujeme blokovo, aby sme nevyťažili zbytočne pamäť.
# !pip install Pillow # v Jupyter Notebooku, ak nemáš nainštalované
from PIL import Image
img = Image.open("data/obrazok.jpg")
print(img.size) # (šírka, výška)
img = img.resize((100, 100))
img.save("resized.jpg")
img
6. Zhrnutie¶
- Základné a pokročilé funkcie: Definícia s
def
, návratové hodnoty, docstringy, prednastavené parametre,*args
,**kwargs
, anonymné funkcielambda
a rekurzia. - Výnimky:
try/except
,else
,finally
,raise
– ako zachytiť alebo vyvolať chybové stavy. - Práca so súbormi:
- Textový režim pre
.txt
,.csv
, atď. - Binárny režim (
rb
,wb
) pre obrázky, PDF a podobne. - JSON:
import json
,json.load()
,json.dump()
– veľmi častý formát na ukladanie/ prenos dát.
- Textový režim pre
Týmto máš ucelený prehľad o písaní vlastných funkcií (od jednoduchých k pokročilým), ošetrovaní chýb pomocou výnimiek a o čítaní rôznych typov súborov v Pythone.