Sedmé a osmé cvičení ... okomentované doplňkové příklady (Skupina 3)¶

Příkaz def – definice funkce¶

In [6]:
# definice funkce: hlavička a tělo
# Tato funkce nemá žádný parametr a vrací hodnotu None
def print_demo():
    print("Byla spuštěna funkce 'print_demo'.")
In [8]:
# Tato funkce má jeden parametr a vrací hodnotu None
def print_demo1(param):
    print("Hodnota parametru je", param)
In [9]:
# Tato funkce má dva parametry a vrací hodnotu None
def print_demo2(param1, param2):
    print("Hodnota prvního parametru je", param1)
    print("Hodnota druhého parametru je", param2)
In [10]:
# Volání funkce:
print_demo()
Byla spuštěna funkce 'print_demo'.
In [14]:
# Volání funkce s jedním paraetrem, "x" je argument pro parametr 'param'
print_demo1("x")
Hodnota parametru je x
In [13]:
print_demo2(1,2)
print_demo2(1,1)
Hodnota prvního parametru je 1
Hodnota druhého parametru je 2
Hodnota prvního parametru je 1
Hodnota druhého parametru je 1
In [33]:
# chyba: funkci musím volat se správným počtem argumentů
print_demo("a")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[33], line 1
----> 1 print_demo("a")

TypeError: print_demo() takes 0 positional arguments but 1 was given
In [15]:
print_demo()        # zde nepředáváme žádný argument
print_demo1(10)     # číslo 10 je argument pro parametr 'param'
print_demo2(10, 20) # čísla 10 je argument pro parametr 'param1', 20 je argument pro parametr 'param2'
Byla spuštěna funkce 'print_demo'.
Hodnota parametru je 10
Hodnota prvního parametru je 10
Hodnota druhého parametru je 20
In [17]:
# výpis objektu, který reprezentuje funkci:
print(print_demo)
<function print_demo at 0x7f3f142b40e0>

Příkaz return – vrácení výsledku funkce¶

In [24]:
# K vrácení výsledné (návratové) hodnoty funkce slouží příkaz return:
def polynom(x):
    return x ** 2 - 3 * x + 1

# výslednou (návratovou) hodnotu funkce mohu např. vložit do proměnné:
vysledek = polynom(2.5)
print(vysledek)

# nebo rovnou vypsat:
print(polynom(-0.5))

# složitější výraz:
vysledek = polynom(2.5) + 4 * polynom(0.5)
print(vysledek)
-0.25
2.75
-1.25
In [22]:
# výpis více hodnot v cyklu:
for x in range(1,10):
    y = polynom(x)
    print(y, end= " ")
-1 -1 1 5 11 19 29 41 55 
In [25]:
# pokud funkce neobsahuje příkaz return, je její návratovou hodnotou None:
def print_demo():
    print("Byla spuštěna funkce 'print_demo'.")

x = print_demo()
print("Návratová hodnota funkce je", x)
Byla spuštěna funkce 'print_demo'.
Návratová hodnota funkce je None
In [27]:
# Tato funkce vrací hodnotu 6
def print_demo():
    print("Byla spuštěna funkce 'print_demo'.")
    return 6

x = print_demo()
print(x)
Byla spuštěna funkce 'print_demo'.
6
In [3]:
def polynom(x):
    vysledek = x ** 2 - 3 * x + 1
    return vysledek

vysledek = polynom(2.5)
print(vysledek)
-0.25
In [28]:
# příkaz return ukončí vykonávání funkce (jako break u cyklu)
# za příkazem return může a nemusí následovat návratová hodnota 
# pokud žádnou návratovou hodnotu nespecifikujeme, vrátí se None

def polynom(x):
    if x < 0:
        print("Definiční obor této funkce nezahrnuje záporná čísla.") # chybová hláška
        return
    return x ** 2 - 3 * x + 1

vysledek = polynom(-12)
print("Návratová hodnota je", vysledek)

print("")

vysledek = polynom(12)
print("Návratová hodnota je", vysledek)
Definiční obor této funkce nezahrnuje záporná čísla.
Návratová hodnota je None

Návratová hodnota je 109
In [39]:
# Další příklad použití příkazu return v různých větvích výpočtu:
def signum(x):
    if x > 0:
        return 1
    elif x == 0:
        return 0
    return -1    
    
print(signum(0), signum(20), signum(-2.3))

for i in range(-10,10):
    print(signum(i), end= " ")
0 1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 1 1 1 1 1 1 1 1 
In [14]:
# funkce se mohou volat navzájem, často je to výhodné:

def mocnina(a,b):
    return a ** b

def nadruhou(x):
    y = mocnina(x,2)
    return y

x = mocnina(2,6)
y = mocnina(4, 0.5)

