Odcinek 5/15 – Funkcje w Pythonie: od prostych do bardziej zaawansowanych

foto kurs pythona odcinek 5

Cel: po tym rozdziale napiszesz funkcje, które rozwiążą mały problem raz, a potem użyjesz ich wiele razy – bez kopiowania kodu.


1) Po co funkcje? (po ludzku)

Funkcja to nazwany przepis. Dajesz składniki (argumenty), dostajesz wynik (return).
Bez funkcji kopiujesz kod w wielu miejscach. Z funkcją – wywołujesz ją jednym słowem.

Bez funkcji:

print("Pole prostokąta:", 5*10)
print("Pole prostokąta:", 3*7)

Z funkcją:

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

print("Pole:", pole_prostokata(5, 10))
print("Pole:", pole_prostokata(3, 7))

2) Jak zdefiniować funkcję

Szablon:

def nazwa(argumenty):
    # ciało funkcji
    return wynik  # można pominąć, wtedy zwraca None
  • def – zaczyna definicję,
  • nazwa – opisowa, snake_case,
  • argumenty – dane wejściowe,
  • return – co oddajesz na zewnątrz.

Przykład:

def powitaj(imie):
    print(f"Cześć, {imie}!")

powitaj("Ala")  # Cześć, Ala!

3) Argumenty funkcji

a) Pozycyjne – liczy się kolejność

def przedstaw(imie, wiek):
    print(f"{imie} ma {wiek} lat")

przedstaw("Ola", 20)

b) Nazwane – podajesz „co jest czym”

przedstaw(wiek=30, imie="Ela")

c) Wartości domyślne

def greet(name="Gościu"):
    print("Witaj,", name)

greet()        # Witaj, Gościu
greet("Ala")   # Witaj, Ala

d) Dowolna liczba argumentów: *args, **kwargs

  • *args – paczka pozycyjnych (krotka),
  • **kwargs – paczka nazwanych (słownik).
def suma(*args):
    return sum(args)

print(suma(1, 2, 3, 4))  # 10

def pokaz(**kwargs):
    for k, v in kwargs.items():
        print(k, "=", v)

pokaz(imie="Ala", wiek=21)

Uwaga: kolejność w definicji bywa ważna:
pozycyjne, domyślne, *args, nazwane, **kwargs.


4) Zwracanie wyników – return

def pole_kola(r):
    return 3.14 * r * r

wynik = pole_kola(5)
print(wynik)  # 78.5

Wiele wartości (wraca krotka):

def minmax(lista):
    return min(lista), max(lista)

low, high = minmax([3, 7, 1, 9])
print(low, high)  # 1 9

5) Zasięg zmiennych (scope) – gdzie „sięga” nazwa?

  • Lokalne – żyją w funkcji.
  • Globalne – widoczne wszędzie w module.
  • global – modyfikuje zmienną globalną (używaj rzadko).
  • nonlocal – dla zagnieżdżonych funkcji (pokażemy później).
x = 10  # globalne

def foo():
    x = 5  # lokalne, zasłania globalne
    print("Wewnątrz:", x)

foo()
print("Na zewnątrz:", x)

6) Funkcje anonimowe (lambda) – krótkie jak sms

Dobre do krótkich operacji „tu i teraz”.

kwadrat = lambda x: x**2
print(kwadrat(5))  # 25

parzyste = list(filter(lambda n: n % 2 == 0, range(10)))
print(parzyste)  # [0, 2, 4, 6, 8]

Często zamiast lambda wygodniej jest użyć key=:

words = ["python", "ai", "programowanie"]
print(max(words, key=len))  # 'programowanie'

7) Dokumentowanie i typowanie

Docstring – pierwszy potrójny cudzysłów w funkcji:

def pole_trojkata(a: float, h: float) -> float:
    """Zwraca pole trójkąta o podstawie a i wysokości h."""
    return (a * h) / 2

Adnotacje typów są dla ludzi i narzędzi (lintery, IDE). Python ich nie wymusza, ale robią porządek.


8) Funkcje to „pierwszorzędni obywatele”

Możesz przekazać funkcję do funkcji, zwrócić funkcję z funkcji, trzymać je w strukturach danych.

def apply_twice(func, x):
    return func(func(x))

print(apply_twice(lambda x: x + 1, 3))  # 5

9) Mini-projekty

A) Kalkulator BMI

def bmi(waga, wzrost):
    return waga / (wzrost ** 2)

print(round(bmi(70, 1.75), 2))  # 22.86

B) Generator haseł

import random, string

def gen_haslo(dlugosc=8):
    znaki = string.ascii_letters + string.digits
    return "".join(random.choice(znaki) for _ in range(dlugosc))

print(gen_haslo(12))

C) Prosta analiza tekstu

def analiza(txt):
    slowa = txt.split()
    return len(slowa), max(slowa, key=len)

liczba, najdluzsze = analiza("Ala ma kota który jest puszysty")
print(liczba, najdluzsze)

10) Typowe pułapki (i szybka naprawa)

❌ Brak return → zwraca None

def pole(a, b):
    a * b  # ups, brak return

Naprawa: return a * b

❌ Mutowalny argument domyślny (lista/słownik)

def add_item(item, lista=[]):  # ZŁE – ta sama lista między wywołaniami
    lista.append(item)
    return lista

Poprawnie:

def add_item(item, lista=None):
    if lista is None:
        lista = []
    lista.append(item)
    return lista

❌ Mylisz kolejność/nazwy argumentów

Używaj nazwanych przy wielu parametrach: funkcja(x=..., y=...).

❌ Modyfikujesz globalne „po cichu”

Unikaj global. Lepiej zwracaj wynik i przypisz: x = funkcja(x).


11) Zadania do samodzielnego zrobienia

  1. pole_kwadratu(a) – zwróć pole.
  2. is_even(n) – zwróć True/False.
  3. srednia(lista) – policz średnią arytmetyczną (zabezpiecz pustą listę).
  4. palindrom(txt) – sprawdź, czy czytany od końca jest taki sam (ignoruj spacje i wielkość liter).
  5. licz_samogloski(txt) – policz samogłoski aąeęiouy (z polskimi znakami).
  6. BONUS: mapuj(lista, func) – zwróć nową listę z zastosowaną funkcją func do każdego elementu (nie używaj wbudowanego map).

Co zabierasz z odcinka 5?

  • Tworzysz funkcje, przekazujesz im dane i zwracasz wyniki.
  • Znasz argumenty domyślne, *args, **kwargs i wiesz, kiedy ich używać.
  • Wiesz, czym jest lambda i zasięg zmiennych.
  • Potrafisz udokumentować funkcję i unikasz pułapek (return, mutowalne domyślne).