O funkciách som písal vlastne už od začiatku seriálu. Boli to rôzne vstavané funkcie Pythonu, či už funkcie (metódy) dátových typov, modulu math alebo základné funkcie ako print()
, input()
, range()
atď. Pre vysvetlenie, ako funkcie fungujú, si ukážeme ako ich vytvárať.
Na vytvorenie funkcie v Pythone sa používa slovíčko def, za ktorým nasleduje názov funkcie, okrúhle zátvorky obsahujúce názvy parametrov pre funkciu a dvojbodka, tak ako tomu je aj pri cykloch či podmienkach.
def function(parameter1, parameter2): #something
Jednoduchá funkcia
Funkcia funkcie spočíva v tom, že do nej vieme „zabaliť“ nejaké príkazy, ktoré môžeme zavolaním funkcie spustiť z ľubovoľného miesta programu. Samozrejme funkciu musíme pred použitím najprv definovať. Príklad vytvorenia jednoduchej funkcie bez parametrov a jej volanie ukážem v interpreteri a vysvetlím komentármi.
>>> def hello(): # definovanie funkcie hello(), ktorá neprijme žiaden argument ... print("Hi!") # osadený blok, ktorý sa vykoná pri zavolaní funkcie ... >>> hello() # zavolanie funkcie bez argumentov Hi! >>> hello(2) # zavolanie funkcie s argumentom 2, Python sa bude sťažovať Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: hello() takes 0 positional arguments but 1 was given >>> 5+5 10 >>> print("Nenáhodný text.") Nenáhodný text. >>> hello() # znovu zavolanie funkcie Hi! >>> for i in range(3): # cyklus for 3-krát po sebe zavolá funkciu hello() ... hello() ... Hi! Hi! Hi!
Funkcia môže volať aj sama seba, čím môže vzniknúť cyklus:
def function(): print("!> Pre zastavenie zadajte: \"exit\" bez úvodzoviek.") inpul = input("?> ") if inpul != "\"exit\" bez úvodzoviek.": if inpul == "exit": print("!> hahaha") function() function() print("!> Gratulujem! Podarilo sa vám zastaviť program.")
Výstup:
$ python fifth.py !> Pre zastavenie zadajte: "exit" bez úvodzoviek. ?> Prečo? !> Pre zastavenie zadajte: "exit" bez úvodzoviek. ?> exit !> hahaha !> Pre zastavenie zadajte: "exit" bez úvodzoviek. ?> ??? !> Pre zastavenie zadajte: "exit" bez úvodzoviek. ?> "exit" bez úvodzoviek. !> Gratulujem! Podarilo sa vám zastaviť program.
Argument vs. parameter
Poznámka autora: Jeden z dôvodov písania seriálu o Pythone je aj ten, že som sa sám chcel zdokonaliť tým, že si jednotlivé veci musím podrobne prejsť a pokúsiť sa ich vysvetliť. Teraz som narazil na rozdiel medzi parametrom a argumentom funkcie, o ktorom som do teraz vlastne ani nevedel.
Parameter funkcie je premenná zapísaná pri definovaní funkcie. Premenná s takýmto názvom je dostupná vrámci funkcie.
def function(parameter): print(parameter)
Argumentom je premenná alebo akýkoľvek vstup pri volaní funkcie.?
function(argument)
Znovu komentovaný príklad:
>>> def hello(name): # definovanie funkcie s parametrom name ... print("Hello "+str(name)) # využitie parametru – premenná name ... >>> hello("Adam") # volanie funkcie s argumentom "Adam" Hello Adam >>> hello() # zavolanie funkcie bez argumentu spôsobí chybu Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: hello() missing 1 required positional argument: 'name'
Voliteľný parameter
Pokiaľ potrebujeme, môžeme obsah parametru funkcie predefinovať už pri vytváraní funkcie.
def function(param=0): print(param)
Teraz pokiaľ funkciu zavoláme bez argumentu, premenná param vo funkcii bude obsahovať 0. Ak pri volaní funkcie určíme argument, premenná param nebude obsahovať 0, ale náš argument. Pre ukážku vylepším hore uvedený príklad funkcie hello()
:
>>> def hello(name="world"): # premenná name má priradenú hodnotu "world" ... print("Hello {}.".format(name)) ... >>> hello("Adam") # volanie funkcie s argumentom prepíše priradenie name="world" Hello Adam. >>> hello() # volanie bez argumentu použije premennú name s hodnotou "world" Hello world. >>> hello("") # aj prázdny reťazec je platným argumentom Hello .
Parametre pri volaní funkcie nemusíme definovať v určenom poradí, pokiaľ pri volaní funkcie zapíšeme, ktorá premenná sa rovná akej hodnote. Príklad ukážem na funkcii, ktorá počíta diskriminant kvadratickej rovnice.
>>> def discriminant(a, b=0, c=0): # parameter a je povinný, b a c sú voliteľné ... print("D={b}^2-4*{a}*{c}".format(a=a, b=b, c=c)) ... d = b**2-4*a*c ... print("D={}".format(d)) ... >>> discriminant(5) # teraz sa a=5, b a c sa rovnajú 0 D=0^2-4*5*0 # rovnica: 5x^2=0 D=0 >>> discriminant(1, c=8) # prvý argument je vždy a, parameter b nedefinujeme D=0^2-4*1*8 # rovnica: 5x^2+8=0 D=-32 >>> discriminant(1, 5, 6) # platí rovnaké poradie parametrov D=5^2-4*1*6 # rovnica: 5x^2+5x+6=0 D=1 >>> discriminant(b=4, c=8) # param. a je povinný - takéto volanie spôsobí chybu Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: discriminant() missing 1 required positional argument: 'a'
Vrátenie hodnoty – return
Funkcie väčšinou neslúžia len na vypísanie nejakých údajov cez print. Oveľa využiteľnejšie je, keď nám funkcia vráti nejakú hodnotu, ktorú vieme zapísať do premennej alebo s ňou rovno pracovať. Vrátenie hodnoty nám zabezpečí práve slovíčko return.
>>> def increase(a): ... return a+1 ... >>> increase(5) # vypísanie nastalo len kvôli spusteniu v interpreteri* 6 >>> value = increase(5) # priradenie premennej value výstup funkcie >>> print(value) 6 >>> value2 = increase(increase(10)) # takisto funkčné >>> print(value2) 12
*V prípade, že by sme takto funkciu spustili v súbore, funkcia sa síce vykoná, ale bez toho, aby sme uvideli nejaký výsledok.
Záver
O funkciách toto ešte nieje všetko a v pokračovaní seriálu si ešte podrobnejšie vysvetlíme fungovanie return, povieme si niečo o doctring funkcií a ukážeme si ako zapísať funkciu tak, aby vedela pracovať s ľubovoľným počtom argumentov.
Nezabudnime na vylepšenie nášho second.py o funkcie. :)
#!/usr/bin/env python3 def input_positive_number(text="Zadajte dĺžku strany kocky (bez jednotiek): "): while True: inp = input(text) try: a = float(inp) except ValueError: print("Neplatný vstup. Zadávajte čísla.") continue if 0 > a: print("Neplatný vstup. Zadávajte kladné čisla.") continue break return a def exit_prompt(text="Chcete ukončiť program?", default=True, reverse=False): prompt = text + " A/n: " if default else text + " a/N: " while True: inpul = input(prompt).upper() if not inpul: to_exit = default elif inpul == "A": to_exit = True elif inpul == "N": to_exit = False else: continue break if reverse: to_exit = not to_exit if to_exit: exit() def cube_surface(a): return 6*a**2 def cube_volume(a): return a**3 def print_results(a, sur, vol): text = ( "Objem kocky je: {}".format(vol), "Príklad: {a}^3={result}".format(a=a, result=vol), "Povrch kocky je: {}".format(sur), "Príklad: 6×{a}^2={result}".format(a=a, result=sur) ) for line in text: print(line) while True: a = input_positive_number() surface_area = cube_surface(a) volume = cube_volume(a) print_results(a, surface_area, volume) exit_prompt("Chcete počítať s novými údajmi?", reverse=True)
Ukážka fungovania vylepšenej verzie second.py
Náš program na primitívny výpočet obsahu a objemu kocky sa už možno aj zbytočne začína podobať na niečo oveľa zložitejšie. Myslím si však, že je lepšie ukázať komplexné riešenie na jednoduchom probléme, ako zaoberať sa nejakým zložitejším problémom. Verím, že pokiaľ sledujete seriál od začiatku, tak nebudete mať problém s pochopením jednotlivých častí programu. Pokiaľ vám však niečo nieje jasné, nebojte sa opýtať v komentároch.