print(x,y)

x = nadruhou(3)
y = nadruhou(x)
print(x,y)
64 2.0
9 81

Proměnné a obor platnosti¶

In [41]:
# Proměnné dělíme na globální (definované na úrovni programu) a lokální (definované na úrovni funkce)

# globální proměnná
y = "a"

# co se týká proměnných, pracuje funkce "ve svém vlastním světě"
# obor platnosti lokálních proměnných je jen uvnitř funkce, pak zaniknou
def f(x):
    
    # lokální proměnná
    a = 1
    
    # výpis lokálních proměnných:
    print("lokalní  x = ", x,", a =  ", a)
    
# použití funkce
f(80)

# výpis globálních proměnných:
print("globální y =", y)

# výpis lokálních proměnných mimo funkci ... chyba! :
#print(a)
#print(x)

# zkuste si pytutor
lokalní  x =  80 , a =   1
globální y = a
In [39]:
# Výhoda: uvnitř funkce si můžeme proměnné pojmenovat jak chceme nezávisle na vnějším světě:

# globální proměnné
x  = 10
a  = "ahoj"

# uvnitř funkce lokální proměnná překryje globální proměnnou stejného jména
def f(x):
    
    # lokální proměnná
    a = 1
    
    # výpis lokálních proměnných
    print("lokalní  x = ", x,", a =  ", a)
    
# použití funkce
f(80)
# f(x)
# f(a)

# výpis globálních proměnných
print("globalni x = ", x,", a = ", a)

# zkuste si pytutor
lokalní  x =  80 , a =   1
globalni x =  10 , a =  ahoj
In [50]:
# Uvnitř funkce můžeme používat objekty s širším oborem platnosti (globální proměnné a globálně importované moduly), ale jen pro čtení: 
# obecně se to ale v prvním případě nedoporučuje "pozveš si domů kamaráda, aby ti pomohl s úkolem a on ti přitom prohledá zásuvky"

# globální proměnné
x  = 10
a  = "ahoj"

import math

# uvnitř funkce lokální proměnná překryje globální proměnnou stejného jména
def f(p):
    
    # lokální proměnná
    b = p + x
    
    b = math.sqrt(b)
    
    # výpis lokálních proměnných
    print("lokalní  p = ", p,", b =  ", b)
    
    print("globální x = ", x,", a = ", a)

    return b

# použití funkce
f(80)

# výpis globálních proměnných
print("globalni x = ", x,", a = ", a)

# zkuste si pytutor
lokalní  p =  80 , b =   9.486832980505138
globální x =  10 , a =  ahoj
globalni x =  10 , a =  ahoj
In [52]:
# Čitelnější řešení: předat funkci globální proměnnou jako parametr:

# globální proměnné
x  = 10
a  = "ahoj"

import math

def f(p, x):
    
    # lokální proměnná
    b = p + x
    b = math.sqrt(b)
    
    # výpis lokálních proměnných
    print("lokalní  p = ", p,", b = ", b, ", x = ", x)

    return b

# použití funkce
f(80, x)

# výpis globálních proměnných
print("globalni x = ", x,", a = ", a)

# zkuste si pytutor
lokalní  p =  80 , b =  9.486832980505138 , x =  10
globalni x =  10 , a =  ahoj
In [57]:
# a) globální proměnné uvnitř funkce nejde měnit
# b) uvnitř jedné funkce nelze zároveň používat globální proměnnou a definovat si novou stejného jména

# globální proměnné
x  = 10
a  = "ahoj"
y  = 15

def f(p):
    
    # lokální proměnná
    b = p + x

    # CHYBA ... globální proměnnou nelze měnit
    # a = a + 56

    # CHYBA ... už jsme použili globální proměnnou x
    # x = "moje lokální proměnná"

    # toto je v pořádku:
    y = 6
    
    # výpis lokálních proměnných
    print("lokalní  p = ", p,", b = ", b, "y = ", y)

    return b

# použití funkce
f(80)

# výpis globálních proměnných
print("globalni x = ", x,", a = ", a, "y = ", y)

# zkuste si pytutor
lokalní  p =  80 , b =  90 y =  6
globalni x =  10 , a =  ahoj y =  15
In [47]:
# globální proměnné
globalni = 10

def f():
    # lokální proměnná
    lokalni = 1

    #globalni = 56
    
    # použití globální proměnné
    lokalni += globalni

    # uvnitř funkce nelze měnit globální proměnné
    # globalni += 1

    # výpis lokálních proměnných
    print("lokalni", lokalni)

   # print("globalni uvnitr", globalni)
    
# použití funkce
f()

# výpis globálních proměnných
print("globalni venku", globalni)

