Szybki quiz – przypomnienie poprzedniej lekcji
Temat poprzedniej lekcji: biblioteki, moduły, pakiety. Odpowiedz bez zaglądania do notatek.
1. Co zostanie wyświetlone?
import math
print(math.ceil(3.2), math.floor(3.8))
Odpowiedź
Odpowiedź: 4 3 – ceil zaokrągla w górę, floor w dół.
2. Znajdź błąd w kodzie. Jak go naprawić (podaj dwa sposoby)?
import math
wynik = sqrt(16)
Odpowiedź
Odpowiedź: Po import math funkcja sqrt jest dostępna tylko z nazwą modułu, więc Python zgłosi NameError. Poprawki: math.sqrt(16) albo zmiana importu na from math import sqrt.
3. Jak po zapisie import datetime as dt pobrać dzisiejszą datę?
Odpowiedź
Odpowiedź: dt.date.today()
4. Jakie wartości może zwrócić random.randint(1, 10) i do czego służy random.seed(12)?
Odpowiedź
Odpowiedź: randint(1, 10) zwraca liczbę całkowitą od 1 do 10 włącznie z oboma końcami. random.seed(12) ustawia ziarno, dzięki czemu losowanie jest powtarzalne (przydatne przy debugowaniu i testach).
5. Co zostanie wyświetlone?
from collections import Counter
print(Counter(["a", "b", "a", "c", "a"]).most_common(1))
Odpowiedź
Odpowiedź: [('a', 3)]
6. Dlaczego ten kod zgłosi błąd i czym można zastąpić {}, żeby działał?
licznik = {}
licznik['a'] += 1
Odpowiedź
Odpowiedź: Klucz 'a' jeszcze nie istnieje, więc jest KeyError. Rozwiązanie: defaultdict(int) z modułu collections, który dla nowego klucza zaczyna od 0.
7. Uzupełnij kod tak, aby zaimportować z własnego modułu moj_modul.py tylko funkcję dodaj i stałą PI.
from moj_modul import ____, ____
Odpowiedź
Odpowiedź: from moj_modul import dodaj, PI
Funkcja to wyodrębniony, nazwany fragment kodu, który wykonuje określone zadanie. Zamiast pisać ten sam kod wiele razy, definiujemy funkcję raz i wielokrotnie ją wywołujemy.
Zalety funkcji:
- DRY (Don’t Repeat Yourself) – unikamy powtórzeń
- Modularność – kod podzielony na logiczne bloki
- Czytelność – łatwiej zrozumieć co robi program
- Łatwość testowania – można testować osobno każdą funkcję
- Możliwość ponownego użycia – ta sama funkcja w różnych projektach
Analogia: Funkcja to jak przepis kulinarny – raz napisany, wiele razy używany. Zamiast za każdym razem opisywać jak zrobić ciasto, piszesz „zrób ciasto według przepisu X”.
Definicja funkcji
Podstawowa składnia
def nazwa_funkcji():
# kod do wykonania
instrukcja1
instrukcja2
Elementy:
def– słowo kluczowe (definition)nazwa_funkcji– nazwa według zasad nazewnictwa zmiennych()– nawiasy (mogą zawierać parametry):– dwukropek- Wcięcie – kod funkcji musi być wcięty (4 spacje)
Pierwszy przykład – funkcja bez argumentów
def przywitaj():
print("Witam serdecznie!")
print("Jak się masz?")
# Wywołanie funkcji
przywitaj()
Wynik:
Witam serdecznie!
Jak się masz?
Funkcje z parametrami
Parametr (argument) to wartość przekazywana do funkcji.
Jeden parametr
def przywitaj(imie):
print(f"Witaj, {imie}!")
# Wywołanie z argumentem
przywitaj("Jan") # Witaj, Jan!
przywitaj("Anna") # Witaj, Anna!
Wiele parametrów
def dodawanie(liczba1, liczba2):
wynik = liczba1 + liczba2
print(wynik)
dodawanie(2, 3) # 5
dodawanie(10, 20) # 30
Uwaga: Liczba argumentów przy wywołaniu musi się zgadzać z liczbą parametrów w definicji!
def dodawanie(a, b):
print(a + b)
dodawanie(5, 10) # OK - 2 argumenty
dodawanie(5) # TypeError - brakuje argumentu
dodawanie(5, 10, 15) # TypeError - za dużo argumentów
Parametry domyślne
Możesz nadać parametrom wartości domyślne.
def powitanie(imie, wiadomosc="Dzień dobry"):
print(f"{wiadomosc}, {imie}!")
# Użycie domyślnej wartości
powitanie("Jan") # Dzień dobry, Jan!
# Nadpisanie domyślnej wartości
powitanie("Anna", "Cześć") # Cześć, Anna!
Zasada: Parametry z wartościami domyślnymi zawsze na końcu!
# DOBRZE
def funkcja(a, b, c=10):
pass
# ŹLE - parametr z domyślną wartością przed zwykłym
def funkcja(a, b=5, c): # SyntaxError
pass
Przykład – odejmowanie z wartością domyślną
def odejmowanie(liczba1, liczba2=4):
wynik = liczba1 - liczba2
print(wynik)
odejmowanie(10) # 6 (10 - 4)
odejmowanie(10, 3) # 7 (10 - 3)
Argumenty nazwane (keyword arguments)
Możesz wywołać funkcję podając nazwy parametrów.
def przedstaw_sie(imie, nazwisko, wiek):
print(f"Jestem {imie} {nazwisko}, mam {wiek} lat")
# Argumenty pozycyjne (kolejność ma znaczenie)
przedstaw_sie("Jan", "Kowalski", 25)
# Argumenty nazwane (kolejność nie ma znaczenia)
przedstaw_sie(wiek=25, imie="Jan", nazwisko="Kowalski")
przedstaw_sie(nazwisko="Kowalski", imie="Jan", wiek=25)
# Mieszane (pozycyjne przed nazwanymi)
przedstaw_sie("Jan", wiek=25, nazwisko="Kowalski")
Return – zwracanie wartości
return zwraca wartość z funkcji, którą możesz później użyć.
print vs return
# Funkcja z print - tylko wyświetla
def dodaj_print(a, b):
wynik = a + b
print(wynik)
# Funkcja z return - zwraca wartość
def dodaj_return(a, b):
wynik = a + b
return wynik
# Porównanie
x = dodaj_print(5, 3) # Wyświetli: 8
print(x) # None (funkcja nic nie zwróciła)
y = dodaj_return(5, 3) # Nie wyświetli nic
print(y) # 8 (funkcja zwróciła wartość)
Kluczowa różnica:
print– wyświetla na ekranie, zwracaNonereturn– zwraca wartość, którą można zapisać lub użyć
Przykład praktyczny
def oblicz_pole_kola(promien):
pi = 3.14159
pole = pi * promien ** 2
return pole
# Używamy zwróconej wartości
wynik = oblicz_pole_kola(5)
print(f"Pole koła: {wynik}")
# Możemy użyć w obliczeniach
podwojone = oblicz_pole_kola(5) * 2
print(f"Podwojone pole: {podwojone}")
Wiele instrukcji return
def sprawdz_wiek(wiek):
if wiek < 18:
return "Niepełnoletni"
elif wiek < 65:
return "Dorosły"
else:
return "Senior"
print(sprawdz_wiek(15)) # Niepełnoletni
print(sprawdz_wiek(30)) # Dorosły
print(sprawdz_wiek(70)) # Senior
Uwaga: Po napotkaniu return funkcja kończy działanie – kod po return nie zostanie wykonany.
def funkcja():
return "To się wykona"
print("To się NIE wykona") # Nigdy nie zostanie wykonane
Zwracanie wielu wartości
Python pozwala zwrócić wiele wartości (jako krotkę).
def oblicz(a, b):
suma = a + b
roznica = a - b
iloczyn = a * b
return suma, roznica, iloczyn
# Odbieranie wielu wartości
s, r, i = oblicz(10, 5)
print(s) # 15
print(r) # 5
print(i) # 50
# Lub jako krotka
wyniki = oblicz(10, 5)
print(wyniki) # (15, 5, 50)
Zasięg zmiennych (scope)
Zmienne lokalne
Zmienne zdefiniowane wewnątrz funkcji są lokalne – dostępne tylko w funkcji.
def funkcja():
lokalna = "Jestem lokalna"
print(lokalna)
funkcja() # Jestem lokalna
# print(lokalna) # NameError - zmienna nie istnieje poza funkcją
Zmienne globalne
Zmienne zdefiniowane poza funkcją są globalne – dostępne wszędzie.
globalna = "Jestem globalna"
def funkcja():
print(globalna) # Funkcja widzi zmienną globalną
funkcja() # Jestem globalna
print(globalna) # Jestem globalna
Lokalna vs globalna – konflikt
Jeśli w funkcji zdefiniujesz zmienną o takiej samej nazwie jak globalna, lokalna ma pierwszeństwo.
zmienna = "globalna"
def funkcja():
zmienna = "lokalna"
print(zmienna)
funkcja() # lokalna
print(zmienna) # globalna
Modyfikacja zmiennej globalnej
Aby zmienić zmienną globalną wewnątrz funkcji, użyj słowa global.
licznik = 0
def zwieksz():
global licznik # Informujemy że chcemy użyć zmiennej globalnej
licznik += 1
zwieksz()
zwieksz()
print(licznik) # 2
Uwaga: Unikaj nadużywania global – lepiej przekazywać i zwracać wartości.
# LEPIEJ - bez global
licznik = 0
def zwieksz(n):
return n + 1
licznik = zwieksz(licznik)
licznik = zwieksz(licznik)
print(licznik) # 2
Funkcja w funkcji (nested function)
def zewnetrzna(name):
print(f"Funkcja zewnętrzna: {name}")
def wewnetrzna():
print(f"Funkcja wewnętrzna: {name}") # Widzi zmienną z zewnętrznej
wewnetrzna() # Wywołanie wewnętrznej
zewnetrzna("Kama")
# Funkcja zewnętrzna: Kama
# Funkcja wewnętrzna: Kama
# wewnetrzna() # NameError - nie istnieje poza zewnętrzną
Nieokreślona liczba argumentów (*args)
Gdy nie wiesz ile argumentów zostanie przekazanych, użyj *args.
Przykład – suma dowolnej liczby argumentów
def suma(*args):
"""
Sumuje dowolną liczbę argumentów.
args to krotka zawierająca wszystkie przekazane argumenty.
"""
wynik = 0
for liczba in args:
wynik += liczba
return wynik
print(suma(1, 2, 3)) # 6
print(suma(1, 2, 3, 4, 5)) # 15
print(suma(10, 20)) # 30
Jak to działa:
*argstworzy krotkę z wszystkich przekazanych argumentów- Możesz iterować po
argsjak po zwykłej krotce
Sprawdzenie typu
def funkcja(*args):
print(type(args)) # <class 'tuple'>
print(args)
funkcja(1, 2, 3, 4, 5)
# (1, 2, 3, 4, 5)
Przykład – znajdź maksimum
def maksimum(*liczby):
if not liczby:
return None
maks = liczby[0]
for liczba in liczby:
if liczba > maks:
maks = liczba
return maks
print(maksimum(5, 2, 9, 1, 7)) # 9
print(maksimum(10, 20)) # 20
Nieokreślona liczba par klucz-wartość (**kwargs)
Gdy nie wiesz ile argumentów nazwanych zostanie przekazanych, użyj **kwargs.
Przykład – zamówienie pizzy
def zamowienie(nazwa, adres, **skladniki):
"""
kwargs to słownik zawierający wszystkie nazwane argumenty.
"""
print(f"Zamówienie dla: {nazwa}")
print(f"Adres: {adres}")
print("Dodatki:")
cena = 20.00
for skladnik, czy_dodac in skladniki.items():
if czy_dodac:
print(f" - {skladnik}")
cena += 2.00
print(f"Cena: {cena} zł")
return cena
zamowienie(
"Jan",
"Warszawa",
jalapenos=True,
dodatkowy_ser=True,
pieczarki=False,
szynka=True
)
Wynik:
Zamówienie dla: Jan
Adres: Warszawa
Dodatki:
- jalapenos
- dodatkowy_ser
- szynka
Cena: 26.0 zł
Sprawdzenie typu
def funkcja(**kwargs):
print(type(kwargs)) # <class 'dict'>
print(kwargs)
funkcja(imie="Jan", wiek=25, miasto="Warszawa")
# {'imie': 'Jan', 'wiek': 25, 'miasto': 'Warszawa'}
Iteracja po **kwargs
def wyswietl_info(**dane):
print("Informacje:")
for klucz, wartosc in dane.items():
print(f" {klucz}: {wartosc}")
wyswietl_info(imie="Jan", wiek=25, zawod="programista")
Wynik:
Informacje:
imie: Jan
wiek: 25
zawod: programista
Łączenie *args i **kwargs
Możesz używać obu jednocześnie.
def funkcja(a, b, *args, **kwargs):
print(f"a: {a}")
print(f"b: {b}")
print(f"args: {args}")
print(f"kwargs: {kwargs}")
funkcja(1, 2, 3, 4, 5, x=10, y=20)
Wynik:
a: 1
b: 2
args: (3, 4, 5)
kwargs: {'x': 10, 'y': 20}
Kolejność parametrów:
- Zwykłe parametry
- Parametry z wartościami domyślnymi
*args**kwargs
def funkcja(a, b=10, *args, **kwargs):
pass
Funkcje rekurencyjne
Rekursja to gdy funkcja wywołuje samą siebie.
Przykład – silnia
Definicja matematyczna:
- 0! = 1
- 1! = 1
- n! = n × (n-1)!
Wersja iteracyjna (pętla):
def silnia_iter(n):
if n in (0, 1):
return 1
wynik = 1
for i in range(2, n + 1):
wynik *= i
return wynik
print(silnia_iter(5)) # 120 (5! = 5×4×3×2×1)
Wersja rekurencyjna:
def silnia(n):
if n <= 1:
return 1
else:
return n * silnia(n - 1)
print(silnia(5)) # 120
Jak to działa:
silnia(5)
= 5 * silnia(4)
= 5 * 4 * silnia(3)
= 5 * 4 * 3 * silnia(2)
= 5 * 4 * 3 * 2 * silnia(1)
= 5 * 4 * 3 * 2 * 1
= 120
Wersja skrócona:
def silnia(n):
return n * silnia(n - 1) if n > 1 else 1
Przykład – ciąg Fibonacciego (rekursja)
def fibonacci(n):
"""Zwraca n-ty element ciągu Fibonacciego."""
if n <= 1:
return n
else:
return fibonacci(n - 1) + fibonacci(n - 2)
# Pierwsze 10 liczb
for i in range(10):
print(fibonacci(i), end=" ")
# 0 1 1 2 3 5 8 13 21 34
Uwaga: Rekursja może być wolna i zużywać dużo pamięci dla dużych wartości.
Lambda – funkcje anonimowe
Lambda to krótka, anonimowa (bez nazwy) funkcja w jednej linii.
Podstawowa składnia
lambda argumenty: wyrażenie
Prosty przykład
# Zwykła funkcja
def kwadrat(x):
return x * x
# Lambda (to samo)
kwadrat_lambda = lambda x: x * x
print(kwadrat(5)) # 25
print(kwadrat_lambda(5)) # 25
Lambda z wieloma argumentami
# Dodawanie
dodaj = lambda a, b: a + b
print(dodaj(3, 7)) # 10
# Maksimum z dwóch liczb
maksimum = lambda a, b: a if a > b else b
print(maksimum(10, 5)) # 10
Lambda z map() – przetwarzanie listy
map() aplikuje funkcję do każdego elementu kolekcji.
liczby = [1, 2, 3, 4, 5]
# Kwadraty liczb
kwadraty = list(map(lambda x: x * x, liczby))
print(kwadraty) # [1, 4, 9, 16, 25]
# Podwojenie wartości
podwojone = list(map(lambda x: x * 2, liczby))
print(podwojone) # [2, 4, 6, 8, 10]
Lambda z filter() – filtrowanie
filter() wybiera elementy spełniające warunek.
liczby = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Tylko liczby parzyste
parzyste = list(filter(lambda x: x % 2 == 0, liczby))
print(parzyste) # [2, 4, 6, 8, 10]
# Liczby większe od 5
wieksze = list(filter(lambda x: x > 5, liczby))
print(wieksze) # [6, 7, 8, 9, 10]
Lambda z sorted() – sortowanie
# Sortowanie słów według długości
words = ["python", "ai", "lambda", "kod"]
sorted_words = sorted(words, key=lambda w: len(w))
print(sorted_words) # ['ai', 'kod', 'lambda', 'python']
# Sortowanie krotek według drugiego elementu
pary = [(1, 3), (4, 1), (2, 5), (3, 2)]
sorted_pary = sorted(pary, key=lambda x: x[1])
print(sorted_pary) # [(4, 1), (3, 2), (1, 3), (2, 5)]
Lambda w list comprehension (alternatywa)
# Lambda + map
kwadraty_map = list(map(lambda x: x**2, range(5)))
# List comprehension (często lepsze)
kwadraty_comp = [x**2 for x in range(5)]
print(kwadraty_map) # [0, 1, 4, 9, 16]
print(kwadraty_comp) # [0, 1, 4, 9, 16]
Zasada: Jeśli lambda jest skomplikowana, lepiej użyć zwykłej funkcji.
Dekoratory
Dekorator to funkcja która modyfikuje działanie innej funkcji.
Podstawowy przykład
def moj_dekorator(func):
"""Dekorator dodający funkcjonalność przed i po funkcji."""
def wrapper():
print("Coś robię przed funkcją")
func()
print("Coś robię po funkcji")
return wrapper
@moj_dekorator
def prosta_funkcja():
print("Właściwa funkcja")
prosta_funkcja()
Wynik:
Coś robię przed funkcją
Właściwa funkcja
Coś robię po funkcji
Jak to działa?
# Bez dekoratora (ręcznie)
def prosta_funkcja():
print("Właściwa funkcja")
prosta_funkcja = moj_dekorator(prosta_funkcja)
prosta_funkcja()
# Z dekoratorem (@) - to samo, krócej
@moj_dekorator
def prosta_funkcja():
print("Właściwa funkcja")
prosta_funkcja()
Praktyczny przykład – mierzenie czasu
import time
def zmierz_czas(func):
def wrapper():
start = time.time()
func()
koniec = time.time()
print(f"Czas wykonania: {koniec - start:.4f}s")
return wrapper
@zmierz_czas
def wolna_funkcja():
time.sleep(2)
print("Funkcja zakończona")
wolna_funkcja()
# Funkcja zakończona
# Czas wykonania: 2.0012s
Docstring – dokumentacja funkcji
Docstring to pierwszy string w funkcji – służy jako dokumentacja.
def oblicz_pole_kola(promien):
"""
Oblicza pole koła.
Argumenty:
promien (float): Promień koła
Zwraca:
float: Pole koła
Przykład:
>>> oblicz_pole_kola(5)
78.53975
"""
pi = 3.14159
return pi * promien ** 2
# Wyświetlanie docstringa
print(oblicz_pole_kola.__doc__)
# Lub funkcja help()
help(oblicz_pole_kola)
Dobre praktyki:
- Opisz co robi funkcja
- Wymień parametry i ich typy
- Opisz co zwraca
- Podaj przykłady użycia
Funkcje wbudowane Pythona
Python ma wiele wbudowanych funkcji, które poznałeś wcześniej:
Funkcje agregujące
liczby = [5, 2, 8, 1, 9, 3]
print(len(liczby)) # 6 - długość
print(sum(liczby)) # 28 - suma
print(max(liczby)) # 9 - maksimum
print(min(liczby)) # 1 - minimum
print(sorted(liczby)) # [1, 2, 3, 5, 8, 9] - sortowanie
Funkcje do iteracji
# enumerate - indeks + element
for i, wartosc in enumerate(['a', 'b', 'c']):
print(f"{i}: {wartosc}")
# 0: a
# 1: b
# 2: c
# zip - łączenie list
imiona = ['Jan', 'Anna', 'Piotr']
wieki = [25, 30, 28]
for imie, wiek in zip(imiona, wieki):
print(f"{imie}: {wiek}")
# Jan: 25
# Anna: 30
# Piotr: 28
Funkcje logiczne
# all - czy wszystkie True
print(all([True, True, True])) # True
print(all([True, False, True])) # False
# any - czy przynajmniej jeden True
print(any([False, False, True])) # True
print(any([False, False, False])) # False
Funkcje do konwersji
# bin - liczba → binarny string
print(bin(10)) # '0b1010'
# hex - liczba → szesnastkowy string
print(hex(255)) # '0xff'
# ord - znak → kod ASCII
print(ord('A')) # 65
# chr - kod ASCII → znak
print(chr(65)) # 'A'
Przykłady kompleksowe
Przykład 1: Kalkulator z funkcjami
def dodaj(a, b):
"""Dodaje dwie liczby."""
return a + b
def odejmij(a, b):
"""Odejmuje dwie liczby."""
return a - b
def pomnoz(a, b):
"""Mnoży dwie liczby."""
return a * b
def podziel(a, b):
"""Dzieli dwie liczby (z walidacją)."""
if b == 0:
return "Błąd: Dzielenie przez zero!"
return a / b
def kalkulator():
"""Prosty kalkulator."""
print("=== KALKULATOR ===")
a = float(input("Podaj pierwszą liczbę: "))
b = float(input("Podaj drugą liczbę: "))
print("\nOperacje:")
print(f"Dodawanie: {dodaj(a, b)}")
print(f"Odejmowanie: {odejmij(a, b)}")
print(f"Mnożenie: {pomnoz(a, b)}")
print(f"Dzielenie: {podziel(a, b)}")
kalkulator()
Przykład 2: Walidator danych
def waliduj_email(email):
"""Sprawdza czy email ma @ i kropkę."""
return '@' in email and '.' in email
def waliduj_haslo(haslo):
"""
Sprawdza czy hasło spełnia wymagania:
- min 8 znaków
- wielka litera
- mała litera
- cyfra
"""
if len(haslo) < 8:
return False, "Hasło za krótkie (min 8 znaków)"
if not any(c.isupper() for c in haslo):
return False, "Brak wielkiej litery"
if not any(c.islower() for c in haslo):
return False, "Brak małej litery"
if not any(c.isdigit() for c in haslo):
return False, "Brak cyfry"
return True, "Hasło poprawne"
def rejestracja():
"""System rejestracji z walidacją."""
email = input("Email: ")
if not waliduj_email(email):
print("Nieprawidłowy email!")
return
haslo = input("Hasło: ")
poprawne, komunikat = waliduj_haslo(haslo)
if not poprawne:
print(f"Błąd: {komunikat}")
return
print("Rejestracja zakończona pomyślnie!")
rejestracja()
Przykład 3: Konwerter temperatur
def celsius_na_fahrenheit(celsius):
"""Konwertuje °C na °F."""
return celsius * 9/5 + 32
def fahrenheit_na_celsius(fahrenheit):
"""Konwertuje °F na °C."""
return (fahrenheit - 32) * 5/9
def celsius_na_kelvin(celsius):
"""Konwertuje °C na K."""
return celsius + 273.15
def konwerter_temperatur():
"""Interaktywny konwerter temperatur."""
print("=== KONWERTER TEMPERATUR ===")
print("1. °C → °F")
print("2. °F → °C")
print("3. °C → K")
wybor = input("\nWybór (1-3): ")
temp = float(input("Temperatura: "))
if wybor == "1":
wynik = celsius_na_fahrenheit(temp)
print(f"{temp}°C = {wynik:.2f}°F")
elif wybor == "2":
wynik = fahrenheit_na_celsius(temp)
print(f"{temp}°F = {wynik:.2f}°C")
elif wybor == "3":
wynik = celsius_na_kelvin(temp)
print(f"{temp}°C = {wynik:.2f}K")
else:
print("Nieprawidłowy wybór!")
konwerter_temperatur()
Dobre praktyki
1. Jedna funkcja = jedno zadanie
# ŹLE - funkcja robi za dużo
def przetwarzaj_dane(dane):
# walidacja
# przetwarzanie
# zapis do pliku
# wysyłanie emaila
pass
# DOBRZE - każda funkcja robi jedno
def waliduj_dane(dane):
pass
def przetwarzaj(dane):
pass
def zapisz_do_pliku(dane):
pass
def wyslij_email():
pass
2. Opisowe nazwy
# ŹLE - niejasne
def f(x, y):
return x + y
# DOBRZE - jasne co robi
def oblicz_sume(liczba1, liczba2):
return liczba1 + liczba2
3. Dodawaj docstringi
# DOBRZE
def oblicz_bmi(waga, wzrost):
"""
Oblicza BMI (Body Mass Index).
Args:
waga (float): Waga w kilogramach
wzrost (float): Wzrost w metrach
Returns:
float: Wartość BMI
"""
return waga / (wzrost ** 2)
4. Unikaj zmiennych globalnych
# ŹLE - modyfikacja globalnej
licznik = 0
def zwieksz():
global licznik
licznik += 1
# LEPIEJ - przekazuj i zwracaj
def zwieksz(n):
return n + 1
licznik = 0
licznik = zwieksz(licznik)
5. Waliduj dane wejściowe
def podziel(a, b):
"""Bezpieczne dzielenie."""
if b == 0:
raise ValueError("Nie można dzielić przez zero!")
return a / b
# Lub zwracaj tuple
def podziel_bezpieczne(a, b):
if b == 0:
return None, "Błąd: dzielenie przez zero"
return a / b, "OK"
Ćwiczenia – Funkcje
Podstawy funkcji
- Napisz funkcję
powitanie()bez parametrów, która wyświetla „Witaj w świecie Pythona!”. - Napisz funkcję
powitaj_osobę(imie)która przyjmuje imię i wyświetla personalizowane powitanie. - Napisz funkcję
dodaj(a, b)która zwraca sumę dwóch liczb. - Napisz funkcję
pole_prostokata(dlugosc, szerokosc)która oblicza i zwraca pole prostokąta. - Napisz funkcję
przedstaw_sie(imie, nazwisko, wiek)która wyświetla wszystkie informacje w jednym zdaniu. - Napisz funkcję
czy_parzysta(liczba)która zwraca True jeśli liczba jest parzysta, False w przeciwnym razie. - Napisz funkcję
srednia(lista)która oblicza średnią arytmetyczną liczb z listy. - Napisz funkcję
najdluzsze_slowo(slowa)która zwraca najdłuższe słowo z listy. - Napisz funkcję
policz_samogloski(tekst)która zwraca liczbę samogłosek w tekście. - Napisz funkcję
odwroc_string(tekst)która zwraca tekst od tyłu.
Parametry domyślne
- Napisz funkcję
powitaj(imie, powitanie="Cześć")z domyślnym powitaniem. - Napisz funkcję
potega(liczba, wykladnik=2)która domyślnie podnosi do kwadratu. - Napisz funkcję
rabat(cena, procent=10)która domyślnie oblicza 10% rabatu. - Napisz funkcję
przedstaw(imie, nazwisko, tytul="Pan/Pani")z domyślnym tytułem. - Napisz funkcję
zakres_liczb(start, stop, krok=1)która generuje listę liczb z domyślnym krokiem 1.
Return vs Print
- Napisz dwie wersje funkcji mnożącej dwie liczby: jedną z
print, drugą zreturn. Porównaj ich działanie. - Napisz funkcję która zwraca sumę i iloczyn dwóch liczb (dwie wartości).
- Napisz funkcję
sprawdz_wiek(wiek)która zwraca „Pełnoletni” lub „Niepełnoletni”. - Napisz funkcję
podziel_bezpiecznie(a, b)która zwraca wynik dzielenia lub komunikat o błędzie przy dzieleniu przez zero. - Napisz funkcję
statystyki(lista)która zwraca krotkę: (suma, średnia, minimum, maksimum).
Zasięg zmiennych
- Stwórz zmienną globalną
licznik = 0. Napisz funkcję która próbuje ją zwiększyć bez słowaglobali sprawdź co się stanie. - Napisz funkcję która używa słowa
globaldo modyfikacji zmiennej globalnej. - Stwórz funkcję z lokalną zmienną o takiej samej nazwie jak globalna. Sprawdź która ma pierwszeństwo.
- Napisz funkcję zagnieżdżoną (funkcja w funkcji) i sprawdź zasięg zmiennych.
- Napisz funkcję
zwieksz(n)która zwracan + 1bez używania zmiennych globalnych.
*args – nieokreślona liczba argumentów
- Napisz funkcję
suma(*args)która sumuje dowolną liczbę argumentów. - Napisz funkcję
maksimum(*liczby)która znajduje największą liczbę spośród argumentów. - Napisz funkcję
srednia(*liczby)która oblicza średnią z dowolnej liczby argumentów. - Napisz funkcję
polacz_stringi(*stringi)która łączy wszystkie stringi spacjami. - Napisz funkcję
wszystkie_parzyste(*liczby)która sprawdza czy wszystkie argumenty są parzyste.
**kwargs – pary klucz-wartość
- Napisz funkcję
wyswietl_info(**dane)która wyświetla wszystkie pary klucz-wartość. - Napisz funkcję
zamowienie_pizzy(rozmiar, **dodatki)która oblicza cenę pizzy z dodatkami. - Napisz funkcję
profil_uzytkownika(**info)która tworzy słownik z danymi użytkownika. - Napisz funkcję
konfiguracja(**ustawienia)która przyjmuje dowolne ustawienia i je wyświetla. - Napisz funkcję
statystyki_gracza(imie, **statystyki)która wyświetla imię gracza i jego statystyki.
Łączenie *args i **kwargs
- Napisz funkcję
uniwersalna(a, b, *args, **kwargs)która wyświetla wszystkie typy argumentów. - Napisz funkcję
kalkulator(operacja, *liczby)która wykonuje operację na dowolnej liczbie argumentów. - Napisz funkcję
stworz_osobe(imie, nazwisko, **dodatkowe)która tworzy słownik osoby. - Napisz funkcję
log(poziom, *wiadomosci, **metadane)która loguje wiadomości z metadanymi. - Napisz funkcję
zaawansowane_zamowienie(nazwa, *produkty, **opcje)dla sklepu internetowego.
Rekursja
- Napisz rekurencyjną funkcję
silnia(n)obliczającą n!. - Napisz rekurencyjną funkcję
fibonacci(n)obliczającą n-ty element ciągu. - Napisz rekurencyjną funkcję
suma_od_1_do_n(n)sumującą liczby od 1 do n. - Napisz rekurencyjną funkcję
potega(a, n)obliczającą a^n. - Napisz rekurencyjną funkcję
dlugosc_listy(lista)obliczającą długość listy bez użycialen(). - Napisz rekurencyjną funkcję
suma_cyfr(n)sumującą cyfry liczby. - Napisz rekurencyjną funkcję
odwroc_liste(lista)odwracającą listę. - Napisz rekurencyjną funkcję
nwd(a, b)obliczającą największy wspólny dzielnik. - Napisz rekurencyjną funkcję wyświetlającą liczby od n do 0.
- Napisz rekurencyjną funkcję
jest_palindromem(tekst)sprawdzającą czy tekst jest palindromem.
Lambda
- Napisz lambdę która podnosi liczbę do kwadratu.
- Napisz lambdę która sprawdza czy liczba jest parzysta.
- Użyj lambda z
map()do podwojenia wszystkich liczb w liście. - Użyj lambda z
filter()do wybrania liczb większych od 10. - Użyj lambda z
sorted()do sortowania słów według długości. - Napisz lambdę która oblicza pole prostokąta (2 argumenty).
- Użyj lambda do sortowania listy krotek według drugiego elementu.
- Użyj lambda z
map()do zamiany listy temperatur Celsjusza na Fahrenheity. - Użyj lambda z
filter()do wybrania stringów zaczynających się na 'P’. - Napisz lambdę z if-else która zwraca „parzysta” lub „nieparzysta”.
Funkcje wbudowane
- Użyj
enumerate()do wyświetlenia listy z indeksami. - Użyj
zip()do połączenia dwóch list w listę krotek. - Użyj
all()do sprawdzenia czy wszystkie liczby w liście są dodatnie. - Użyj
any()do sprawdzenia czy w liście jest przynajmniej jedna liczba parzysta. - Użyj
bin()do wyświetlenia liczby 42 w systemie binarnym. - Użyj
sorted()z parametremkeydo sortowania listy słowników. - Policz ile jedynek jest w binarnej reprezentacji liczby 255.
- Użyj
map()z funkcjąlen()do znalezienia długości wszystkich słów w liście. - Użyj
filter()do wybrania tylko stringów z listy mieszanych typów. - Użyj
isinstance()do sprawdzenia typów elementów w liście.
Docstring i dokumentacja
- Napisz funkcję
oblicz_bmi(waga, wzrost)z pełnym docstringiem. - Napisz funkcję z docstringiem zawierającym przykłady użycia.
- Napisz moduł z 3 funkcjami, każda z docstringiem. Użyj
help()do wyświetlenia dokumentacji. - Napisz funkcję z docstringiem opisującym parametry, zwracaną wartość i możliwe wyjątki.
- Stwórz funkcję której docstring zawiera informacje o złożoności czasowej algorytmu.
Zadania praktyczne
- Napisz funkcję
waliduj_email(email)która sprawdza poprawność adresu email (@ i kropka). - Napisz funkcję
waliduj_pesel(pesel)która sprawdza czy PESEL ma 11 cyfr. - Napisz funkcję
generuj_haslo(dlugosc)która generuje losowe hasło. - Napisz funkcję
sprawdz_sile_hasla(haslo)która ocenia siłę hasła (słabe/średnie/silne). - Napisz funkcję
formatuj_numer_telefonu(numer)która formatuje numer na XXX-XXX-XXX. - Napisz funkcję
oblicz_wiek(data_urodzenia)która oblicza wiek na podstawie daty. - Napisz funkcję
czy_rok_przestepny(rok)sprawdzającą czy rok jest przestępny. - Napisz funkcję
konwertuj_temperature(temp, z_jednostki, do_jednostki)konwertującą temperatury. - Napisz funkcję
oblicz_vat(cena_netto, stawka_vat)obliczającą cenę brutto. - Napisz funkcję
skroc_tekst(tekst, max_dlugosc)która skraca tekst i dodaje „…”.
Zadania algorytmiczne
- Napisz funkcję
czy_pierwsza(n)sprawdzającą czy liczba jest pierwsza. - Napisz funkcję
liczby_pierwsze(n)zwracającą listę pierwszych n liczb pierwszych. - Napisz funkcję
nwd(a, b)obliczającą największy wspólny dzielnik (algorytm Euklidesa). - Napisz funkcję
nww(a, b)obliczającą najmniejszą wspólną wielokrotność. - Napisz funkcję
czy_anagram(slowo1, slowo2)sprawdzającą czy słowa są anagramami. - Napisz funkcję
sortuj_babelkowo(lista)implementującą sortowanie bąbelkowe. - Napisz funkcję
wyszukaj_binarne(lista, element)implementującą wyszukiwanie binarne. - Napisz funkcję
fibonacci_lista(n)zwracającą listę pierwszych n liczb Fibonacciego. - Napisz funkcję
suma_dzielnikow(n)zwracającą sumę dzielników liczby. - Napisz funkcję
czy_doskonala(n)sprawdzającą czy liczba jest doskonała (suma dzielników = liczba).
Zadania ze stringami
- Napisz funkcję
policz_slowa(tekst)licząca słowa w tekście. - Napisz funkcję
odwroc_slowa(zdanie)która odwraca kolejność słów. - Napisz funkcję
usun_samogloski(tekst)usuwającą samogłoski z tekstu. - Napisz funkcję
tytul_zdania(tekst)która zamienia pierwszą literę każdego słowa na wielką. - Napisz funkcję
czy_pangram(tekst)sprawdzającą czy tekst zawiera wszystkie litery alfabetu.
Zadania z listami i kolekcjami
- Napisz funkcję
usun_duplikaty(lista)usuwającą duplikaty z zachowaniem kolejności. - Napisz funkcję
czy_unikalne(lista)sprawdzającą czy lista zawiera tylko unikalne elementy. - Napisz funkcję
polacz_listy(*listy)łączącą dowolną liczbę list. - Napisz funkcję
podziel_liste(lista, n)dzielącą listę na n równych części. - Napisz funkcję
znajdz_najczestszy(lista)znajdującą najczęściej występujący element. - Napisz funkcję
rotuj_liste(lista, n)rotującą listę o n pozycji. - Napisz funkcję
spłaszcz_liste(lista)która spłaszcza zagnieżdżoną listę. - Napisz funkcję
transpozycja(macierz)wykonującą transpozycję macierzy (lista list). - Napisz funkcję
mediana(lista)obliczającą medianę liczb. - Napisz funkcję
moda(lista)znajdującą wartość najczęściej występującą.
Zadania ze słownikami
- Napisz funkcję
polacz_slowniki(*slowniki)łączącą wiele słowników. - Napisz funkcję
odwroc_slownik(slownik)zamieniającą klucze z wartościami. - Napisz funkcję
filtruj_slownik(slownik, klucze)zwracającą tylko wybrane klucze. - Napisz funkcję
sortuj_slownik_po_wartosciach(slownik)sortującą słownik według wartości. - Napisz funkcję
zlicz_wystapienia(lista)zwracającą słownik z licznikiem wystąpień.
Zadania kompleksowe
- Napisz system zarządzania kontaktami: funkcje dodaj_kontakt, usun_kontakt, znajdz_kontakt, wyswietl_wszystkie.
- Napisz kalkulator kredytu: funkcje oblicz_rate, oblicz_calkowity_koszt, generuj_harmonogram_splat.
- Napisz system ocen: funkcje dodaj_ocene, oblicz_srednia, najwyzsza_ocena, najnizsza_ocena, histogram_ocen.
- Napisz konwerter walut: funkcje pobierz_kurs, konwertuj, historia_konwersji.
- Napisz prosty system TODO: funkcje dodaj_zadanie, usun_zadanie, oznacz_jako_zrobione, wyswietl_zadania, filtruj_zadania.
PODSUMOWANIE
- Funkcja to nazwany fragment kodu, który definiujesz raz (
def) i wywołujesz wiele razy. Sama definicja niczego nie wykonuje – kod uruchamia dopiero wywołanienazwa(). - Definicja wymaga:
def, nazwy, nawiasów(), dwukropka i wcięcia (4 spacje). - Liczba argumentów przy wywołaniu musi pasować do parametrów, inaczej jest
TypeError. - Parametry z wartością domyślną zawsze na końcu listy parametrów, inaczej
SyntaxError. - Argumenty pozycyjne – liczy się kolejność. Argumenty nazwane – kolejność nie ma znaczenia, a przy mieszaniu pozycyjne idą przed nazwanymi.
printareturn:printtylko wyświetla, a funkcja bezreturnzwracaNone.returnoddaje wartość, którą można zapisać w zmiennej lub użyć w obliczeniach.returnkończy funkcję – kod po nim się nie wykona.- Wiele wartości w
return(return a, b) to w rzeczywistości krotka; można ją rozpakować:x, y = funkcja(). - Zasięg: zmienna z wnętrza funkcji jest lokalna i poza funkcją nie istnieje. Zmienna lokalna o tej samej nazwie co globalna ma pierwszeństwo.
- Zmianę zmiennej globalnej w funkcji umożliwia
global, ale lepiej przekazywać wartość i zwracać wynik. *argszbiera nadmiarowe argumenty pozycyjne w krotkę,**kwargs– nazwane w słownik. Kolejność w definicji: zwykłe, domyślne,*args,**kwargs.- Rekurencja to funkcja wywołująca samą siebie. Zawsze potrzebuje warunku zakończenia (np.
if n <= 1: return 1) i kroku, który zbliża do tego warunku. - Lambda to krótka funkcja anonimowa w jednej linii (
lambda x: x * x). Najczęściej używana zmap(),filter()isorted(key=...). Złożona logika – zwykła funkcja. - Dekorator (
@nazwa) to funkcja, która opakowuje inną funkcję i dodaje działanie przed/po jej wywołaniu. - Docstring (pierwszy string w funkcji) dokumentuje funkcję; wyświetlisz go przez
nazwa.__doc__lubhelp(nazwa). - Dobre praktyki: jedna funkcja = jedno zadanie, opisowe nazwy, docstring, unikanie
global.
Minimum, które powinno wejść w pamięć
Jeżeli masz zapamiętać tylko kilka rzeczy z tej lekcji, zapamiętaj te:
- Schemat:
def nazwa(parametry):+ wcięty kod. Definicja nic nie robi, dopóki nie wywołasz funkcji. print≠return. Funkcja bezreturnzwracaNone.returnkończy funkcję.- Liczba argumentów musi zgadzać się z parametrami. Parametry z wartością domyślną idą na końcu.
- Zmienne w funkcji są lokalne. Do zmiany globalnej potrzeba
global, ale lepiej: przekaż wartość → zwróć wynik. *args= krotka,**kwargs= słownik. Kolejność: zwykłe → domyślne →*args→**kwargs.- Rekurencja = warunek zakończenia + wywołanie z „mniejszym” argumentem.
lambda argumenty: wyrażenie– bezreturn, jedna linia.- Pułapka:
funkcja(bez nawiasów) to sama funkcja, afunkcja()to jej wywołanie. - Do samodzielnego napisania funkcji wystarczy: nazwa, parametry, ciało,
return, test wywołaniem.
Ściągawka – najważniejsze polecenia i składnia
Definicja i wywołanie
def nazwa(a, b=10): # b ma wartość domyślną
"""Krótki opis funkcji."""
return a + b
nazwa(1) # 11
nazwa(1, 2) # 3 (pozycyjnie)
nazwa(b=2, a=1) # 3 (nazwane)
Zwracanie wielu wartości
def f(a, b):
return a + b, a * b
suma, iloczyn = f(3, 4) # 7 i 12
Zasięg
licznik = 0
def zwieksz():
global licznik # tylko gdy musisz zmienić zmienną globalną
licznik += 1
*args i `kwargs`**
def f(a, b=2, *args, **kwargs):
...
f(1, 5, 7, 8, x=9) # a=1, b=5, args=(7, 8), kwargs={'x': 9}
Rekurencja
def silnia(n):
if n <= 1: # warunek zakończenia
return 1
return n * silnia(n - 1)
Lambda
kwadrat = lambda x: x * x
list(map(lambda x: x * 2, liczby)) # przetwórz każdy element
list(filter(lambda x: x > 5, liczby)) # zostaw elementy spełniające warunek
sorted(slowa, key=lambda w: len(w)) # sortuj według klucza
Dekorator
@moj_dekorator
def funkcja():
...
# to samo co: funkcja = moj_dekorator(funkcja)
Dokumentacja funkcji
print(nazwa.__doc__)
help(nazwa)
Typowe błędy
| Objaw | Najczęstsza przyczyna |
|---|---|
None zamiast wyniku | print zamiast return |
TypeError przy wywołaniu | zła liczba argumentów |
SyntaxError w nagłówku def | parametr domyślny przed zwykłym |
NameError poza funkcją | zmienna jest lokalna |
UnboundLocalError w funkcji | zmiana zmiennej globalnej bez global |
brak efektu po return | kod po return nie jest wykonywany |
Quiz – sprawdź się
1. Co zostanie wyświetlone?
def dodaj(a, b):
wynik = a + b
x = dodaj(2, 3)
print(x)
2. Wyjaśnij jednym–dwoma zdaniami różnicę między print a return w funkcji. Co jeszcze robi return poza zwracaniem wartości?
3. Która definicja funkcji jest poprawna?
- A)
def f(a, b=5, c): - B)
def f(a, c, b=5): - C)
def f(b=5, a, c):
4. Co zostanie wyświetlone?
def powitaj(imie, powitanie="Cześć"):
print(f"{powitanie}, {imie}!")
powitaj("Ola")
powitaj(powitanie="Hej", imie="Ola")
5. Znajdź błąd i podaj dwie wersje poprawki (jedną zalecaną, drugą z global).
licznik = 0
def zwieksz():
licznik += 1
zwieksz()
print(licznik)
6. Co zostanie wyświetlone?
x = "global"
def p():
x = "lokalna"
return x
print(p(), x)
7. Uzupełnij kod tak, aby s miało wartość 7, a i wartość 12.
def oblicz(a, b):
return ____
s, i = oblicz(3, 4)
8. Co zostanie wyświetlone?
def f(a, b=2, *args, **kwargs):
print(a, b, args, kwargs)
f(1, 5, 7, 8, x=9)
9. Uzupełnij funkcję, która sumuje dowolną liczbę argumentów.
def suma(____):
wynik = 0
for liczba in ____:
wynik += liczba
return wynik
print(suma(1, 2, 3)) # 6
10. Co zostanie wyświetlone? Który fragment kodu kończy rekurencję?
def odliczaj(n):
if n == 0:
print(0)
else:
print(n)
odliczaj(n - 1)
odliczaj(3)
11. Co zostanie wyświetlone?
liczby = [1, 2, 3, 4]
print(list(map(lambda x: x * 2, liczby)))
print(list(filter(lambda x: x > 2, liczby)))
print(sorted(["python", "ai", "kod"], key=lambda w: len(w)))
12. Co zostanie wyświetlone?
def moj_dekorator(func):
def wrapper():
print("przed")
func()
print("po")
return wrapper
@moj_dekorator
def hej():
print("hej")
hej()
13. Zadanie praktyczne: napisz funkcję czy_parzysta(liczba), która zwraca True, jeśli liczba jest parzysta, i False w przeciwnym razie. Dodaj docstring i dwa wywołania sprawdzające.
Odpowiedzi
1. None – funkcja nie ma return, więc zwraca None; wynik został tylko obliczony, nigdzie nie oddany.
2. print tylko wyświetla wartość na ekranie (funkcja i tak zwraca None), a return oddaje wartość, którą można zapisać w zmiennej lub użyć w obliczeniach. Dodatkowo return kończy działanie funkcji – kod po nim się nie wykona.
3. B. Parametry z wartością domyślną muszą być na końcu. W A i C jest SyntaxError.
4.
Cześć, Ola!
Hej, Ola!
Przy drugim wywołaniu argumenty nazwane, więc kolejność nie ma znaczenia.
5. Funkcja próbuje zmienić zmienną, która w jej wnętrzu jest traktowana jako lokalna, więc jest błąd (UnboundLocalError).
Wersja zalecana (bez global):
def zwieksz(n):
return n + 1
licznik = 0
licznik = zwieksz(licznik)
Wersja z global:
def zwieksz():
global licznik
licznik += 1
6. lokalna global – lokalna x ma pierwszeństwo w funkcji, a globalna x nie została zmieniona.
7. a + b, a * b
8. 1 5 (7, 8) {'x': 9} – a=1, b=5 (nadpisana wartość domyślna), reszta pozycyjnych trafia do krotki args, a nazwane do słownika kwargs.
9. def suma(*args): oraz for liczba in args:
10. Wynik (każda liczba w osobnej linii): 3, 2, 1, 0. Rekurencję kończy warunek if n == 0: – wtedy funkcja nie wywołuje już samej siebie.
11.
[2, 4, 6, 8]
[3, 4]
['ai', 'kod', 'python']
12.
przed
hej
po
Zapis @moj_dekorator jest równoważny z hej = moj_dekorator(hej).
13. Przykładowe rozwiązanie:
def czy_parzysta(liczba):
"""Zwraca True, jeśli liczba jest parzysta, w przeciwnym razie False."""
return liczba % 2 == 0
print(czy_parzysta(4)) # True
print(czy_parzysta(7)) # False
Zwróć uwagę, że funkcja używa return, a nie print, i że wynik porównania liczba % 2 == 0 jest już wartością True/False, więc nie trzeba pisać if.