18. diel - Funkcie v Pythone
V minulej lekcii, Cykly v Pythone druhýkrát - Výraz pass, break a continue, sme ucelili naše znalosti cyklov ďalšími
konštrukciami a kľúčovými slovami pass, break a
continue.
V dnešnom tutoriáli Pythonu sa naučíme funkcionálny štýl programovania. Pozrieme sa na deklaráciu funkcií, ukážku parametrov a návratových hodnôt.
Funkcie
Doteraz sme programy písali imperatívne - urob tento príkaz, následne tamten a tak ďalej. Týmto spôsobom je možné písať jednoduché a krátke programy. Väčšie programy by však boli veľmi neprehľadné. Preto prejdeme na ďalšiu programovaciu paradigmu (spôsob, ako niečo naprogramovať) – na funkcionálne programovanie. Náš program si rozdelíme na menšie časti (podproblémy), ktoré vyriešime samostatne. Jednotlivé problémy riešia funkcie. Pre funkcionálny štýl programovania môžeme použiť všetko, čo sme sa doteraz naučili.
Funkcia zvyčajne prijíma argumenty (dáta, ktoré funkcia
spracuje) a niečo vracia, napríklad výslednú hodnotu.
Nemusí však vracať ani nič – ako napr. funkcia print().
Základná syntax funkcie
Funkcia sa definuje pomocou kľúčového slova def a výslednú
hodnotu vracia kľúčovým slovom return. Za def sa
píše medzera a potom názov funkcie. Za názov funkcie sa dávajú jednoduché
zátvorky, do ktorých sa píšu názvy jednotlivých argumentov. Argumentom
funkcie v programovacom jazyku Python je hodnota alebo premenná, ktorej
odovzdávame funkciu, aby hodnotu alebo premennú mohla použiť počas svojho
vykonávania. Keď funkciu definujeme, špecifikujeme, aké argumenty môže
prijať. Potom, keď funkciu voláme, dosadzujeme hodnoty pre tieto argumenty.
Funkcia môže byť aj bez argumentov. Na konci prvého riadku
sa píše dvojbodka. Telo funkcie sa štandardne odsadzuje:
def power(number): number = number ** 2 return number
Takto vytvorená funkcia power() vracia číslo umocnené na
druhú. Napríklad pri zavolaní power(1) vráti 1,
pri zavolaní power(2) vráti 4 atď. V praxi to
vyzerá takto:
def power(number): # number is the argument name
number = number ** 2
return number
first_number = power(2) # 2 is the value passed to the function
print(first_number)
Argumentov môže byť samozrejme aj viac:
def product(first_number, second_number, third_number):
number = first_number * second_number * third_number
return number
example = product(2, 3, 4)
print(example)
Funkciu môžeme tiež použiť ako argument inej funkcie:
def product(first_number, second_number, third_number):
number = first_number * second_number * third_number
return number
print(product(2, 3, 4)) # we use our function as an argument of the print() function
Druhy argumentov funkcie
V Pythone máme dva druhy argumentov:
- pozičné,
- kľúčové.
Pozičné argumenty
Pozičné argumenty sme videli vyššie. Na ich pozícii sa dosadí argument
na rovnakej pozícii pri volaní funkcie. Tieto argumenty nemajú danú
základnú hodnotu. Ich syntax je jednoduchá: argument_name.
Kľúčové argumenty
Kľúčové argumenty majú už vopred nastavenú hodnotu, ktorú je možné
zmeniť. Na rozdiel od argumentov pozičných sú tie kľúčové
označené kľúčovým slovom (majú svoj názov). Tieto
argumenty nemusia byť pri volaní funkcie zadané v poradí, v ktorom sú
deklarované. Navyše ich nemusíme pri volaní funkcie inicializovať (určiť
ich hodnotu). V takom prípade sa použije ich východisková
hodnota. Syntax vyzerá takto: argument_name=value.
Všetky pozičné argumenty musia byť deklarované pred tými kľúčovými!
Ako príklad si ukážme vylepšenú verziu funkcie na výpočet mocniny:
def power(base, exponent=2): # base is a positional argument, exponent is a keyword argument
result = base ** exponent
return result
print(power(2))
Prvý argument je pozičný, druhý je kľúčový. Teraz môžeme volať
power(1), power(1, exponent=2), prípadne
power(1, 2) a dostaneme rovnaký výsledok.
Navyše môžeme umocniť 3 na 4 –
power(3, exponent=4). To už však musíme hodnotu exponentu
špecifikovať:
def power(base, exponent=2):
result = base ** exponent
return result
print(power(3, exponent=4))
Všeobecne sa pozičné argumenty zapisujú ako
args a kľúčové ako kwargs.
Zvláštnou vlastnosťou Pythonu je to, že kľúčový argument (kwarg) môžeme zadávať aj ako obyčajný argument (arg), ak jeho poradie zodpovedá deklarácii funkcie.
Ako príklad si ešte raz ukážme našu funkciu power():
def power(base, exponent=2): # base is a positional argument, exponent is a keyword argument
result = base ** exponent
return result
print(power(3, 4)) # here we called the keyword argument exponent as a regular positional argument
Operátor *
V Pythone operátor * neslúži len na násobenie. Keď ho
použijeme v definícii funkcie, umožňuje nám zachytávať premenný počet
pozičných argumentov. Týmto spôsobom môžeme flexibilne pracovať s rôznym
množstvom vstupných hodnôt. Uveďme si príklad:
def some_function(*positional_arguments): pass
V tomto prípade sa všetky zadané pozičné argumenty odovzdané funkcii
zhromaždia do n-tice (dátový typ podobný zoznamu) s názvom
positional_arguments. S touto n-ticou môžeme ďalej pracovať,
napríklad ju prechádzať pomocou cyklu for:
def product(*numbers):
result = 1
for number in numbers:
result = result * number
return result
print(product(2, 3, 4, 5))
Keď teda zavoláme funkciu product(2, 3, 4, 5), všetky štyri
čísla sú zbalené do n-tice numbers a v tele funkcie sú
následne prístupné ako numbers[0], numbers[1],
numbers[2] a numbers[3]. N-ticu potom jednoducho
prejdeme pomocou cyklu for. Vďaka tejto vlastnosti môžeme
funkciu product() volať s ľubovoľným počtom čísel.
Keď použijeme * v definícii funkcie bez
nasledujúceho mena premennej, hovoríme tým, že funkcia smie od
tohto miesta ďalej prijímať iba kľúčové argumenty.
Inými slovami, všetky argumenty za * musia byť pri volaní
funkcie špecifikované ako kľúčové.
Ukážme si to na konkrétnom príklade:
def my_function(*, first_keyword_arg=1, second_keyword_arg=1): print(first_keyword_arg, second_keyword_arg)
V tomto prípade nám funkcia nedovolí použiť pozičné argumenty. Musíme ich špecifikovať ako kľúčové argumenty:
my_function(first_keyword_arg=5, second_keyword_arg=10) # output: 5 10 # The following call would raise an error: # my_function(5, 10) # TypeError: my_function() takes 0 positional arguments but 2 were given
Ak chceme použiť zápis s operátorom * pre
kľúčové argumenty, napíšeme dve hviezdičky.
Rekurzia
Pojem rekurzia označuje zápis kódu, kedy funkcia volá samu seba. Rekurziu môžeme použiť napríklad na výpočet faktoriálu. Uveďme si príklad:
def factorial(number): if number > 0: return factorial(number - 1) * number else: return 1
Pri rekurzii si musíme dať pozor, aby sa funkcia niekedy ukončila. Inak program spadne kvôli pretečeniu zásobníka. Rekurzie podrobne vysvetľujeme pri algoritme faktoriálu.
Typovanie funkcií
Ak chceme explicitne deklarovať typ parametrov funkcií a ich návratové
hodnoty, použijeme na to operátor ->. Pozrime sa na
príklad:
def generate_hello(name: str) -> str: # the return value of the function will be str return "Hello, " + name + "!"
V rozsiahlejších projektoch je typovanie obzvlášť užitočné pre udržanie kvality a konzistencie kódu. Uľahčuje spoluprácu viacerých vývojárov a pomáha pri zachovaní dobrej architektúry.
Mimochodom, podobne postupujeme aj u premenných. Len operátor je iný. Ak
chceme explicitne deklarovať typ premennej, použijeme na to dvojbodkový
operátor ::
text: str = "Hello World!"
Teraz je jasne povedané, že text je typu str. V
tomto prípade to možno spoznať podľa hodnoty "Hello World!",
takže také označenie je tu trochu nadbytočné. V programoch v praxi však
býva veľa miest, kde to už také jasné nie je. Potom má deklarovanie typu
zmysel.
Úprava výstupu funkcie
print()
Teraz sa naučíme upraviť si funkciu print(). Už sme sa s
tým čiastočne stretli v predchádzajúcich lekciách, keď sme upravovali,
čím funkcia print() ukončí riadok. Teraz sa na ňu pozrieme
podrobnejšie. Najprv sa zameriame na jej dva kľúčové argumenty:
sep– Argument udáva medzery medzi jednotlivými prvkami (pozičnými argumentmi). Normálne je nastavený na medzeru (" ").end– Tento argument definuje, čím sa zápis ukončí. Normálne sa tak deje znakom nového riadka ("\n").
Poďme si to vyskúšať na príklade:
print(1, 2, 3, "a", sep="-")
print("No new line", end=" ")
print("will appear", end=" ")
Zhrnutie lekcie
Funkcie nám pomáhajú rozdeliť program na menšie časti, aby bol
prehľadnejší a ľahšie sa upravoval. Definujeme ich pomocou kľúčového
slova def a výsledok z nich vraciame príkazom
return. Funkcie môžu prijímať argumenty, teda hodnoty, s
ktorými vnútri pracujú. Pozičné argumenty sa odovzdávajú podľa poradia,
zatiaľ čo kľúčové argumenty určujeme názvom a môžeme im nastaviť
predvolenú hodnotu. Pomocou * môžeme prijať ľubovoľný počet
argumentov. Funkcia môže volať samu seba, čomu hovoríme rekurzia, ale vždy
musí mať podmienku ukončenia. Pri funkciách aj premenných môžeme
zapisovať typové anotácie, ktoré sprehľadňujú kód a uľahčujú jeho
kontrolu.
V nasledujúcej lekcii, Matematické funkcie v Pythone a knižnica math, sa pozrieme na užitočné matematické funkcie.