# lokální proměnné definované uvnitř funkce nejsou k dispozici na globální úrovni
#print(lokalni)
lokalni 11
globalni venku 10

Parametry s výchozí hodnotou¶

In [58]:
# parametrům funkce můžeme nastavit jejich výchozí (defaultní) hodnotu:
# parametry s výchozí hodnotou musí být až za všemi parametry bez výchozí hodnoty:
def demo_funkce_s_mnoha_parametry(param1, param2, param3=10, param4=None):
    print("param1 je", param1)
    print("param2 je", param2)
    print("param3 je", param3)
    print("param4 je", param4)
In [3]:
# parametry s výchozí hodnotou můžeme při volání funkce vynechat:
demo_funkce_s_mnoha_parametry(1,2)
param1 je 1
param2 je 2
param3 je 10
param4 je None
In [16]:
demo_funkce_s_mnoha_parametry(1, 2, 3)
param1 je 1
param2 je 2
param3 je 3
param4 je None
In [17]:
demo_funkce_s_mnoha_parametry(1, 2, 3, 4)
param1 je 1
param2 je 2
param3 je 3
param4 je 4
In [59]:
# chyba
demo_funkce_s_mnoha_parametry(1)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[59], line 1
----> 1 demo_funkce_s_mnoha_parametry(1)

TypeError: demo_funkce_s_mnoha_parametry() missing 1 required positional argument: 'param2'

Poziční vs. pojmenované argumenty¶

In [18]:
# funkci můžeme volat s pojmenovanými argumenty:
demo_funkce_s_mnoha_parametry(param1=1, param2=2, param3=3, param4=4)
param1 je 1
param2 je 2
param3 je 3
param4 je 4
In [60]:
# pojmenované argumenty můžeme zadávat v libovolném pořadí:
demo_funkce_s_mnoha_parametry(param2=2, param1=1, param4=4, param3=3)
param1 je 1
param2 je 2
param3 je 3
param4 je 4
In [20]:
demo_funkce_s_mnoha_parametry(param4=4, param3=3, param2=2, param1=1)
param1 je 1
param2 je 2
param3 je 3
param4 je 4
In [21]:
# pojmenované argumenty musí být až za všemi pozičními:
demo_funkce_s_mnoha_parametry(1, 2, param4=4)
param1 je 1
param2 je 2
param3 je 10
param4 je 4

Funkce jako proměnné¶

In [61]:
x = min(6,2,4,10)
y = max(6,2,4,10)
print(x,y)

# funkci mohu dát další jméno:
def demo1():
    f = max
    g = min
    v = f(f(2, g(1, 3)), 4)
    print("v =", v)

demo1()

x = min(6,2,4,10)
y = max(6,2,4,10)
print(x,y)
      
2 10
v = 4
2 10
In [63]:
x = min(6,2,4,10)
y = max(6,2,4,10)
print(x,y)

# uvnitř funkce mohu definovat proměnné min a max:
def demo2():
    min = 1
    max = 5
    for i in range(min, max + 1):
        print(i, end = " ")
    print("")    
        
demo2()

x = min(6,2,4,10)
y = max(6,2,4,10)
print(x,y)
2 10
1 2 3 4 5 
2 10

Docstring a nápověda¶

In [12]:
def demo():
    """ Toto je docstring. Slouží jako místo k umístění dokumentace pro danou funkci.

        Docstring typicky obsahuje:
        - popis všech parametrů a jejich vliv na chování funkce
        - popis návratové hodnoty
        - popis případných chyb, které mohou nastat při vykonávání funkce
    """
    return
In [13]:
help(demo)
Help on function demo in module __main__:

demo()
    Toto je docstring. Slouží jako místo k umístění dokumentace pro danou funkci.
    
    Docstring typicky obsahuje:
    - popis všech parametrů a jejich vliv na chování funkce
    - popis návratové hodnoty
    - popis případných chyb, které mohou nastat při vykonávání funkce

In [66]:
# výpis nápovědy:
help(input)

# alternativně: Show Contextual Help
Help on method raw_input in module ipykernel.kernelbase:

raw_input(prompt='') method of ipykernel.ipkernel.IPythonKernel instance
    Forward raw_input to frontends
    
    Raises
    ------
    StdinNotImplementedError if active frontend doesn't support stdin.

In [17]:
import math

help(max)
Help on built-in function max in module builtins:

max(...)
    max(iterable, *[, default=obj, key=func]) -> value
    max(arg1, arg2, *args, *[, key=func]) -> value
    
    With a single iterable argument, return its biggest item. The
    default keyword-only argument specifies an object to return if
    the provided iterable is empty.
    With two or more arguments, return the largest argument.

In [67]:
# Zkuste odteď ke každé své funkci napsat docstring