Návod na Python – podprogramy, funkce

Python podprogramy a funkce

Python podporuje jak paradigma strukturovaného programování, tak i objektově orientovaného a funkcionálního programování. Samozřejmě umožňuje vytvářet podprogramy, procedury i funkce s jednotnou konstrukcí s pomocí klíčového slova def.

def Podprogram(argumenty, parametry):
  # telo podprogramu
  return vystup              # v případě funkce

Tělo podprogramu opět odsazujeme stejně jako v příkazech if a while. Nepotřebujeme-li žádnou návratovou hodnotu, poslední příkaz return nepoužijeme, definujeme tak proceduru. V případě funkce naopak příkazem return říkáme, jakou hodnotu má podprogram vrátit.

def Druha_odmocnina(x):
  odmocnina = x ** (0.5)      # x na 1/2 je totéž jako math.sqrt(x)
  return odmocnina            # byť pomaleji vypočítaná

Nadefinovaný podprogram pak jednoduše použijeme jako proceduru funkci pod definovaným názvem v hlavním těle programu. I kdyby funkce či procedura neměla žádné argumenty, musíme uvést závorky za názvem. Celý program i s definicí funkce pak bude vypadat takto:

def Druha_odmocnina(x):
  odmocnina = x ** (0.5)
  return odmocnina


c = float(input("Zadej číslo x pro výpočet jeho druhé odmocniny:"))
o = Druha_odmocnina(c)
print("Druhá odmocnina z", c, "je:", o)

Proč používat procedury a funkce

U krátkých jednoduchých programů většinou podprogramy nepotřebujeme. U větších už ale ano. K čemu to bude dobré? Kusy kódu, které potřebujeme opakovaně, můžeme napsat pouze jednou a pak už je jen jako podprogram volat. Tím se nám celkový kód zkrátí a zpřehlední. Vyhneme se také chybám, které by kusy podobného kódu roztroušené všude možně po programu, mohly obsahovat.

Vytvořením podprogramu si tak vlastně rozšiřujeme množinu elementárních příkazů, které pak můžeme v programu využívat. Stejně tak funkce, které importujeme z modulů (např. math.sqrt()), jsou podprogramy, které za nás udělal někdo jiný.

Argumenty a parametry podprogramů, rozsah platnosti proměnných

Obecně v programování platí, že definovaná funkce (podprogram) dosáhne pouze na proměnné, které si uvnitř sebe nadeklaruje, na parametry uvedené v hlavičce (argumenty) a na globální proměnné zpřístupněné deklarací global. Ostatní proměnné jinde v programu či v jiných funkcích nevidí. Podívejme se podívat na to, jak to funguje v Pythonu, blíže.

Začněme parametry podprogramu. Ty uvádíme v hlavičce definice podprogramu v závorkách, jsou to jména proměnných, které můžeme uvnitř funkce používat. Jim se při volání funkce předává hodnota proměnné, kterou uvedeme na pozici parametru dané funkce. Předáváné proměnné se při volání funkce říká argument.

def Obecna_mocnina(A, R):      # A a R jsou parametry funkce
  mocnina = A ** R             # používáme je jako deklarované proměnné uvnitř těla funkce
  return mocnina

x = Obecna_mocnina(2, 0.5)     # voláme funkci s argumenty A = 2 a R = 0.5
print(x)

Funkce si může samozřejmě pro svoje vlastní potřeby nadefinovat vlastní lokální proměnné. Ty ale budou platit jen uvnitř funkce, jinde v programu jako by neexistovaly. Příkladem je proměnná mocnina v předchozím příkladu. Kdybychom ji chtěli použít (např. vytisknout) mimo definici funkce, program by ohlásil chybu.

Jak jsou na tom proměnné z vyšší úrovně uvnitř podprogramů? Pokud nemáme v podprogramu proměnnou se stejným jménem, podprogram danou proměnnou vyšší úrovně vidí, ale nemůže ji změnit. Níže uvedený program sice proměnnou x vytiskne, ale když se jí pokusí změnit, ohlásí interpret chybu.

a = 1
x = 25.1

def zmen(r):
  r = r * 2
  print(x)
  x = x - 25

print(a, x)  
zmen(a)

Pokud si v podprogramu nadefinujeme lokální proměnnou se stejným názvem, jako již má nějaká proměnná na vyšší úrovni, nic se neděje. Podprogram s ní pracuje v rámci vlastního měřítka, globální proměnné si nevšímá.

Pokud z nějakého důvodu opravdu potřebujeme pracovat s proměnnou z vyšší úrovně, měnit její hodnotu i uvnitř podprogramu, zpřístupníme si ji příkazem global. Tím z ní v rámci měřítka podprogramu děláme globální proměnnou, která je nám plně k dispozici.

a = 1
x = 25.1

def zmen(r):
  global x     # v tuto chvíli máme k dispozici proměnnou x 
               # z vyšší úrovně a můžeme ji měnit
  r = r * 2
  print(x)
  x = x - 25

print(a, x)  
zmen(a)

Tento přístup s sebou ovšem nese riziko. Změnou globální proměnné někde uvnitř funkce si opět koledujeme o nevypočitatelné chování programu, o chyby, které budeme složitě odhalovat.

Typ parametru, argumenty předávané hodnotou a odkazem

Python nepotřebuje znát typ parametru funkce. Jednoduše si parametr nějak nazvete a dále s ním pracujete, jak potřebujete. Očekáváte-li string, pracujete s ním uvnitř funkce jako se stringem, je-li parametrem číslo, počítáte s ním jako s číslem. Samozřejmě, pokud jako argument předáte číslo a pracujete s ním uvnitř funkce jako se stringem, může nastat problém.

Python rozlišuje datové typy na tzv. mutable a immutable, tedy měnitelné a neměnitelné. Mezi měnitelné patří seznamy (pole), slovníky a množiny, mezi neměnitelné např. čísla (int, float), retězce (str), n-tice (tuple) nebo rozsahy (range). Nebudeme rozebírat dopodrobna, co přesně znamená měnitelnost, či neměnitelnost, ale ukážeme si, jaký má význam při předávání parametrů (argumentů) funkcí:

  1. Pokud je argumentem neměnitelný objekt (immutable, např. číslo nebo string), předá se argument hodnotou. Tj. obsah proměnné, kterou předáváme jako argument funkce, se uloží jako hodnota parametru a dále se už ve funkci pracuje jen s parametrem jako lokální proměnnou. Pokud tedy změníme obsah parametru, obsah původní proměnné se nemění.
  2. Pokud je argumentem měnitelný objekt (mutable, např. pole), předá se argument tzv. odkazem. Parametrické proměnné se předá odkaz na daný objekt, čili celý objekt se vším všudy. Změníme-li v tomto případě obsah parametrické proměnné, mění se tím i původní proměnná.
def vymen_prvky_pole(pole, i, j):
  pole[i], pole[j] = pole[j], pole[i]
  i, j = j, i

Auta = ["Ford", "Audi", "Škoda"]
prvni = 0
druhe = 1
vymen_prvky_pole(Auta, prvni, druhe)
print(Auta, prvni, druhe)

Výše uvedená procedura vymen_prvky_pole prohodí první a druhý prvek pole Auta (pole se předávalo odkazem na již existující objekt, procedura k němu má přístup), ale proměnné prvni a druhe zůstanou nezměněné (argumenty se předávaly hodnotou, procedura nemá k obsahu původních proměnných přístup).

Návratová hodnota funkce

Závěrečnou deklarací return říkáme, co má naše funkce vrátit jako návratovou či funkční hodnotu. Většinou je to číslo, ale stejně tak to může být řetězec, hodnota True nebo False, ale také strukturovaný datový typ jako např. pole.

def NaplnPole(Delka):

  import random
  P = []
  for i in range(Delka):
    P[i] = random.randint(-99,99)
  return P

Lze použít i jinou datovou strukturu, např. n-tici (tuple) a pomocí ní vrátit více hodnot místo jedné. Samozřejmě je poté potřeba s výsledkem pracovat jako s n-ticí a načíst ji do více proměnných, nebo ji následně rozdělit.

def KomplexneSdruzene(Re, Im):
  return Re, -Im

Re = 1
Im = 2   # komplexní číslo 1+2i
Re1, Im1 = KomplexneSdruzene(Re, Im)

Buďte první, kdo vloží komentář

Přidejte odpověď