<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kama Kaczmarek</title>
	<atom:link href="https://kamakaczmarek.net/feed/" rel="self" type="application/rss+xml" />
	<link>https://kamakaczmarek.net/</link>
	<description>Strona z materiałami dla uczniów i nauczycieli</description>
	<lastBuildDate>Wed, 10 Jun 2026 08:27:26 +0000</lastBuildDate>
	<language>pl-PL</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>23. Python – Generatory</title>
		<link>https://kamakaczmarek.net/23-python-generatory/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Wed, 10 Jun 2026 08:27:25 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=5126</guid>

					<description><![CDATA[<p>Generator&#160;to specjalna funkcja która zwraca iterator. Zamiast zwracać wszystkie wartości na raz, generuje je po kolei, &#8222;leniwie&#8221; (lazy evaluation). Dlaczego generatory? Kluczowe słowo:&#160;yield&#160;(zamiast&#160;return) Zwykła funkcja vs Generator Zwykła funkcja: Generator: Jak działa yield Kluczowe: Pierwszy praktyczny generator Generator vs Lista &#8211; porównanie pamięci Generator expressions (wyrażenia generatorowe) Podobne do list comprehensions, ale z&#160;()&#160;zamiast&#160;[]: Nieskończone generatory [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/23-python-generatory/">23. Python – Generatory</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Generator</strong>&nbsp;to specjalna funkcja która zwraca iterator. Zamiast zwracać wszystkie wartości na raz, generuje je po kolei, &#8222;leniwie&#8221; (lazy evaluation).</p>



<p class="wp-block-paragraph"><strong>Dlaczego generatory?</strong></p>



<ul class="wp-block-list">
<li>Oszczędność pamięci (nie trzymają wszystkich wartości)</li>



<li>Efektywność dla dużych zbiorów danych</li>



<li>Nieskończone sekwencje</li>



<li>Pipeline&#8217;y przetwarzania danych</li>
</ul>



<p class="wp-block-paragraph"><strong>Kluczowe słowo:</strong>&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">yield</code>&nbsp;(zamiast&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">return</code>)</p>



<h2 class="wp-block-heading">Zwykła funkcja vs Generator</h2>



<h3 class="wp-block-heading">Zwykła funkcja:</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def liczby_zwykla():
    """Zwraca listę - wszystko naraz w pamięci"""
    wynik = &#91;]
    for i in range(5):
        wynik.append(i)
    return wynik

print(liczby_zwykla())  # &#91;0, 1, 2, 3, 4]
</code></pre>



<h3 class="wp-block-heading">Generator:</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def liczby_generator():
    """Generator - zwraca po kolei"""
    for i in range(5):
        yield i  # yield zamiast append/return

# Generator nie wykonuje się od razu
gen = liczby_generator()
print(gen)  # &lt;generator object liczby_generator at 0x...&gt;

# Pobierz wartości po kolei
print(next(gen))  # 0
print(next(gen))  # 1
print(next(gen))  # 2

# Lub w pętli
for liczba in liczby_generator():
    print(liczba)
# 0, 1, 2, 3, 4
</code></pre>



<h2 class="wp-block-heading">Jak działa yield</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def prosty_generator():
    print("Start")
    yield 1
    print("Między 1 a 2")
    yield 2
    print("Między 2 a 3")
    yield 3
    print("Koniec")

gen = prosty_generator()

print("Pierwsza wartość:")
print(next(gen))
# Start
# 1

print("Druga wartość:")
print(next(gen))
# Między 1 a 2
# 2

print("Trzecia wartość:")
print(next(gen))
# Między 2 a 3
# 3

print("Próba czwartej:")
# next(gen)  # StopIteration - generator się wyczerpał
</code></pre>



<p class="wp-block-paragraph"><strong>Kluczowe:</strong></p>



<ul class="wp-block-list">
<li>Generator &#8222;zatrzymuje się&#8221; po każdym <code class="prettyprint lang-sql" style="font-size: 0.85em;">yield</code></li>



<li>Przy następnym <code class="prettyprint lang-sql" style="font-size: 0.85em;">next()</code> kontynuuje od miejsca zatrzymania</li>



<li>Zapamiętuje stan (zmienne lokalne)</li>
</ul>



<h2 class="wp-block-heading">Pierwszy praktyczny generator</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def liczby_parzyste(n):
    """Generuje liczby parzyste od 0 do n"""
    for i in range(n + 1):
        if i % 2 == 0:
            yield i

# Użycie
for liczba in liczby_parzyste(10):
    print(liczba)
# 0, 2, 4, 6, 8, 10
</code></pre>



<h2 class="wp-block-heading">Generator vs Lista &#8211; porównanie pamięci</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sys

# Lista - wszystko w pamięci
lista = &#91;x for x in range(1000000)]
print(f"Lista zajmuje: {sys.getsizeof(lista)} bajtów")
# Lista zajmuje: 8000056 bajtów

# Generator - tylko instrukcje
generator = (x for x in range(1000000))
print(f"Generator zajmuje: {sys.getsizeof(generator)} bajtów")
# Generator zajmuje: 104 bajty

# Generator jest ~77000 razy mniejszy!
</code></pre>



<h2 class="wp-block-heading">Generator expressions (wyrażenia generatorowe)</h2>



<p class="wp-block-paragraph">Podobne do list comprehensions, ale z&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">()</code>&nbsp;zamiast&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">[]</code>:</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># List comprehension - lista w pamięci
lista = &#91;x**2 for x in range(10)]
print(lista)  # &#91;0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# Generator expression - generator
generator = (x**2 for x in range(10))
print(generator)  # &lt;generator object ...&gt;

# Użycie
for wartosc in generator:
    print(wartosc)
</code></pre>



<h2 class="wp-block-heading">Nieskończone generatory</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def liczby_naturalne():
    """Nieskończony generator liczb naturalnych"""
    n = 0
    while True:  # Nieskończona pętla!
        yield n
        n += 1

# Użycie - pobierz pierwsze 10
gen = liczby_naturalne()
for i in range(10):
    print(next(gen))
# 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
</code></pre>



<h2 class="wp-block-heading">Generator Fibonacciego</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def fibonacci():
    """Nieskończony generator liczb Fibonacciego"""
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# Pierwsze 10 liczb
gen = fibonacci()
for i in range(10):
    print(next(gen))
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
</code></pre>



<h2 class="wp-block-heading">Generator z limitem</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def fibonacci_limit(limit):
    """Generator Fibonacciego do limitu"""
    a, b = 0, 1
    while a &lt;= limit:
        yield a
        a, b = b, a + b

# Wszystkie liczby Fibonacciego &lt;= 100
for liczba in fibonacci_limit(100):
    print(liczba)
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
</code></pre>



<h2 class="wp-block-heading">Generator odczytujący plik</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def czytaj_linie(nazwa_pliku):
    """Generator czytający plik linia po linii"""
    with open(nazwa_pliku, 'r', encoding='utf-8') as plik:
        for linia in plik:
            yield linia.strip()

# Użycie - oszczędność pamięci dla dużych plików
for linia in czytaj_linie('duzy_plik.txt'):
    print(linia)
    # Przetwarza jedną linię na raz, nie cały plik!
</code></pre>



<h2 class="wp-block-heading">Generator z filtrowaniem</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def wiersze_z_slowem(nazwa_pliku, slowo):
    """Generator zwracający wiersze zawierające słowo"""
    with open(nazwa_pliku, 'r', encoding='utf-8') as plik:
        for linia in plik:
            if slowo in linia:
                yield linia.strip()

# Znajdź wszystkie linie z "Python"
for linia in wiersze_z_slowem('log.txt', 'Python'):
    print(linia)
</code></pre>



<h2 class="wp-block-heading">Generator liczb pierwszych</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def liczby_pierwsze(limit):
    """Generator liczb pierwszych do limitu"""
    def czy_pierwsza(n):
        if n &lt; 2:
            return False
        for i in range(2, int(n**0.5) + 1):
            if n % i == 0:
                return False
        return True
    
    for n in range(2, limit + 1):
        if czy_pierwsza(n):
            yield n

# Wszystkie liczby pierwsze &lt;= 50
for liczba in liczby_pierwsze(50):
    print(liczba)
# 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47
</code></pre>



<h2 class="wp-block-heading">Generator z yield from</h2>



<p class="wp-block-paragraph"><code class="prettyprint lang-sql" style="font-size: 0.85em;">yield from</code>&nbsp;deleguje do innego generatora:</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def generator1():
    yield 1
    yield 2
    yield 3

def generator2():
    yield 4
    yield 5
    yield 6

def polaczony():
    yield from generator1()
    yield from generator2()

for wartosc in polaczony():
    print(wartosc)
# 1, 2, 3, 4, 5, 6
</code></pre>



<h2 class="wp-block-heading">Generator zagnieżdżonych list</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def splaszcz(lista):
    """Spłaszcza zagnieżdżoną listę"""
    for element in lista:
        if isinstance(element, list):
            yield from splaszcz(element)  # Rekurencja!
        else:
            yield element

zagniezdzona = &#91;1, &#91;2, 3, &#91;4, 5]], 6, &#91;7, &#91;8, 9]]]
for element in splaszcz(zagniezdzona):
    print(element)
# 1, 2, 3, 4, 5, 6, 7, 8, 9
</code></pre>



<h2 class="wp-block-heading">Praktyczne przykłady</h2>



<h3 class="wp-block-heading">Przykład 1: Przetwarzanie CSV</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def czytaj_csv(nazwa_pliku):
    """Generator wierszy CSV"""
    with open(nazwa_pliku, 'r', encoding='utf-8') as plik:
        naglowki = next(plik).strip().split(',')
        
        for linia in plik:
            wartosci = linia.strip().split(',')
            yield dict(zip(naglowki, wartosci))

# Użycie
for rekord in czytaj_csv('dane.csv'):
    print(rekord)
    # {'Imie': 'Jan', 'Wiek': '25', 'Miasto': 'Warszawa'}
</code></pre>



<h3 class="wp-block-heading">Przykład 2: Batching (grupowanie)</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def batches(iterable, rozmiar_batcha):
    """Dzieli iterable na batche o określonym rozmiarze"""
    batch = &#91;]
    for element in iterable:
        batch.append(element)
        if len(batch) == rozmiar_batcha:
            yield batch
            batch = &#91;]
    
    # Ostatni batch (może być mniejszy)
    if batch:
        yield batch

# Użycie
dane = range(1, 11)  # 1 do 10
for batch in batches(dane, 3):
    print(batch)
# &#91;1, 2, 3]
# &#91;4, 5, 6]
# &#91;7, 8, 9]
# &#91;10]
</code></pre>



<h3 class="wp-block-heading">Przykład 3: Sliding window</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def okno_przesuwne(iterable, rozmiar):
    """Generator okna przesuwnego"""
    from collections import deque
    okno = deque(maxlen=rozmiar)
    
    for element in iterable:
        okno.append(element)
        if len(okno) == rozmiar:
            yield list(okno)

# Użycie
dane = &#91;1, 2, 3, 4, 5, 6, 7]
for okno in okno_przesuwne(dane, 3):
    print(okno)
# &#91;1, 2, 3]
# &#91;2, 3, 4]
# &#91;3, 4, 5]
# &#91;4, 5, 6]
# &#91;5, 6, 7]
</code></pre>



<h3 class="wp-block-heading">Przykład 4: Pipeline przetwarzania</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def czytaj_liczby(nazwa_pliku):
    """Krok 1: Czytaj liczby z pliku"""
    with open(nazwa_pliku, 'r') as plik:
        for linia in plik:
            yield int(linia.strip())

def filtruj_parzyste(liczby):
    """Krok 2: Filtruj parzyste"""
    for liczba in liczby:
        if liczba % 2 == 0:
            yield liczba

def pomnoz_przez_2(liczby):
    """Krok 3: Pomnóż przez 2"""
    for liczba in liczby:
        yield liczba * 2

# Pipeline
liczby = czytaj_liczby('liczby.txt')
parzyste = filtruj_parzyste(liczby)
podwojone = pomnoz_przez_2(parzyste)

# Wszystko działa leniwie - przetwarza po jednej liczbie!
for wynik in podwojone:
    print(wynik)
</code></pre>



<h3 class="wp-block-heading">Przykład 5: Generator losowych danych</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import random

def losowe_liczby(ile, min_val, max_val):
    """Generator losowych liczb"""
    for _ in range(ile):
        yield random.randint(min_val, max_val)

def losowe_imiona(ile):
    """Generator losowych imion"""
    imiona = &#91;'Jan', 'Anna', 'Piotr', 'Ewa', 'Tomasz', 'Kasia']
    for _ in range(ile):
        yield random.choice(imiona)

# Użycie
for liczba in losowe_liczby(5, 1, 100):
    print(liczba)
# 42, 17, 89, 5, 63

for imie in losowe_imiona(3):
    print(imie)
# Anna, Piotr, Jan
</code></pre>



<h2 class="wp-block-heading">Send i Close</h2>



<p class="wp-block-paragraph">Generatory mogą również&nbsp;<strong>przyjmować</strong>&nbsp;wartości!</p>



<h3 class="wp-block-heading">send()</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def kalkulator():
    """Generator jako kalkulator"""
    wynik = 0
    while True:
        operacja = yield wynik
        if operacja is None:
            break
        
        akcja, liczba = operacja
        if akcja == 'dodaj':
            wynik += liczba
        elif akcja == 'odejmij':
            wynik -= liczba

# Użycie
kalk = kalkulator()
next(kalk)  # Uruchom generator

print(kalk.send(('dodaj', 10)))     # 10
print(kalk.send(('dodaj', 5)))      # 15
print(kalk.send(('odejmij', 3)))    # 12
</code></pre>



<h3 class="wp-block-heading">close()</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def nieskonczone_liczby():
    n = 0
    try:
        while True:
            yield n
            n += 1
    finally:
        print("Generator zamknięty - sprzątam")

gen = nieskonczone_liczby()
print(next(gen))  # 0
print(next(gen))  # 1
gen.close()       # Generator zamknięty - sprzątam
# print(next(gen))  # StopIteration
</code></pre>



<h2 class="wp-block-heading">Itertools &#8211; moduł z generatorami</h2>



<p class="wp-block-paragraph">Python ma wbudowany moduł&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">itertools</code>&nbsp;z potężnymi generatorami:</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import itertools

# count - nieskończone liczenie
for i in itertools.count(10, 2):
    if i &gt; 20:
        break
    print(i)
# 10, 12, 14, 16, 18, 20

# cycle - cykliczne powtarzanie
kolory = itertools.cycle(&#91;'czerwony', 'zielony', 'niebieski'])
for i, kolor in enumerate(kolory):
    if i &gt;= 6:
        break
    print(kolor)
# czerwony, zielony, niebieski, czerwony, zielony, niebieski

# repeat - powtarzanie n razy
for x in itertools.repeat('Python', 3):
    print(x)
# Python, Python, Python

# chain - łączenie iteratorów
for x in itertools.chain(&#91;1, 2, 3], &#91;'a', 'b', 'c']):
    print(x)
# 1, 2, 3, a, b, c

# islice - wycinki
for x in itertools.islice(range(100), 5, 15, 2):
    print(x)
# 5, 7, 9, 11, 13

# combinations - kombinacje
for combo in itertools.combinations(&#91;1, 2, 3, 4], 2):
    print(combo)
# (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)

# permutations - permutacje
for perm in itertools.permutations(&#91;1, 2, 3], 2):
    print(perm)
# (1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)
</code></pre>



<h2 class="wp-block-heading">Generator vs Iterator</h2>



<p class="wp-block-paragraph"><strong>Iterator</strong>&nbsp;to obiekt implementujący metody&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">__iter__()</code>&nbsp;i&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">__next__()</code>:</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class LicznikIterator:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current &gt;= self.limit:
            raise StopIteration
        self.current += 1
        return self.current

# Użycie
for i in LicznikIterator(5):
    print(i)
# 1, 2, 3, 4, 5
</code></pre>



<p class="wp-block-paragraph"><strong>Generator to prostsza składnia dla iteratora:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def licznik_generator(limit):
    for i in range(1, limit + 1):
        yield i

# To samo, krócej!
for i in licznik_generator(5):
    print(i)
# 1, 2, 3, 4, 5
</code></pre>



<h2 class="wp-block-heading">Podsumowanie Generatorów</h2>



<p class="wp-block-paragraph"><strong>Definicja:</strong></p>



<ul class="wp-block-list">
<li>Funkcja z <code class="prettyprint lang-sql" style="font-size: 0.85em;">yield</code> zamiast <code class="prettyprint lang-sql" style="font-size: 0.85em;">return</code></li>



<li>Zwraca iterator</li>



<li>Leniwa ewaluacja</li>
</ul>



<p class="wp-block-paragraph"><strong>Kluczowe słowa:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">yield</code> &#8211; zwróć wartość i zatrzymaj</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">yield from</code> &#8211; deleguj do innego generatora</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">next()</code> &#8211; pobierz następną wartość</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">send()</code> &#8211; wyślij wartość do generatora</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">close()</code> &#8211; zamknij generator</li>
</ul>



<p class="wp-block-paragraph"><strong>Zalety:</strong></p>



<ul class="wp-block-list">
<li>Oszczędność pamięci</li>



<li>Efektywność dla dużych danych</li>



<li>Nieskończone sekwencje</li>



<li>Pipeline&#8217;y przetwarzania</li>
</ul>



<p class="wp-block-paragraph"><strong>Zastosowania:</strong></p>



<ul class="wp-block-list">
<li>Przetwarzanie dużych plików</li>



<li>Strumienie danych</li>



<li>Pipeline&#8217;y transformacji</li>



<li>Nieskończone sekwencje</li>
</ul>



<p class="wp-block-paragraph"><strong>Generator expressions:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">(x for x in range(10))</code> &#8211; jak list comprehension ale z <code class="prettyprint lang-sql" style="font-size: 0.85em;">()</code></li>
</ul>



<h1 class="wp-block-heading">Ćwiczenia</h1>



<h2 class="wp-block-heading">Generatory</h2>



<ol class="wp-block-list">
<li>Napisz generator liczb od n do m z krokiem k.</li>



<li>Napisz generator liczb parzystych.</li>



<li>Napisz generator liczb nieparzystych.</li>



<li>Napisz generator Fibonacciego do limitu.</li>



<li>Napisz generator liczb pierwszych.</li>



<li>Napisz generator kwadratów liczb.</li>



<li>Napisz generator odwracający string znak po znaku.</li>



<li>Napisz generator czytający plik linia po linii.</li>



<li>Napisz generator filtrujący puste linie z pliku.</li>



<li>Napisz generator countdown (odliczanie).</li>
</ol>



<h2 class="wp-block-heading">Generatory &#8211; zaawansowane</h2>



<ol start="11" class="wp-block-list">
<li>Napisz generator spłaszczający zagnieżdżoną listę.</li>



<li>Napisz generator grupujący elementy w batche.</li>



<li>Napisz generator okna przesuwnego (sliding window).</li>



<li>Napisz generator permutacji listy.</li>



<li>Napisz generator kombinacji elementów.</li>



<li>Napisz generator kartezjańskiego iloczynu.</li>



<li>Napisz generator nieskończonych liczb Fibonacciego.</li>



<li>Napisz generator losowych liczb w zakresie.</li>



<li>Napisz generator dat między dwoma datami.</li>



<li>Napisz generator tokenów z tekstu.</li>
</ol>



<h2 class="wp-block-heading">Generator expressions</h2>



<ol start="21" class="wp-block-list">
<li>Stwórz generator expression kwadratów liczb 1-10.</li>



<li>Stwórz generator expression parzystych z listy.</li>



<li>Filtruj listę stringów (długość > 5) przez generator.</li>



<li>Stwórz generator sumujący elementy dwóch list.</li>



<li>Generator expression dla wielkich liter z tekstu.</li>
</ol>



<h2 class="wp-block-heading">Pipeline&#8217;y</h2>



<ol start="26" class="wp-block-list">
<li>Stwórz pipeline: czytaj liczby → filtruj parzyste → pomnóż × 2.</li>



<li>Pipeline: czytaj plik → filtruj linie ze słowem → zlicz.</li>



<li>Pipeline: generator liczb → filtruj pierwsze → sumuj.</li>



<li>Pipeline: czytaj CSV → przekształć dane → filtruj.</li>



<li>Pipeline: generuj losowe → filtruj zakres → agreguj.</li>
</ol>



<h2 class="wp-block-heading">Praktyczne zastosowania</h2>



<ol start="31" class="wp-block-list">
<li>Generator odczytujący duży plik CSV.</li>



<li>Generator przetwarzający logi (filtruj ERROR).</li>



<li>Generator paginacji (strony wyników).</li>



<li>Generator krokowy (skip n elementów).</li>



<li>Generator unikalnych elementów.</li>



<li>Generator zip dla wielu iteratorów.</li>



<li>Generator grupujący po kluczu.</li>



<li>Generator akumulujący (cumsum).</li>



<li>Generator take/drop (weź n, pomiń n).</li>



<li>Generator iterujący po drzewie katalogów.</li>
</ol>
<p>Artykuł <a href="https://kamakaczmarek.net/23-python-generatory/">23. Python – Generatory</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>22. Python &#8211; Closures (Domknięcia)</title>
		<link>https://kamakaczmarek.net/22-python-closures-domkniecia/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Wed, 10 Jun 2026 07:58:16 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=5124</guid>

					<description><![CDATA[<p>Closure (domknięcie)&#160;to funkcja, która &#8222;zapamiętuje&#8221; zmienne z zakresu zewnętrznego, nawet po zakończeniu wykonywania funkcji zewnętrznej. Kluczowe elementy: Dlaczego closures są ważne? Podstawy &#8211; funkcje zagnieżdżone Zwracanie funkcji wewnętrznej Ważne:&#160;Funkcja&#160;wewnetrzna&#160;&#8222;zapamiętała&#8221; zmienną&#160;wiadomosc&#160;mimo że&#160;zewnetrzna()&#160;już się zakończyła! Pierwszy prawdziwy closure Co się dzieje: Closure z wieloma zmiennymi Kluczowe słowo&#160;nonlocal: Przykład: Mnożnik Przykład: Funkcja potęgująca Closure ze stanem Zalety: Closure [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/22-python-closures-domkniecia/">22. Python &#8211; Closures (Domknięcia)</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Closure (domknięcie)</strong>&nbsp;to funkcja, która &#8222;zapamiętuje&#8221; zmienne z zakresu zewnętrznego, nawet po zakończeniu wykonywania funkcji zewnętrznej.</p>



<p class="wp-block-paragraph"><strong>Kluczowe elementy:</strong></p>



<ul class="wp-block-list">
<li>Funkcja zagnieżdżona (wewnątrz innej funkcji)</li>



<li>Funkcja wewnętrzna odwołuje się do zmiennych zewnętrznych</li>



<li>Funkcja zewnętrzna zwraca funkcję wewnętrzną</li>
</ul>



<p class="wp-block-paragraph"><strong>Dlaczego closures są ważne?</strong></p>



<ul class="wp-block-list">
<li>Enkapsulacja danych</li>



<li>Tworzenie funkcji fabryk</li>



<li>Dekoratory</li>



<li>Callbacks i event handlery</li>
</ul>



<h2 class="wp-block-heading">Podstawy &#8211; funkcje zagnieżdżone</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def zewnetrzna():
    """Funkcja zewnętrzna"""
    wiadomosc = "Hello"
    
    def wewnetrzna():
        """Funkcja wewnętrzna"""
        print(wiadomosc)  # Dostęp do zmiennej zewnętrznej
    
    wewnetrzna()

zewnetrzna()  # Hello
</code></pre>



<h2 class="wp-block-heading">Zwracanie funkcji wewnętrznej</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def zewnetrzna():
    wiadomosc = "Hello"
    
    def wewnetrzna():
        print(wiadomosc)
    
    return wewnetrzna  # Zwracamy funkcję (bez nawiasów!)

# Przypisz funkcję do zmiennej
funkcja = zewnetrzna()

# Wywołaj
funkcja()  # Hello
</code></pre>



<p class="wp-block-paragraph"><strong>Ważne:</strong>&nbsp;Funkcja&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">wewnetrzna</code>&nbsp;&#8222;zapamiętała&#8221; zmienną&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">wiadomosc</code>&nbsp;mimo że&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">zewnetrzna()</code>&nbsp;już się zakończyła!</p>



<h2 class="wp-block-heading">Pierwszy prawdziwy closure</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def stworz_powitanie(pozdrowienie):
    """Funkcja fabrykująca - tworzy spersonalizowane powitania"""
    
    def powitaj(imie):
        return f"{pozdrowienie}, {imie}!"
    
    return powitaj

# Stwórz różne funkcje powitań
hello = stworz_powitanie("Hello")
czesc = stworz_powitanie("Cześć")
hola = stworz_powitanie("Hola")

# Użycie
print(hello("Anna"))   # Hello, Anna!
print(czesc("Jan"))    # Cześć, Jan!
print(hola("Maria"))   # Hola, Maria!
</code></pre>



<p class="wp-block-paragraph"><strong>Co się dzieje:</strong></p>



<ol class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">stworz_powitanie("Hello")</code>&nbsp;tworzy funkcję&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">powitaj</code>&nbsp;która &#8222;pamięta&#8221;&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">pozdrowienie = "Hello"</code></li>



<li>Każde wywołanie tworzy niezależne closure z własną wartością</li>
</ol>



<h2 class="wp-block-heading">Closure z wieloma zmiennymi</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def licznik(start=0):
    """Tworzy licznik zaczynający od start"""
    count = start
    
    def increment():
        nonlocal count  # Pozwala modyfikować zmienną zewnętrzną
        count += 1
        return count
    
    return increment

# Stwórz liczniki
licznik1 = licznik(0)
licznik2 = licznik(100)

print(licznik1())  # 1
print(licznik1())  # 2
print(licznik1())  # 3

print(licznik2())  # 101
print(licznik2())  # 102
</code></pre>



<p class="wp-block-paragraph"><strong>Kluczowe słowo&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">nonlocal</code>:</strong></p>



<ul class="wp-block-list">
<li>Bez&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">nonlocal</code>&nbsp;&#8211; Python tworzy nową lokalną zmienną</li>



<li>Z&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">nonlocal</code>&nbsp;&#8211; modyfikuje zmienną z zakresu zewnętrznego</li>
</ul>



<h2 class="wp-block-heading">Przykład: Mnożnik</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def stworz_mnoznik(n):
    """Tworzy funkcję mnożącą przez n"""
    
    def mnoz(x):
        return x * n
    
    return mnoz

# Stwórz różne mnożniki
razy_2 = stworz_mnoznik(2)
razy_5 = stworz_mnoznik(5)
razy_10 = stworz_mnoznik(10)

print(razy_2(10))   # 20
print(razy_5(10))   # 50
print(razy_10(10))  # 100
</code></pre>



<h2 class="wp-block-heading">Przykład: Funkcja potęgująca</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def stworz_potege(wykladnik):
    """Tworzy funkcję podnoszącą do potęgi"""
    
    def poteguj(podstawa):
        return podstawa ** wykladnik
    
    return poteguj

# Różne potęgi
kwadrat = stworz_potege(2)
szescian = stworz_potege(3)
czwarta = stworz_potege(4)

print(kwadrat(5))   # 25
print(szescian(5))  # 125
print(czwarta(2))   # 16
</code></pre>



<h2 class="wp-block-heading">Closure ze stanem</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def stworz_konto(wlasciciel, saldo_poczatkowe=0):
    """Tworzy konto bankowe z enkapsulacją"""
    saldo = saldo_poczatkowe
    
    def wplata(kwota):
        nonlocal saldo
        if kwota &gt; 0:
            saldo += kwota
            return f"{wlasciciel}: Wpłata {kwota}. Saldo: {saldo}"
        return "Kwota musi być dodatnia"
    
    def wyplata(kwota):
        nonlocal saldo
        if kwota &gt; saldo:
            return f"{wlasciciel}: Brak środków. Saldo: {saldo}"
        if kwota &gt; 0:
            saldo -= kwota
            return f"{wlasciciel}: Wypłata {kwota}. Saldo: {saldo}"
        return "Kwota musi być dodatnia"
    
    def sprawdz_saldo():
        return f"{wlasciciel}: Saldo: {saldo}"
    
    # Zwróć słownik funkcji
    return {
        'wplata': wplata,
        'wyplata': wyplata,
        'saldo': sprawdz_saldo
    }

# Stwórz konta
konto_jan = stworz_konto("Jan", 1000)
konto_anna = stworz_konto("Anna", 500)

# Użycie
print(konto_jan&#91;'saldo']())        # Jan: Saldo: 1000
print(konto_jan&#91;'wplata'](500))    # Jan: Wpłata 500. Saldo: 1500
print(konto_jan&#91;'wyplata'](200))   # Jan: Wypłata 200. Saldo: 1300

print(konto_anna&#91;'saldo']())       # Anna: Saldo: 500
</code></pre>



<p class="wp-block-paragraph"><strong>Zalety:</strong></p>



<ul class="wp-block-list">
<li>Dane są prywatne (nie można bezpośrednio modyfikować&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">saldo</code>)</li>



<li>Każde konto ma niezależny stan</li>



<li>Enkapsulacja bez klas</li>
</ul>



<h2 class="wp-block-heading">Closure vs Klasy</h2>



<h3 class="wp-block-heading">Z klasą:</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Licznik:
    def __init__(self, start=0):
        self.count = start
    
    def increment(self):
        self.count += 1
        return self.count

licznik = Licznik(0)
print(licznik.increment())  # 1
</code></pre>



<h3 class="wp-block-heading">Z closure:</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def licznik(start=0):
    count = start
    
    def increment():
        nonlocal count
        count += 1
        return count
    
    return increment

licznik = licznik(0)
print(licznik())  # 1
</code></pre>



<p class="wp-block-paragraph"><strong>Kiedy używać:</strong></p>



<ul class="wp-block-list">
<li><strong>Closure</strong>&nbsp;&#8211; proste przypadki, enkapsulacja jednej funkcji</li>



<li><strong>Klasy</strong>&nbsp;&#8211; złożone obiekty, wiele metod, dziedziczenie</li>
</ul>



<h2 class="wp-block-heading">Praktyczne zastosowania</h2>



<h3 class="wp-block-heading">1. Dekoratory (najczęstsze!)</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def mierz_czas(funkcja):
    """Dekorator mierzący czas wykonania"""
    import time
    
    def wrapper(*args, **kwargs):
        start = time.time()
        wynik = funkcja(*args, **kwargs)
        koniec = time.time()
        print(f"{funkcja.__name__} wykonała się w {koniec - start:.4f}s")
        return wynik
    
    return wrapper

@mierz_czas
def wolna_funkcja():
    import time
    time.sleep(1)
    return "Gotowe"

wynik = wolna_funkcja()
# wolna_funkcja wykonała się w 1.0012s
</code></pre>



<h3 class="wp-block-heading">2. Funkcje fabrykujące</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def stworz_validator(min_dlugosc, max_dlugosc):
    """Tworzy validator długości"""
    
    def waliduj(tekst):
        dlugosc = len(tekst)
        if dlugosc &lt; min_dlugosc:
            return False, f"Za krótkie (min: {min_dlugosc})"
        if dlugosc &gt; max_dlugosc:
            return False, f"Za długie (max: {max_dlugosc})"
        return True, "OK"
    
    return waliduj

# Stwórz różne validatory
waliduj_haslo = stworz_validator(8, 20)
waliduj_nick = stworz_validator(3, 15)

print(waliduj_haslo("abc"))      # (False, 'Za krótkie (min: 8)')
print(waliduj_haslo("Python123")) # (True, 'OK')
print(waliduj_nick("Jo"))        # (False, 'Za krótkie (min: 3)')
</code></pre>



<h3 class="wp-block-heading">3. Callbacks z kontekstem</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def stworz_button_handler(button_id):
    """Tworzy handler dla przycisku"""
    klikniecia = 0
    
    def on_click():
        nonlocal klikniecia
        klikniecia += 1
        print(f"Przycisk {button_id} kliknięty {klikniecia} razy")
    
    return on_click

# Stwórz handlery
button1_click = stworz_button_handler("Zapisz")
button2_click = stworz_button_handler("Anuluj")

# Symulacja kliknięć
button1_click()  # Przycisk Zapisz kliknięty 1 razy
button1_click()  # Przycisk Zapisz kliknięty 2 razy
button2_click()  # Przycisk Anuluj kliknięty 1 razy
</code></pre>



<h3 class="wp-block-heading">4. Memoizacja (cache wyników)</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def memoize(funkcja):
    """Closure cache'ujące wyniki funkcji"""
    cache = {}
    
    def wrapper(*args):
        if args in cache:
            print(f"Zwracam z cache dla {args}")
            return cache&#91;args]
        
        print(f"Obliczam dla {args}")
        wynik = funkcja(*args)
        cache&#91;args] = wynik
        return wynik
    
    return wrapper

@memoize
def fibonacci(n):
    if n &lt; 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(5))
# Obliczam dla (5,)
# Obliczam dla (4,)
# Obliczam dla (3,)
# Obliczam dla (2,)
# Obliczam dla (1,)
# Obliczam dla (0,)
# Zwracam z cache dla (1,)
# Zwracam z cache dla (2,)
# Zwracam z cache dla (3,)
# 5
</code></pre>



<h3 class="wp-block-heading">5. Rate limiting</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def rate_limiter(max_calls, time_window):
    """Ogranicza liczbę wywołań funkcji w czasie"""
    import time
    calls = &#91;]
    
    def decorator(funkcja):
        def wrapper(*args, **kwargs):
            nonlocal calls
            teraz = time.time()
            
            # Usuń stare wywołania
            calls = &#91;c for c in calls if teraz - c &lt; time_window]
            
            if len(calls) &gt;= max_calls:
                return f"Za dużo wywołań! Max {max_calls} w {time_window}s"
            
            calls.append(teraz)
            return funkcja(*args, **kwargs)
        
        return wrapper
    return decorator

@rate_limiter(max_calls=3, time_window=10)
def wyslij_email(adres):
    return f"Email wysłany do {adres}"

# Pierwsze 3 wywołania - OK
print(wyslij_email("jan@test.com"))
print(wyslij_email("anna@test.com"))
print(wyslij_email("piotr@test.com"))

# 4-te - za dużo
print(wyslij_email("ewa@test.com"))
# Za dużo wywołań! Max 3 w 10s
</code></pre>



<h2 class="wp-block-heading">Inspekcja closure</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def zewnetrzna(x):
    def wewnetrzna(y):
        return x + y
    return wewnetrzna

closure_func = zewnetrzna(10)

# Sprawdź co closure "zapamiętała"
print(closure_func.__closure__)
# (&lt;cell at 0x...: int object at 0x...&gt;,)

# Wartość
print(closure_func.__closure__&#91;0].cell_contents)  # 10
</code></pre>



<h2 class="wp-block-heading">Podsumowanie Closures</h2>



<p class="wp-block-paragraph"><strong>Definicja:</strong></p>



<ul class="wp-block-list">
<li>Funkcja zagnieżdżona</li>



<li>Używa zmiennych z funkcji zewnętrznej</li>



<li>Jest zwracana przez funkcję zewnętrzną</li>
</ul>



<p class="wp-block-paragraph"><strong>Kluczowe słowa:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">nonlocal</code>&nbsp;&#8211; modyfikuj zmienną zewnętrzną</li>
</ul>



<p class="wp-block-paragraph"><strong>Zastosowania:</strong></p>



<ul class="wp-block-list">
<li>Dekoratory</li>



<li>Funkcje fabrykujące</li>



<li>Enkapsulacja danych</li>



<li>Callbacks z kontekstem</li>



<li>Memoizacja</li>
</ul>



<p class="wp-block-paragraph"><strong>Zalety:</strong></p>



<ul class="wp-block-list">
<li>Prywatne dane</li>



<li>Prostsza składnia niż klasy</li>



<li>Funkcyjne programowanie</li>
</ul>



<h2 class="wp-block-heading">Ćwiczenia</h2>



<ol class="wp-block-list">
<li>Napisz closure zwracające funkcję mnożącą przez dowolną liczbę.</li>



<li>Napisz closure tworzące licznik (increment, decrement, reset).</li>



<li>Napisz closure zapisujące historię wywołań funkcji.</li>



<li>Stwórz funkcję fabrykującą validatory (min długość, max długość).</li>



<li>Napisz closure implementujące prostą cache (memoizację).</li>



<li>Stwórz closure z prywatnym stanem (np. konto bankowe).</li>



<li>Napisz closure logujące wywołania funkcji.</li>



<li>Stwórz closure obliczające średnią ruchomą.</li>



<li>Napisz closure rate limitera (max wywołań w czasie).</li>



<li>Stwórz closure generujące unikalne ID.</li>
</ol>
<p>Artykuł <a href="https://kamakaczmarek.net/22-python-closures-domkniecia/">22. Python &#8211; Closures (Domknięcia)</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>22. Python – Debugging (Debugowanie)</title>
		<link>https://kamakaczmarek.net/22-python-debugging-debugowanie/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 11:54:37 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=5092</guid>

					<description><![CDATA[<p>Debugging&#160;to proces znajdowania i naprawiania błędów (bugów) w kodzie. Rodzaje błędów: Dlaczego debugging jest ważny? Metody debugowania 1. Print debugging (najprostsza) Zalety: Wady: 2. Asercje (Assertions) Użycie: Python 3. Logging &#8211; profesjonalne logowanie Poziomy logowania: 4. Debugger PDB (Python Debugger) PDB&#160;to wbudowany debugger w Pythonie. Podstawowe komendy PDB: 5. Breakpoint() &#8211; Python 3.7+ breakpoint()&#160;to to [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/22-python-debugging-debugowanie/">22. Python – Debugging (Debugowanie)</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Debugging</strong>&nbsp;to proces znajdowania i naprawiania błędów (bugów) w kodzie.</p>



<p class="wp-block-paragraph"><strong>Rodzaje błędów:</strong></p>



<ol class="wp-block-list">
<li><strong>Składniowe</strong>&nbsp;(Syntax Errors) &#8211; błędy w kodzie, program się nie uruchomi</li>



<li><strong>Runtime Errors</strong>&nbsp;&#8211; błędy podczas działania (wyjątki)</li>



<li><strong>Logiczne</strong>&nbsp;&#8211; program działa, ale wyniki są błędne</li>
</ol>



<p class="wp-block-paragraph"><strong>Dlaczego debugging jest ważny?</strong></p>



<ul class="wp-block-list">
<li>Każdy kod ma bugi</li>



<li>Debugowanie to 50%+ czasu programisty</li>



<li>Umiejętność szybkiego znajdowania błędów = produktywność</li>
</ul>



<h2 class="wp-block-heading">Metody debugowania</h2>



<h3 class="wp-block-heading">1. Print debugging (najprostsza)</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def oblicz_srednia(liczby):
    suma = 0
    for liczba in liczby:
        print(f"Dodaję: {liczba}")  # Debug
        suma += liczba
    
    print(f"Suma: {suma}")  # Debug
    print(f"Liczba elementów: {len(liczby)}")  # Debug
    
    srednia = suma / len(liczby)
    print(f"Średnia: {srednia}")  # Debug
    
    return srednia

wynik = oblicz_srednia(&#91;10, 20, 30])</code></pre>



<p class="wp-block-paragraph"><strong>Zalety:</strong></p>



<ul class="wp-block-list">
<li>Proste</li>



<li>Szybkie</li>



<li>Działa wszędzie</li>
</ul>



<p class="wp-block-paragraph"><strong>Wady:</strong></p>



<ul class="wp-block-list">
<li>Trzeba pamiętać o usunięciu printów</li>



<li>Nieefektywne dla złożonych problemów</li>
</ul>



<h3 class="wp-block-heading">2. Asercje (Assertions)</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def podziel(a, b):
    assert b != 0, "Dzielnik nie może być zerem!"
    return a / b

# Asercja sprawdza warunek
# Jeśli False → AssertionError z komunikatem

wynik = podziel(10, 2)  # OK
# wynik = podziel(10, 0)  # AssertionError: Dzielnik nie może być zerem!</code></pre>



<p class="wp-block-paragraph"><strong>Użycie:</strong></p>



<ul class="wp-block-list">
<li>Sprawdzanie założeń</li>



<li>Walidacja stanów wewnętrznych</li>



<li>Tylko w fazie rozwoju (wyłączane w produkcji)</li>
</ul>



<p class="wp-block-paragraph">Python</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def oblicz_srednia(liczby):
    assert len(liczby) > 0, "Lista nie może być pusta!"
    assert all(isinstance(x, (int, float)) for x in liczby), "Wszystkie elementy muszą być liczbami!"
    
    return sum(liczby) / len(liczby)</code></pre>



<h3 class="wp-block-heading">3. Logging &#8211; profesjonalne logowanie</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import logging

# Konfiguracja
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def oblicz_srednia(liczby):
    logging.debug(f"Wywołano oblicz_srednia z {liczby}")
    
    if not liczby:
        logging.error("Lista jest pusta!")
        return None
    
    suma = sum(liczby)
    logging.info(f"Suma: {suma}")
    
    srednia = suma / len(liczby)
    logging.info(f"Średnia: {srednia}")
    
    return srednia

wynik = oblicz_srednia(&#91;10, 20, 30])</code></pre>



<p class="wp-block-paragraph"><strong>Poziomy logowania:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">DEBUG</code>&nbsp;&#8211; szczegółowe informacje diagnostyczne</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">INFO</code>&nbsp;&#8211; potwierdzenie że wszystko działa</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">WARNING</code>&nbsp;&#8211; coś nieprzewidzianego, ale program działa</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">ERROR</code>&nbsp;&#8211; poważny problem</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">CRITICAL</code>&nbsp;&#8211; program może się zatrzymać</li>
</ul>



<h3 class="wp-block-heading">4. Debugger PDB (Python Debugger)</h3>



<p class="wp-block-paragraph"><strong>PDB</strong>&nbsp;to wbudowany debugger w Pythonie.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pdb

def oblicz_srednia(liczby):
    suma = 0
    
    for liczba w liczby:
        pdb.set_trace()  # ← Breakpoint - program się zatrzyma tutaj
        suma += liczba
    
    return suma / len(liczby)

oblicz_srednia(&#91;10, 20, 30])</code></pre>



<p class="wp-block-paragraph"><strong>Podstawowe komendy PDB:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">l</code>&nbsp;(list) &#8211; pokaż kod</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">n</code>&nbsp;(next) &#8211; następna linia</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">s</code>&nbsp;(step) &#8211; wejdź do funkcji</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">c</code>&nbsp;(continue) &#8211; kontynuuj do następnego breakpointa</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">p zmienna</code>&nbsp;&#8211; wypisz wartość zmiennej</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">pp zmienna</code>&nbsp;&#8211; ładnie wypisz</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">h</code>&nbsp;(help) &#8211; pomoc</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">q</code>&nbsp;(quit) &#8211; wyjdź</li>
</ul>



<h3 class="wp-block-heading">5. Breakpoint() &#8211; Python 3.7+</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def oblicz_srednia(liczby):
    suma = 0
    
    for liczba in liczby:
        breakpoint()  # ← Nowocześniejszy sposób
        suma += liczba
    
    return suma / len(liczby)

oblicz_srednia(&#91;10, 20, 30])</code></pre>



<p class="wp-block-paragraph"><code class="prettyprint lang-sql" style="font-size: 0.85em;">breakpoint()</code>&nbsp;to to samo co&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">pdb.set_trace()</code>, ale lepsze (można łatwo wyłączyć wszystkie).</p>



<h2 class="wp-block-heading">Debugowanie w IDE</h2>



<h3 class="wp-block-heading">Visual Studio Code</h3>



<p class="wp-block-paragraph"><a href="https://code.visualstudio.com/docs/debugtest/debugging">Dokumentacja debuggowania</a></p>



<h4 class="wp-block-heading">Interfejs użytkownika debuggera</h4>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="681" src="https://kamakaczmarek.net/wp-content/uploads/debugging_hero-1024x681.png" alt="" class="wp-image-5115" srcset="https://kamakaczmarek.net/wp-content/uploads/debugging_hero-1024x681.png 1024w, https://kamakaczmarek.net/wp-content/uploads/debugging_hero-300x200.png 300w, https://kamakaczmarek.net/wp-content/uploads/debugging_hero-768x511.png 768w, https://kamakaczmarek.net/wp-content/uploads/debugging_hero-1536x1022.png 1536w, https://kamakaczmarek.net/wp-content/uploads/debugging_hero.png 1892w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<ul class="wp-block-list">
<li><strong>Widok Uruchom i debuguj</strong> : wyświetla wszystkie informacje dotyczące uruchamiania, debugowania i zarządzania ustawieniami konfiguracji debugowania.</li>



<li><strong>Pasek narzędzi debugowania</strong> : zawiera przyciski umożliwiające wykonywanie najczęściej spotykanych czynności debugowania.</li>



<li><strong>Konsola debugowania</strong> : umożliwia przeglądanie i interakcję z wynikami kodu uruchomionego w debugerze.</li>



<li><strong>Pasek boczny debugowania</strong> : w trakcie sesji debugowania umożliwia interakcję ze stosem wywołań, punktami przerwania, zmiennymi i zmiennymi obserwowanymi.</li>



<li><strong>Menu Uruchom</strong> : zawiera najczęstsze polecenia uruchamiania i debugowania.</li>
</ul>



<h4 class="wp-block-heading">Rozpocznij sesję debugowania</h4>



<ul class="wp-block-list">
<li>Otwórz plik zawierający kod, który chcesz debugować.</li>



<li>Rozpocznij sesję debugowania klawiszem F5 lub wybierz opcję <strong>Uruchom i debuguj</strong> w widoku <strong>Uruchom i debuguj</strong> ( <code class="prettyprint lang-sql" style="font-size: 0.85em;">workbench.view.debug</code>).</li>
</ul>



<figure class="wp-block-image size-full"><img decoding="async" width="400" height="339" src="https://kamakaczmarek.net/wp-content/uploads/debug-start.png" alt="" class="wp-image-5117" srcset="https://kamakaczmarek.net/wp-content/uploads/debug-start.png 400w, https://kamakaczmarek.net/wp-content/uploads/debug-start-300x254.png 300w" sizes="(max-width: 400px) 100vw, 400px" /></figure>



<p class="wp-block-paragraph">W przypadku bardziej złożonych scenariuszy debugowania, takich jak dołączanie do działającego procesu, należy utworzyć <br /><code class="prettyprint lang-sql" style="font-size: 0.85em;">launch.json</code>plik określający konfigurację debugera. Więcej informacji na temat <br />konfiguracji debugowania znajdziesz tutaj .</p>



<ul class="wp-block-list">
<li>Z listy dostępnych debugerów wybierz debuger, którego chcesz użyć.VS Code próbuje uruchomić i debugować aktualnie aktywny plik. W przypadku Node.js, VS Code sprawdza, czy <code class="prettyprint lang-sql" style="font-size: 0.85em;">start</code>w <code class="prettyprint lang-sql" style="font-size: 0.85em;">package.json</code>pliku znajduje się skrypt, aby określić punkt wejścia aplikacji.</li>



<li>Po rozpoczęciu sesji debugowania wyświetlany jest panel <strong>DEBUG CONSOLE</strong> z wynikami debugowania, a pasek stanu zmienia kolor (domyślny motyw kolorystyczny jest pomarańczowy).</li>
</ul>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="541" src="https://kamakaczmarek.net/wp-content/uploads/debug-session-1024x541.png" alt="" class="wp-image-5118" srcset="https://kamakaczmarek.net/wp-content/uploads/debug-session-1024x541.png 1024w, https://kamakaczmarek.net/wp-content/uploads/debug-session-300x158.png 300w, https://kamakaczmarek.net/wp-content/uploads/debug-session-768x406.png 768w, https://kamakaczmarek.net/wp-content/uploads/debug-session.png 1272w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph"><strong>Podstawowe funkcje:</strong></p>



<p class="wp-block-paragraph">Po rozpoczęciu sesji debugowania u góry okna pojawia się pasek narzędzi Debugowanie. Pasek zawiera akcje sterujące przebiegiem sesji debugowania, takie jak przechodzenie przez kod krok po kroku, wstrzymywanie wykonywania i zatrzymywanie sesji debugowania.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="297" height="44" src="https://kamakaczmarek.net/wp-content/uploads/toolbar.png" alt="" class="wp-image-5119"/></figure>



<ul class="wp-block-list">
<li><strong>F9</strong>&nbsp;&#8211; ustaw/usuń breakpoint</li>



<li><strong>F5</strong> &#8211; rozpocznij debugowanie </li>



<li><strong>F10</strong>&nbsp;&#8211; następna linia (step over)</li>



<li><strong>F11</strong>&nbsp;&#8211; wejdź do funkcji (step into)</li>



<li><strong>Shift+F11</strong>&nbsp;&#8211; wyjdź z funkcji (step out)</li>



<li><strong>F5</strong>&nbsp;&#8211; kontynuuj</li>
</ul>



<h4 class="wp-block-heading">Punkty przerwania</h4>



<p class="wp-block-paragraph">Punkt przerwania to specjalny znacznik, który wstrzymuje wykonywanie kodu w określonym momencie, umożliwiając sprawdzenie stanu aplikacji w tym momencie. VS Code obsługuje kilka typów punktów przerwania</p>



<p class="wp-block-paragraph"><strong>Ustawianie punktów przerwania</strong></p>



<p class="wp-block-paragraph">Aby ustawić lub usunąć punkt przerwania, kliknij&nbsp;<strong>margines edytora</strong>&nbsp;lub użyj&nbsp;klawisza F9&nbsp;w bieżącym wierszu.</p>



<ul class="wp-block-list">
<li>Punkty przerwania na marginesie edytora są zazwyczaj wyświetlane jako wypełnione na czerwono kółka.</li>



<li>Wyłączone punkty przerwania są oznaczone wypełnionym szarym okręgiem.</li>



<li>Po uruchomieniu sesji debugowania punkty przerwania, których nie można zarejestrować w debugerze, zmieniają się w szare, puste kółko. To samo może się zdarzyć, jeśli kod źródłowy jest edytowany podczas sesji debugowania bez obsługi edycji na żywo.</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="801" height="289" src="https://kamakaczmarek.net/wp-content/uploads/bpts-in-overview.png" alt="" class="wp-image-5120" srcset="https://kamakaczmarek.net/wp-content/uploads/bpts-in-overview.png 801w, https://kamakaczmarek.net/wp-content/uploads/bpts-in-overview-300x108.png 300w, https://kamakaczmarek.net/wp-content/uploads/bpts-in-overview-768x277.png 768w" sizes="(max-width: 801px) 100vw, 801px" /></figure>



<p class="wp-block-paragraph">Aby mieć większą kontrolę nad punktami przerwania, skorzystaj z sekcji <br /><strong>„PUNKTY PRZERWANIA”</strong> w widoku <br /><strong>„Uruchom i debuguj”</strong> . Ta sekcja zawiera listę wszystkich punktów przerwania w kodzie i udostępnia dodatkowe akcje do zarządzania nimi.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="801" height="419" src="https://kamakaczmarek.net/wp-content/uploads/breakpoints.png" alt="" class="wp-image-5121" srcset="https://kamakaczmarek.net/wp-content/uploads/breakpoints.png 801w, https://kamakaczmarek.net/wp-content/uploads/breakpoints-300x157.png 300w, https://kamakaczmarek.net/wp-content/uploads/breakpoints-768x402.png 768w" sizes="(max-width: 801px) 100vw, 801px" /></figure>



<h3 class="wp-block-heading">PyCharm</h3>



<p class="wp-block-paragraph"><strong>Podobne funkcje:</strong></p>



<ul class="wp-block-list">
<li>Kliknij na marginesie obok linii → breakpoint</li>



<li><strong>Shift+F9</strong>&nbsp;&#8211; debuguj</li>



<li><strong>F8</strong>&nbsp;&#8211; następna linia</li>



<li><strong>F7</strong>&nbsp;&#8211; wejdź do funkcji</li>
</ul>



<h2 class="wp-block-heading">Techniki debugowania</h2>



<h3 class="wp-block-heading">1. Rubber Duck Debugging</h3>



<p class="wp-block-paragraph"><strong>Metoda:</strong>&nbsp;Wyjaśnij swój kod &#8222;gumowej kaczce&#8221; (lub koledze) linijka po linijce.</p>



<p class="wp-block-paragraph"><strong>Dlaczego działa:</strong>&nbsp;Wymuszając werbalizację często sam znajdziesz błąd.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="724" height="1024" src="https://kamakaczmarek.net/wp-content/uploads/ZSE-rubber-duck-debugging-724x1024.png" alt="" class="wp-image-5096" srcset="https://kamakaczmarek.net/wp-content/uploads/ZSE-rubber-duck-debugging-724x1024.png 724w, https://kamakaczmarek.net/wp-content/uploads/ZSE-rubber-duck-debugging-212x300.png 212w, https://kamakaczmarek.net/wp-content/uploads/ZSE-rubber-duck-debugging-768x1086.png 768w, https://kamakaczmarek.net/wp-content/uploads/ZSE-rubber-duck-debugging-1086x1536.png 1086w, https://kamakaczmarek.net/wp-content/uploads/ZSE-rubber-duck-debugging.png 1414w" sizes="(max-width: 724px) 100vw, 724px" /></figure>
</div>


<h3 class="wp-block-heading">2. Dziel i zwyciężaj</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Błąd gdzieś w tym kodzie
def skomplikowana_funkcja(dane):
    # 100 linii kodu
    ...
    return wynik

# Podziel na mniejsze części
def czesc1(dane):
    print("Po części 1:", dane)  # Debug
    return wynik1

def czesc2(dane):
    print("Po części 2:", dane)  # Debug
    return wynik2

def czesc3(dane):
    print("Po części 3:", dane)  # Debug
    return wynik3</code></pre>



<h3 class="wp-block-heading">3. Binary Search Debugging</h3>



<p class="wp-block-paragraph">Jeśli wiesz że błąd jest w 100-liniowej funkcji:</p>



<ol class="wp-block-list">
<li>Dodaj print/breakpoint w linii 50</li>



<li>Sprawdź czy błąd jest przed czy po</li>



<li>Powtarzaj aż znajdziesz</li>
</ol>



<h3 class="wp-block-heading">4. Zrozum komunikat błędu</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">Traceback (most recent call last):
  File "program.py", line 10, in &lt;module>
    wynik = oblicz(5, 0)
  File "program.py", line 6, in oblicz
    return a / b
ZeroDivisionError: division by zero</code></pre>



<p class="wp-block-paragraph"><strong>Jak czytać:</strong></p>



<ul class="wp-block-list">
<li><strong>Od dołu do góry!</strong></li>



<li>Ostatnia linia = typ błędu i komunikat</li>



<li>Powyżej = stos wywołań (gdzie nastąpił błąd)</li>
</ul>



<h2 class="wp-block-heading">Częste błędy i jak je debugować</h2>



<h3 class="wp-block-heading">1. NameError &#8211; niezdefiniowana zmienna</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">print(zmiennna)  # NameError: name 'zmiennna' is not defined

# Debug:
# - Sprawdź literówki
# - Czy zmienna została zdefiniowana?
# - Czy jesteś w odpowiednim zakresie (scope)?</code></pre>



<h3 class="wp-block-heading">2. IndexError &#8211; indeks poza zakresem</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">lista = &#91;1, 2, 3]
print(lista&#91;5])  # IndexError: list index out of range

# Debug:
print(f"Długość listy: {len(lista)}")
print(f"Próbuję dostać się do indeksu: 5")
# Aha! 5 >= 3</code></pre>



<h3 class="wp-block-heading">3. KeyError &#8211; brak klucza w słowniku</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">slownik = {"klucz1": "wartość1"}
print(slownik&#91;"klucz2"])  # KeyError: 'klucz2'

# Debug:
print(f"Dostępne klucze: {slownik.keys()}")
# Użyj get() zamiast &#91;]
print(slownik.get("klucz2", "Domyślna"))</code></pre>



<h3 class="wp-block-heading">4. TypeError &#8211; niewłaściwy typ</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">wynik = "5" + 5  # TypeError: can only concatenate str (not "int") to str

# Debug:
print(f"Typ pierwszej wartości: {type('5')}")  # str
print(f"Typ drugiej wartości: {type(5)}")      # int
# Konwertuj:
wynik = "5" + str(5)  # lub int("5") + 5</code></pre>



<h3 class="wp-block-heading">5. AttributeError &#8211; brak atrybutu</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">lista = &#91;1, 2, 3]
lista.add(4)  # AttributeError: 'list' object has no attribute 'add'

# Debug:
print(f"Typ obiektu: {type(lista)}")
print(f"Dostępne metody: {dir(lista)}")
# Poprawka:
lista.append(4)</code></pre>



<h2 class="wp-block-heading">Narzędzia pomocnicze</h2>



<h3 class="wp-block-heading">1. traceback &#8211; szczegółowe informacje o błędzie</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import traceback

try:
    wynik = 10 / 0
except Exception as e:
    print("Wystąpił błąd:")
    traceback.print_exc()
    
    # Lub zapisz do pliku
    with open('error.log', 'w') as f:
        traceback.print_exc(file=f)</code></pre>



<h3 class="wp-block-heading">2. sys.exc_info() &#8211; informacje o wyjątku</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sys

try:
    wynik = 10 / 0
except:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    print(f"Typ: {exc_type}")
    print(f"Wartość: {exc_value}")
    print(f"Traceback: {exc_traceback}")</code></pre>



<h3 class="wp-block-heading">3. inspect &#8211; inspekcja obiektów</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import inspect

def moja_funkcja(a, b):
    return a + b

# Informacje o funkcji
print(inspect.getsource(moja_funkcja))  # Kod źródłowy
print(inspect.signature(moja_funkcja))  # Sygnatura: (a, b)</code></pre>



<h3 class="wp-block-heading">4. dis &#8211; disassembler</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import dis

def dodaj(a, b):
    return a + b

# Zobacz bytecode Pythona
dis.dis(dodaj)</code></pre>



<h2 class="wp-block-heading">Praktyczne przykłady debugowania</h2>



<h3 class="wp-block-heading">Przykład 1: Błąd logiczny</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Kod ma błąd - znajdź go!
def oblicz_srednia_ocen(oceny):
    suma = 0
    licznik = 0
    
    for ocena in oceny:
        suma += ocena
        licznik += 1
    
    return suma / licznik  # Dzielenie przez zero?

# Test
print(oblicz_srednia_ocen(&#91;4, 5, 3]))  # Działa
print(oblicz_srednia_ocen(&#91;]))  # ZeroDivisionError!

# Debug z printami
def oblicz_srednia_ocen_debug(oceny):
    print(f"Wejście: {oceny}")
    print(f"Długość: {len(oceny)}")
    
    suma = 0
    licznik = 0
    
    for ocena in oceny:
        suma += ocena
        licznik += 1
        print(f"Suma: {suma}, Licznik: {licznik}")
    
    if licznik == 0:
        print("UWAGA: Dzielenie przez zero!")
        return None
    
    return suma / licznik

# Poprawiona wersja
def oblicz_srednia_ocen_fix(oceny):
    if not oceny:
        return 0  # lub raise ValueError("Lista ocen jest pusta")
    
    return sum(oceny) / len(oceny)</code></pre>



<h3 class="wp-block-heading">Przykład 2: Debugowanie z PDB</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pdb

def faktoryzacja(n):
    """Zwraca dzielniki liczby n."""
    dzielniki = &#91;]
    
    for i in range(1, n + 1):
        pdb.set_trace()  # Zatrzymaj się tutaj
        if n % i == 0:
            dzielniki.append(i)
    
    return dzielniki

print(faktoryzacja(12))

# W PDB:
# p i           # Wypisz i
# p n           # Wypisz n
# p n % i       # Wypisz resztę z dzielenia
# n             # Następna iteracja</code></pre>



<h3 class="wp-block-heading">Przykład 3: Logging w aplikacji</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import logging

# Konfiguracja
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=&#91;
        logging.FileHandler('app.log'),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance
        logger.info(f"Utworzono konto dla {owner} z saldem {balance}")
    
    def deposit(self, amount):
        if amount &lt;= 0:
            logger.warning(f"Próba wpłaty nieprawidłowej kwoty: {amount}")
            return False
        
        self.balance += amount
        logger.info(f"{self.owner}: Wpłata {amount}, nowe saldo: {self.balance}")
        return True
    
    def withdraw(self, amount):
        if amount > self.balance:
            logger.error(f"{self.owner}: Próba wypłaty {amount}, ale saldo to tylko {self.balance}")
            return False
        
        self.balance -= amount
        logger.info(f"{self.owner}: Wypłata {amount}, nowe saldo: {self.balance}")
        return True

# Użycie
konto = BankAccount("Jan Kowalski", 1000)
konto.deposit(500)
konto.withdraw(2000)  # Błąd - za mało środków
konto.withdraw(200)</code></pre>



<h2 class="wp-block-heading">Najlepsze praktyki debugowania</h2>



<h3 class="wp-block-heading">1. Czytaj dokumentację</h3>



<p class="wp-block-paragraph">Przed debugowaniem sprawdź dokumentację funkcji/biblioteki.</p>



<h3 class="wp-block-heading">2. Pisz testy jednostkowe</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import unittest

def dodaj(a, b):
    return a + b

class TestDodaj(unittest.TestCase):
    def test_dodatnie(self):
        self.assertEqual(dodaj(2, 3), 5)
    
    def test_ujemne(self):
        self.assertEqual(dodaj(-2, -3), -5)
    
    def test_mieszane(self):
        self.assertEqual(dodaj(-2, 3), 1)

if __name__ == '__main__':
    unittest.main()</code></pre>



<p class="wp-block-paragraph">Testy pomagają wykrywać bugi wcześnie.</p>



<h3 class="wp-block-heading">3. Używaj type hints</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def dodaj(a: int, b: int) -> int:
    return a + b

# IDE od razu wykryje błąd
# dodaj("a", "b")  # Typ niezgodny!</code></pre>



<h3 class="wp-block-heading">4. Code review</h3>



<p class="wp-block-paragraph">Poproś kogoś o przejrzenie kodu &#8211; świeże oko często widzi błędy.</p>



<h3 class="wp-block-heading">5. Git bisect &#8211; znajdź kiedy pojawił się bug</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">git bisect start
git bisect bad  # Obecna wersja ma bug
git bisect good abc123  # Commit abc123 nie miał buga
# Git automatycznie znajdzie commit który wprowadził błąd</code></pre>



<h2 class="wp-block-heading">Podsumowanie</h2>



<p class="wp-block-paragraph"><strong>Metody debugowania:</strong></p>



<ol class="wp-block-list">
<li><strong>Print debugging</strong>&nbsp;&#8211; proste, szybkie</li>



<li><strong>Assertions</strong>&nbsp;&#8211; sprawdzanie założeń</li>



<li><strong>Logging</strong>&nbsp;&#8211; profesjonalne logowanie</li>



<li><strong>PDB/breakpoint()</strong>&nbsp;&#8211; interaktywny debugger</li>



<li><strong>IDE debugger</strong>&nbsp;&#8211; najpotężniejsze</li>
</ol>



<p class="wp-block-paragraph"><strong>Techniki:</strong></p>



<ul class="wp-block-list">
<li>Rubber duck debugging</li>



<li>Dziel i zwyciężaj</li>



<li>Binary search</li>



<li>Czytaj traceback od dołu</li>
</ul>



<p class="wp-block-paragraph"><strong>Narzędzia:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">traceback</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">inspect</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">dis</code></li>



<li>Testy jednostkowe</li>



<li>Type hints</li>
</ul>



<p class="wp-block-paragraph"><strong>Dobre praktyki:</strong></p>



<ul class="wp-block-list">
<li>Debuguj systematycznie</li>



<li>Dokumentuj znalezione błędy</li>



<li>Ucz się na błędach</li>



<li>Pisz testy</li>
</ul>



<p class="wp-block-paragraph"><strong>Pamiętaj:</strong>&nbsp;Debugging to umiejętność &#8211; im więcej ćwiczysz, tym lepszy się stajesz!</p>
<p>Artykuł <a href="https://kamakaczmarek.net/22-python-debugging-debugowanie/">22. Python – Debugging (Debugowanie)</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>21. Python – Szablony (wzorce) klas &#8211; Generics</title>
		<link>https://kamakaczmarek.net/21-python-szablony-wzorce-klas-generics/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 11:54:37 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=5089</guid>

					<description><![CDATA[<p>Generics (Typy ogólne)&#160;to mechanizm pozwalający na tworzenie klas, funkcji i struktur danych działających z różnymi typami, zachowując bezpieczeństwo typów. Dlaczego Generics? W Pythonie:&#160;Moduł&#160;typing&#160;(Python 3.5+) Moduł typing Funkcje z typami TypeVar &#8211; zmienne typowe TypeVar&#160;pozwala stworzyć &#8222;placeholder&#8221; dla typu. Generic &#8211; klasa ogólna Para &#8211; generic z dwoma typami Stos (Stack) &#8211; praktyczny przykład Kolejka (Queue) [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/21-python-szablony-wzorce-klas-generics/">21. Python – Szablony (wzorce) klas &#8211; Generics</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Generics (Typy ogólne)</strong>&nbsp;to mechanizm pozwalający na tworzenie klas, funkcji i struktur danych działających z różnymi typami, zachowując bezpieczeństwo typów.</p>



<p class="wp-block-paragraph"><strong>Dlaczego Generics?</strong></p>



<ul class="wp-block-list">
<li>Wielokrotne użycie kodu</li>



<li>Bezpieczeństwo typów</li>



<li>Czytelność kodu</li>



<li>Lepsze wsparcie IDE (autouzupełnianie)</li>
</ul>



<p class="wp-block-paragraph"><strong>W Pythonie:</strong>&nbsp;Moduł&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">typing</code>&nbsp;(Python 3.5+)</p>



<h2 class="wp-block-heading">Moduł typing</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import List, Dict, Tuple, Optional, Union, Any

# Proste typy
imie: str = "Jan"
wiek: int = 25
cena: float = 19.99
aktywny: bool = True

# Kolekcje
liczby: List&#91;int] = &#91;1, 2, 3, 4]
slownik: Dict&#91;str, int] = {"Jan": 25, "Anna": 30}
para: Tuple&#91;str, int] = ("Jan", 25)

# Optional - może być None
imie_opcjonalne: Optional&#91;str] = None  # To samo co: Union&#91;str, None]

# Union - jeden z typów
identyfikator: Union&#91;int, str] = 123  # Może być int lub str

# Any - dowolny typ
cokolwiek: Any = "może być wszystko"
</code></pre>



<h2 class="wp-block-heading">Funkcje z typami</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import List

def suma_liczb(liczby: List&#91;int]) -&gt; int:
    """
    Sumuje listę liczb.
    
    Args:
        liczby: Lista liczb całkowitych
    
    Returns:
        Suma wszystkich liczb
    """
    return sum(liczby)

# Użycie
wynik: int = suma_liczb(&#91;1, 2, 3, 4, 5])
print(wynik)  # 15

# IDE podpowie błąd
# suma_liczb(&#91;"a", "b"])  # Błąd typu!
</code></pre>



<h2 class="wp-block-heading">TypeVar &#8211; zmienne typowe</h2>



<p class="wp-block-paragraph"><code class="prettyprint lang-sql" style="font-size: 0.85em;">TypeVar</code>&nbsp;pozwala stworzyć &#8222;placeholder&#8221; dla typu.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import TypeVar, List

# Stwórz zmienną typową
T = TypeVar('T')

def pierwszy_element(lista: List&#91;T]) -&gt; T:
    """
    Zwraca pierwszy element listy.
    Typ zwracany jest taki sam jak typ elementów.
    """
    return lista&#91;0]

# Użycie
liczby = &#91;1, 2, 3]
wynik1 = pierwszy_element(liczby)  # wynik1: int

teksty = &#91;"a", "b", "c"]
wynik2 = pierwszy_element(teksty)  # wynik2: str
</code></pre>



<h2 class="wp-block-heading">Generic &#8211; klasa ogólna</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import TypeVar, Generic

T = TypeVar('T')

class Pudelko(Generic&#91;T]):
    """
    Generyczna klasa pudełka - może przechowywać dowolny typ.
    """
    def __init__(self, zawartosc: T):
        self.zawartosc = zawartosc
    
    def pobierz(self) -&gt; T:
        return self.zawartosc
    
    def ustaw(self, nowa_zawartosc: T) -&gt; None:
        self.zawartosc = nowa_zawartosc

# Użycie z int
pudelko_int: Pudelko&#91;int] = Pudelko(42)
liczba = pudelko_int.pobierz()  # liczba: int

# Użycie z str
pudelko_str: Pudelko&#91;str] = Pudelko("Hello")
tekst = pudelko_str.pobierz()  # tekst: str

# IDE ostrzeże o błędzie
# pudelko_int.ustaw("tekst")  # Błąd - oczekiwano int!
</code></pre>



<h2 class="wp-block-heading">Para &#8211; generic z dwoma typami</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import TypeVar, Generic

T = TypeVar('T')
U = TypeVar('U')

class Para(Generic&#91;T, U]):
    """Generyczna para dwóch wartości."""
    
    def __init__(self, pierwszy: T, drugi: U):
        self.pierwszy = pierwszy
        self.drugi = drugi
    
    def pobierz_pierwszy(self) -&gt; T:
        return self.pierwszy
    
    def pobierz_drugi(self) -&gt; U:
        return self.drugi
    
    def __str__(self) -&gt; str:
        return f"Para({self.pierwszy}, {self.drugi})"

# Użycie
para1: Para&#91;str, int] = Para("Jan", 25)
print(para1)  # Para(Jan, 25)

para2: Para&#91;int, str] = Para(1, "jeden")
print(para2)  # Para(1, jeden)
</code></pre>



<h2 class="wp-block-heading">Stos (Stack) &#8211; praktyczny przykład</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import TypeVar, Generic, List, Optional

T = TypeVar('T')

class Stos(Generic&#91;T]):
    """
    Generyczny stos (LIFO - Last In First Out).
    """
    def __init__(self):
        self._elementy: List&#91;T] = &#91;]
    
    def push(self, element: T) -&gt; None:
        """Dodaj element na szczyt stosu."""
        self._elementy.append(element)
    
    def pop(self) -&gt; Optional&#91;T]:
        """Usuń i zwróć element ze szczytu."""
        if self.jest_pusty():
            return None
        return self._elementy.pop()
    
    def peek(self) -&gt; Optional&#91;T]:
        """Sprawdź szczyt bez usuwania."""
        if self.jest_pusty():
            return None
        return self._elementy&#91;-1]
    
    def jest_pusty(self) -&gt; bool:
        """Czy stos jest pusty?"""
        return len(self._elementy) == 0
    
    def rozmiar(self) -&gt; int:
        """Liczba elementów."""
        return len(self._elementy)
    
    def __str__(self) -&gt; str:
        return f"Stos({self._elementy})"

# Użycie
stos_int: Stos&#91;int] = Stos()
stos_int.push(1)
stos_int.push(2)
stos_int.push(3)
print(stos_int)  # Stos(&#91;1, 2, 3])
print(stos_int.pop())  # 3

stos_str: Stos&#91;str] = Stos()
stos_str.push("Python")
stos_str.push("Java")
print(stos_str)  # Stos(&#91;'Python', 'Java'])
</code></pre>



<h2 class="wp-block-heading">Kolejka (Queue) &#8211; przykład</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import TypeVar, Generic, List, Optional

T = TypeVar('T')

class Kolejka(Generic&#91;T]):
    """
    Generyczna kolejka (FIFO - First In First Out).
    """
    def __init__(self):
        self._elementy: List&#91;T] = &#91;]
    
    def enqueue(self, element: T) -&gt; None:
        """Dodaj element na koniec kolejki."""
        self._elementy.append(element)
    
    def dequeue(self) -&gt; Optional&#91;T]:
        """Usuń i zwróć element z początku."""
        if self.jest_pusta():
            return None
        return self._elementy.pop(0)
    
    def jest_pusta(self) -&gt; bool:
        return len(self._elementy) == 0
    
    def rozmiar(self) -&gt; int:
        return len(self._elementy)
    
    def __str__(self) -&gt; str:
        return f"Kolejka({self._elementy})"

# Użycie
kolejka: Kolejka&#91;str] = Kolejka()
kolejka.enqueue("Pierwszy")
kolejka.enqueue("Drugi")
kolejka.enqueue("Trzeci")
print(kolejka)  # Kolejka(&#91;'Pierwszy', 'Drugi', 'Trzeci'])
print(kolejka.dequeue())  # Pierwszy
</code></pre>



<h2 class="wp-block-heading">Linked List &#8211; lista powiązana</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import TypeVar, Generic, Optional

T = TypeVar('T')

class Wezel(Generic&#91;T]):
    """Węzeł listy powiązanej."""
    def __init__(self, dane: T):
        self.dane = dane
        self.nastepny: Optional&#91;Wezel&#91;T]] = None

class ListaPowiazana(Generic&#91;T]):
    """Generyczna lista powiązana."""
    
    def __init__(self):
        self.glowa: Optional&#91;Wezel&#91;T]] = None
    
    def dodaj_na_poczatek(self, dane: T) -&gt; None:
        """Dodaj element na początek."""
        nowy = Wezel(dane)
        nowy.nastepny = self.glowa
        self.glowa = nowy
    
    def dodaj_na_koniec(self, dane: T) -&gt; None:
        """Dodaj element na koniec."""
        nowy = Wezel(dane)
        
        if self.glowa is None:
            self.glowa = nowy
            return
        
        aktualny = self.glowa
        while aktualny.nastepny is not None:
            aktualny = aktualny.nastepny
        aktualny.nastepny = nowy
    
    def wyswietl(self) -&gt; None:
        """Wyświetl wszystkie elementy."""
        aktualny = self.glowa
        elementy = &#91;]
        while aktualny is not None:
            elementy.append(str(aktualny.dane))
            aktualny = aktualny.nastepny
        print(" -&gt; ".join(elementy))

# Użycie
lista: ListaPowiazana&#91;int] = ListaPowiazana()
lista.dodaj_na_koniec(1)
lista.dodaj_na_koniec(2)
lista.dodaj_na_koniec(3)
lista.wyswietl()  # 1 -&gt; 2 -&gt; 3
</code></pre>



<h2 class="wp-block-heading">Ograniczenia typów (Bounded TypeVar)</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import TypeVar

# Ograniczenie do typów numerycznych
Liczba = TypeVar('Liczba', int, float)

def suma(a: Liczba, b: Liczba) -&gt; Liczba:
    """Sumuje dwie liczby (int lub float)."""
    return a + b

print(suma(5, 3))      # 8 (int)
print(suma(5.5, 3.2))  # 8.7 (float)
# suma("a", "b")  # Błąd - string nie jest dozwolony!
</code></pre>



<h2 class="wp-block-heading">Protocol &#8211; duck typing z typami</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import Protocol

class Drawable(Protocol):
    """Protokół dla obiektów które można narysować."""
    def draw(self) -&gt; str:
        ...

class Circle:
    def draw(self) -&gt; str:
        return "Rysujęokrąg"

class Square:
    def draw(self) -&gt; str:
        return "Rysuję kwadrat"

def render(shape: Drawable) -&gt; None:
    """Rysuje kształt."""
    print(shape.draw())

# Użycie - Circle i Square automatycznie spełniają Protocol
circle = Circle()
square = Square()

render(circle)  # Rysuję okrąg
render(square)  # Rysuję kwadrat
</code></pre>



<h2 class="wp-block-heading">Callable &#8211; typ funkcji</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import Callable

def wykonaj_operacje(a: int, b: int, operacja: Callable&#91;&#91;int, int], int]) -&gt; int:
    """
    Wykonuje operację na dwóch liczbach.
    
    operacja: funkcja przyjmująca dwa int i zwracająca int
    """
    return operacja(a, b)

def dodaj(x: int, y: int) -&gt; int:
    return x + y

def pomnoz(x: int, y: int) -&gt; int:
    return x * y

print(wykonaj_operacje(5, 3, dodaj))    # 8
print(wykonaj_operacje(5, 3, pomnoz))   # 15
</code></pre>



<h2 class="wp-block-heading">Praktyczny przykład &#8211; Repository</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from typing import TypeVar, Generic, List, Optional, Dict

T = TypeVar('T')

class Repository(Generic&#91;T]):
    """
    Generyczne repozytorium do przechowywania obiektów.
    """
    def __init__(self):
        self._dane: Dict&#91;int, T] = {}
        self._next_id: int = 1
    
    def dodaj(self, obiekt: T) -&gt; int:
        """Dodaje obiekt i zwraca jego ID."""
        id_obiektu = self._next_id
        self._dane&#91;id_obiektu] = obiekt
        self._next_id += 1
        return id_obiektu
    
    def pobierz(self, id_obiektu: int) -&gt; Optional&#91;T]:
        """Pobiera obiekt po ID."""
        return self._dane.get(id_obiektu)
    
    def wszystkie(self) -&gt; List&#91;T]:
        """Zwraca wszystkie obiekty."""
        return list(self._dane.values())
    
    def usun(self, id_obiektu: int) -&gt; bool:
        """Usuwa obiekt po ID."""
        if id_obiektu in self._dane:
            del self._dane&#91;id_obiektu]
            return True
        return False

# Użycie z różnymi typami
class Uzytkownik:
    def __init__(self, imie: str):
        self.imie = imie
    
    def __str__(self):
        return f"Uzytkownik({self.imie})"

repo_uzytkownikow: Repository&#91;Uzytkownik] = Repository()
id1 = repo_uzytkownikow.dodaj(Uzytkownik("Jan"))
id2 = repo_uzytkownikow.dodaj(Uzytkownik("Anna"))

print(repo_uzytkownikow.pobierz(id1))  # Uzytkownik(Jan)
print(repo_uzytkownikow.wszystkie())   # &#91;Uzytkownik(Jan), Uzytkownik(Anna)]
</code></pre>



<h2 class="wp-block-heading">Podsumowanie</h2>



<p class="wp-block-paragraph"><strong>Typing:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">List[T]</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">Dict[K, V]</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">Tuple[T, ...]</code></li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">Optional[T]</code> = <code class="prettyprint lang-sql" style="font-size: 0.85em;">Union[T, None]</code></li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">Union[T, U]</code> &#8211; jeden z typów</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">Any</code> &#8211; dowolny typ</li>
</ul>



<p class="wp-block-paragraph"><strong>Generics:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">TypeVar('T')</code> &#8211; zmienna typowa</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">Generic[T]</code> &#8211; klasa ogólna</li>



<li>Wielokrotne użycie kodu</li>



<li>Bezpieczeństwo typów</li>
</ul>



<p class="wp-block-paragraph"><strong>Przykłady:</strong></p>



<ul class="wp-block-list">
<li>Pudełko, Para</li>



<li>Stos, Kolejka</li>



<li>Lista powiązana</li>



<li>Repository</li>
</ul>



<p class="wp-block-paragraph"><strong>Korzyści:</strong></p>



<ul class="wp-block-list">
<li>IDE podpowiada typy</li>



<li>Wykrywanie błędów przed uruchomieniem</li>



<li>Lepszaczytelność kodu</li>



<li>Dokumentacja w kodzie</li>
</ul>
<p>Artykuł <a href="https://kamakaczmarek.net/21-python-szablony-wzorce-klas-generics/">21. Python – Szablony (wzorce) klas &#8211; Generics</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>20. Python – Algorytmy: Sortowanie i Przeszukiwanie</title>
		<link>https://kamakaczmarek.net/20-python-algorytmy-sortowanie-i-przeszukiwanie/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 11:38:29 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=5086</guid>

					<description><![CDATA[<p>Algorytm&#160;to precyzyjny zestaw kroków prowadzących do rozwiązania problemu. Dlaczego algorytmy? W tej lekcji: Złożoność obliczeniowa (Big O Notation) Złożoność obliczeniowa&#160;mierzy jak szybko rośnie czas wykonania algorytmu wraz ze wzrostem rozmiaru danych. Notacja Big O O(n)&#160;&#8211; &#8222;Big O of n&#8221; &#8211; opisuje&#160;najgorszy przypadek. Najczęstsze złożoności&#160;(od najlepszej do najgorszej): Notacja Nazwa Przykład Opis O(1) Stała Dostęp do [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/20-python-algorytmy-sortowanie-i-przeszukiwanie/">20. Python – Algorytmy: Sortowanie i Przeszukiwanie</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Algorytm</strong>&nbsp;to precyzyjny zestaw kroków prowadzących do rozwiązania problemu.</p>



<p class="wp-block-paragraph"><strong>Dlaczego algorytmy?</strong></p>



<ul class="wp-block-list">
<li>Efektywność &#8211; szybsze przetwarzanie danych</li>



<li>Optymalizacja &#8211; mniej zasobów (pamięć, czas)</li>



<li>Zrozumienie podstaw informatyki</li>



<li>Rozmowy kwalifikacyjne</li>
</ul>



<p class="wp-block-paragraph"><strong>W tej lekcji:</strong></p>



<ul class="wp-block-list">
<li>Algorytmy sortowania</li>



<li>Algorytmy przeszukiwania</li>



<li>Złożoność obliczeniowa (Big O)</li>
</ul>



<h2 class="wp-block-heading">Złożoność obliczeniowa (Big O Notation)</h2>



<p class="wp-block-paragraph"><strong>Złożoność obliczeniowa</strong>&nbsp;mierzy jak szybko rośnie czas wykonania algorytmu wraz ze wzrostem rozmiaru danych.</p>



<h3 class="wp-block-heading">Notacja Big O</h3>



<p class="wp-block-paragraph"><strong>O(n)</strong>&nbsp;&#8211; &#8222;Big O of n&#8221; &#8211; opisuje&nbsp;<strong>najgorszy przypadek</strong>.</p>



<p class="wp-block-paragraph"><strong>Najczęstsze złożoności</strong>&nbsp;(od najlepszej do najgorszej):</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Notacja</th><th>Nazwa</th><th>Przykład</th><th>Opis</th></tr></thead><tbody><tr><td><strong>O(1)</strong></td><td>Stała</td><td>Dostęp do elementu tablicy</td><td>Niezależnie od rozmiaru</td></tr><tr><td><strong>O(log n)</strong></td><td>Logarytmiczna</td><td>Przeszukiwanie binarne</td><td>Bardzo szybkie</td></tr><tr><td><strong>O(n)</strong></td><td>Liniowa</td><td>Przeszukiwanie liniowe</td><td>Wprost proporcjonalne</td></tr><tr><td><strong>O(n log n)</strong></td><td>Liniowo-logarytmiczna</td><td>Merge sort, Quick sort</td><td>Dobre sortowanie</td></tr><tr><td><strong>O(n²)</strong></td><td>Kwadratowa</td><td>Bubble sort, Selection sort</td><td>Wolne dla dużych danych</td></tr><tr><td><strong>O(2^n)</strong></td><td>Wykładnicza</td><td>Niektóre rekurencje</td><td>Bardzo wolne</td></tr><tr><td><strong>O(n!)</strong></td><td>Silnia</td><td>Permutacje</td><td>Ekstremalnie wolne</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Wizualizacja wzrostu</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">n = 10:
O(1)      = 1
O(log n)  = 3
O(n)      = 10
O(n log n)= 30
O(n²)     = 100
O(2^n)    = 1024

n = 1000:
O(1)      = 1
O(log n)  = 10
O(n)      = 1000
O(n log n)= 10000
O(n²)     = 1000000
O(2^n)    = ???  (za dużo!)</code></pre>



<h3 class="wp-block-heading">Przykłady złożoności</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># O(1) - Stała
def get_first(lista):
    return lista&#91;0]  # Zawsze 1 operacja

# O(n) - Liniowa
def contains(lista, element):
    for item in lista:  # n operacji
        if item == element:
            return True
    return False

# O(n²) - Kwadratowa
def print_pairs(lista):
    for i in lista:       # n razy
        for j in lista:   # n razy
            print(i, j)   # n * n = n²</code></pre>



<h2 class="wp-block-heading">Algorytmy sortowania</h2>



<p class="wp-block-paragraph"><strong>Sortowanie</strong>&nbsp;to uporządkowanie elementów według określonego kryterium.</p>



<h2 class="wp-block-heading">1. Bubble Sort (Sortowanie bąbelkowe)</h2>



<p class="wp-block-paragraph"><strong>Idea:</strong>&nbsp;Porównuj sąsiednie elementy i zamieniaj je miejscami jeśli są w złej kolejności. Powtarzaj aż lista będzie posortowana.</p>



<p class="wp-block-paragraph"><strong>Złożoność:</strong></p>



<ul class="wp-block-list">
<li><strong>Czasowa:</strong> O(n²) &#8211; najgorszy i średni przypadek</li>



<li><strong>Czasowa:</strong> O(n) &#8211; najlepszy przypadek (lista już posortowana)</li>



<li><strong>Pamięciowa:</strong> O(1) &#8211; sortowanie in-place</li>
</ul>



<p class="wp-block-paragraph"><strong>Kiedy używać:</strong></p>



<ul class="wp-block-list">
<li>Małe zbiory danych</li>



<li>Dane prawie posortowane</li>



<li>Cel edukacyjny</li>
</ul>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def bubble_sort(lista):
    """
    Sortowanie bąbelkowe.
    Porównuje sąsiednie elementy i zamienia je miejscami.
    """
    n = len(lista)
    
    # Zewnętrzna pętla - liczba przejść
    for i in range(n):
        # Flaga - czy było zamiana
        zamiana = False
        
        # Wewnętrzna pętla - porównania
        for j in range(0, n - i - 1):
            # Jeśli element jest większy od następnego
            if lista&#91;j] > lista&#91;j + 1]:
                # Zamień miejscami
                lista&#91;j], lista&#91;j + 1] = lista&#91;j + 1], lista&#91;j]
                zamiana = True
        
        # Jeśli nie było zamiany, lista jest posortowana
        if not zamiana:
            break
    
    return lista

# Test
dane = &#91;64, 34, 25, 12, 22, 11, 90]
print("Przed:", dane)
bubble_sort(dane)
print("Po:", dane)
# Po: &#91;11, 12, 22, 25, 34, 64, 90]</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="890" height="935" src="https://kamakaczmarek.net/wp-content/uploads/bubble_sort.png" alt="" class="wp-image-5102" srcset="https://kamakaczmarek.net/wp-content/uploads/bubble_sort.png 890w, https://kamakaczmarek.net/wp-content/uploads/bubble_sort-286x300.png 286w, https://kamakaczmarek.net/wp-content/uploads/bubble_sort-768x807.png 768w" sizes="(max-width: 890px) 100vw, 890px" /></figure>
</div>



<p class="wp-block-paragraph"><strong>Wizualizacja (pierwsze przejście):</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">&#91;64, 34, 25, 12, 22, 11, 90]
 64>34 → zamień
&#91;34, 64, 25, 12, 22, 11, 90]
    64>25 → zamień
&#91;34, 25, 64, 12, 22, 11, 90]
       64>12 → zamień
&#91;34, 25, 12, 64, 22, 11, 90]
          64>22 → zamień
&#91;34, 25, 12, 22, 64, 11, 90]
             64>11 → zamień
&#91;34, 25, 12, 22, 11, 64, 90]
                64&lt;90 → OK</code></pre>



<h2 class="wp-block-heading">2. Selection Sort (Sortowanie przez wybieranie)</h2>



<p class="wp-block-paragraph"><strong>Idea:</strong>&nbsp;Znajdź najmniejszy element i umieść go na początku. Powtarzaj dla pozostałej części.</p>



<p class="wp-block-paragraph"><strong>Złożoność:</strong></p>



<ul class="wp-block-list">
<li><strong>Czasowa:</strong> O(n²) &#8211; zawsze</li>



<li><strong>Pamięciowa:</strong> O(1)</li>
</ul>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def selection_sort(lista):
    """
    Sortowanie przez wybieranie.
    Znajduje minimum i umieszcza na początku.
    """
    n = len(lista)
    
    # Przejdź przez wszystkie elementy
    for i in range(n):
        # Znajdź indeks najmniejszego elementu
        min_idx = i
        for j in range(i + 1, n):
            if lista&#91;j] &lt; lista&#91;min_idx]:
                min_idx = j
        
        # Zamień znaleziony minimum z pierwszym elementem
        lista&#91;i], lista&#91;min_idx] = lista&#91;min_idx], lista&#91;i]
    
    return lista

# Test
dane = &#91;64, 25, 12, 22, 11]
print("Przed:", dane)
selection_sort(dane)
print("Po:", dane)
# Po: &#91;11, 12, 22, 25, 64]</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="869" height="913" src="https://kamakaczmarek.net/wp-content/uploads/selection_sort.png" alt="" class="wp-image-5107" srcset="https://kamakaczmarek.net/wp-content/uploads/selection_sort.png 869w, https://kamakaczmarek.net/wp-content/uploads/selection_sort-286x300.png 286w, https://kamakaczmarek.net/wp-content/uploads/selection_sort-768x807.png 768w" sizes="(max-width: 869px) 100vw, 869px" /></figure>
</div>



<p class="wp-block-paragraph"><strong>Wizualizacja:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">&#91;64, 25, 12, 22, 11]
 ^               ^  min=11, zamień
&#91;11, 25, 12, 22, 64]
     ^   ^          min=12, zamień
&#91;11, 12, 25, 22, 64]
         ^   ^      min=22, zamień
&#91;11, 12, 22, 25, 64]
             ^  ^   min=25, już OK
&#91;11, 12, 22, 25, 64] ✓</code></pre>



<h2 class="wp-block-heading">3. Insertion Sort (Sortowanie przez wstawianie)</h2>



<p class="wp-block-paragraph"><strong>Idea:</strong>&nbsp;Bierz kolejne elementy i wstawiaj je we właściwe miejsce w już posortowanej części.</p>



<p class="wp-block-paragraph"><strong>Złożoność:</strong></p>



<ul class="wp-block-list">
<li><strong>Czasowa:</strong> O(n²) &#8211; najgorszy przypadek</li>



<li><strong>Czasowa:</strong> O(n) &#8211; najlepszy przypadek (lista posortowana)</li>



<li><strong>Pamięciowa:</strong> O(1)</li>
</ul>



<p class="wp-block-paragraph"><strong>Kiedy używać:</strong></p>



<ul class="wp-block-list">
<li>Małe zbiory danych</li>



<li>Dane prawie posortowane</li>



<li>Sortowanie online (elementy przychodzą po kolei)</li>
</ul>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def insertion_sort(lista):
    """
    Sortowanie przez wstawianie.
    Jak sortowanie kart w ręce.
    """
    n = len(lista)
    
    # Zacznij od drugiego elementu
    for i in range(1, n):
        # Element do wstawienia
        key = lista&#91;i]
        j = i - 1
        
        # Przesuń elementy większe od key o jedno miejsce w prawo
        while j >= 0 and lista&#91;j] > key:
            lista&#91;j + 1] = lista&#91;j]
            j -= 1
        
        # Wstaw key na właściwe miejsce
        lista&#91;j + 1] = key
    
    return lista

# Test
dane = &#91;12, 11, 13, 5, 6]
print("Przed:", dane)
insertion_sort(dane)
print("Po:", dane)
# Po: &#91;5, 6, 11, 12, 13]</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="367" height="856" src="https://kamakaczmarek.net/wp-content/uploads/insertion_sort.png" alt="" class="wp-image-5103" srcset="https://kamakaczmarek.net/wp-content/uploads/insertion_sort.png 367w, https://kamakaczmarek.net/wp-content/uploads/insertion_sort-129x300.png 129w" sizes="(max-width: 367px) 100vw, 367px" /></figure>
</div>



<p class="wp-block-paragraph"><strong>Analogia:</strong>&nbsp;Jak sortowanie kart w ręce &#8211; bierzesz kolejną kartę i wstawiasz ją we właściwe miejsce.</p>



<h2 class="wp-block-heading">4. Merge Sort (Sortowanie przez scalanie)</h2>



<p class="wp-block-paragraph"><strong>Idea:</strong>&nbsp;Dziel listę na połowy, sortuj rekurencyjnie, następnie scalaj posortowane połowy.</p>



<p class="wp-block-paragraph"><strong>Złożoność:</strong></p>



<ul class="wp-block-list">
<li><strong>Czasowa:</strong> O(n log n) &#8211; zawsze!</li>



<li><strong>Pamięciowa:</strong> O(n) &#8211; wymaga dodatkowej pamięci</li>
</ul>



<p class="wp-block-paragraph"><strong>Kiedy używać:</strong></p>



<ul class="wp-block-list">
<li>Duże zbiory danych</li>



<li>Stabilne sortowanie (zachowuje kolejność równych elementów)</li>



<li>Gwarantowana wydajność O(n log n)</li>
</ul>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def merge_sort(lista):
    """
    Sortowanie przez scalanie (rekurencyjne).
    Dziel i zwyciężaj.
    """
    # Warunek bazowy - lista o długości 1 jest posortowana
    if len(lista) &lt;= 1:
        return lista
    
    # Podziel na dwie połowy
    srodek = len(lista) // 2
    lewa = lista&#91;:srodek]
    prawa = lista&#91;srodek:]
    
    # Rekurencyjnie posortuj połowy
    lewa = merge_sort(lewa)
    prawa = merge_sort(prawa)
    
    # Scal posortowane połowy
    return merge(lewa, prawa)

def merge(lewa, prawa):
    """Scala dwie posortowane listy."""
    wynik = &#91;]
    i = j = 0
    
    # Porównuj elementy z obu list
    while i &lt; len(lewa) and j &lt; len(prawa):
        if lewa&#91;i] &lt;= prawa&#91;j]:
            wynik.append(lewa&#91;i])
            i += 1
        else:
            wynik.append(prawa&#91;j])
            j += 1
    
    # Dodaj pozostałe elementy
    wynik.extend(lewa&#91;i:])
    wynik.extend(prawa&#91;j:])
    
    return wynik

# Test
dane = &#91;38, 27, 43, 3, 9, 82, 10]
print("Przed:", dane)
posortowane = merge_sort(dane)
print("Po:", posortowane)
# Po: &#91;3, 9, 10, 27, 38, 43, 82]</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="367" height="1002" src="https://kamakaczmarek.net/wp-content/uploads/merge_sort.png" alt="" class="wp-image-5105" srcset="https://kamakaczmarek.net/wp-content/uploads/merge_sort.png 367w, https://kamakaczmarek.net/wp-content/uploads/merge_sort-110x300.png 110w" sizes="(max-width: 367px) 100vw, 367px" /></figure>
</div>



<p class="wp-block-paragraph"><strong>Wizualizacja:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">&#91;38, 27, 43, 3, 9, 82, 10]
       ↓ dziel ↓
&#91;38, 27, 43]  &#91;3, 9, 82, 10]
  ↓ dziel ↓    ↓ dziel ↓
&#91;38] &#91;27, 43]  &#91;3, 9] &#91;82, 10]
       ↓          ↓       ↓
    &#91;27, 43]    &#91;3, 9]  &#91;10, 82]
        ↓ scal ↓          ↓
    &#91;27, 38, 43]    &#91;3, 9, 10, 82]
           ↓ scal ↓
    &#91;3, 9, 10, 27, 38, 43, 82]</code></pre>



<h2 class="wp-block-heading">5. Quick Sort (Sortowanie szybkie)</h2>



<p class="wp-block-paragraph"><strong>Idea:</strong>&nbsp;Wybierz element (pivot), podziel na mniejsze i większe, sortuj rekurencyjnie.</p>



<p class="wp-block-paragraph"><strong>Złożoność:</strong></p>



<ul class="wp-block-list">
<li><strong>Czasowa:</strong> O(n log n) &#8211; średni przypadek</li>



<li><strong>Czasowa:</strong> O(n²) &#8211; najgorszy (rzadko)</li>



<li><strong>Pamięciowa:</strong> O(log n) &#8211; rekursja</li>
</ul>



<p class="wp-block-paragraph"><strong>Kiedy używać:</strong></p>



<ul class="wp-block-list">
<li>Duże zbiory danych</li>



<li>Najszybszy w praktyce</li>



<li>Sortowanie in-place</li>
</ul>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def quick_sort(lista):
    """
    Sortowanie szybkie.
    Wybiera pivot i dzieli na mniejsze/większe.
    """
    # Warunek bazowy
    if len(lista) &lt;= 1:
        return lista
    
    # Wybierz pivot (środkowy element)
    pivot = lista&#91;len(lista) // 2]
    
    # Podziel na trzy grupy
    mniejsze = &#91;x for x in lista if x &lt; pivot]
    rowne = &#91;x for x in lista if x == pivot]
    wieksze = &#91;x for x in lista if x > pivot]
    
    # Rekurencyjnie posortuj i połącz
    return quick_sort(mniejsze) + rowne + quick_sort(wieksze)

# Test
dane = &#91;10, 7, 8, 9, 1, 5]
print("Przed:", dane)
posortowane = quick_sort(dane)
print("Po:", posortowane)
# Po: &#91;1, 5, 7, 8, 9, 10]</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="377" height="1009" src="https://kamakaczmarek.net/wp-content/uploads/quick_sort.png" alt="" class="wp-image-5106" srcset="https://kamakaczmarek.net/wp-content/uploads/quick_sort.png 377w, https://kamakaczmarek.net/wp-content/uploads/quick_sort-112x300.png 112w" sizes="(max-width: 377px) 100vw, 377px" /></figure>
</div>



<p class="wp-block-paragraph"><strong>Wizualizacja:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">&#91;10, 7, 8, 9, 1, 5]  pivot=8
      ↓
mniejsze: &#91;7, 1, 5]
rowne: &#91;8]
wieksze: &#91;10, 9]
      ↓ sortuj rekurencyjnie
&#91;1, 5, 7] + &#91;8] + &#91;9, 10]
      ↓
&#91;1, 5, 7, 8, 9, 10]</code></pre>



<h2 class="wp-block-heading">Porównanie algorytmów sortowania</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Algorytm</th><th>Najlepszy</th><th>Średni</th><th>Najgorszy</th><th>Pamięć</th><th>Stabilny</th></tr></thead><tbody><tr><td><strong>Bubble Sort</strong></td><td>O(n)</td><td>O(n²)</td><td>O(n²)</td><td>O(1)</td><td>Tak</td></tr><tr><td><strong>Selection Sort</strong></td><td>O(n²)</td><td>O(n²)</td><td>O(n²)</td><td>O(1)</td><td>Nie</td></tr><tr><td><strong>Insertion Sort</strong></td><td>O(n)</td><td>O(n²)</td><td>O(n²)</td><td>O(1)</td><td>Tak</td></tr><tr><td><strong>Merge Sort</strong></td><td>O(n log n)</td><td>O(n log n)</td><td>O(n log n)</td><td>O(n)</td><td>Tak</td></tr><tr><td><strong>Quick Sort</strong></td><td>O(n log n)</td><td>O(n log n)</td><td>O(n²)</td><td>O(log n)</td><td>Nie</td></tr><tr><td><strong>Wbudowany sort()</strong></td><td>O(n log n)</td><td>O(n log n)</td><td>O(n log n)</td><td>O(n)</td><td>Tak</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Stabilny</strong>&nbsp;= zachowuje względną kolejność równych elementów.</p>



<h2 class="wp-block-heading">Algorytmy przeszukiwania</h2>



<h2 class="wp-block-heading">1. Przeszukiwanie liniowe (Linear Search)</h2>



<p class="wp-block-paragraph"><strong>Idea:</strong>&nbsp;Sprawdź każdy element po kolei.</p>



<p class="wp-block-paragraph"><strong>Złożoność:</strong></p>



<ul class="wp-block-list">
<li><strong>Czasowa:</strong> O(n)</li>



<li><strong>Pamięciowa:</strong> O(1)</li>
</ul>



<p class="wp-block-paragraph"><strong>Kiedy używać:</strong></p>



<ul class="wp-block-list">
<li>Mała lista</li>



<li>Lista nieposortowana</li>



<li>Jednorazowe wyszukiwanie</li>
</ul>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def linear_search(lista, szukany):
    """
    Przeszukiwanie liniowe.
    Sprawdza każdy element po kolei.
    """
    for i in range(len(lista)):
        if lista&#91;i] == szukany:
            return i  # Zwróć indeks
    return -1  # Nie znaleziono

# Test
dane = &#91;10, 23, 45, 70, 11, 15]
wynik = linear_search(dane, 70)
print(f"Element 70 znajduje się na indeksie: {wynik}")  # 3

wynik = linear_search(dane, 100)
print(f"Element 100 znajduje się na indeksie: {wynik}")  # -1</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="418" height="619" src="https://kamakaczmarek.net/wp-content/uploads/linear_search.png" alt="" class="wp-image-5104" srcset="https://kamakaczmarek.net/wp-content/uploads/linear_search.png 418w, https://kamakaczmarek.net/wp-content/uploads/linear_search-203x300.png 203w" sizes="(max-width: 418px) 100vw, 418px" /></figure>
</div>



<h2 class="wp-block-heading">2. Przeszukiwanie binarne (Binary Search)</h2>



<p class="wp-block-paragraph"><strong>Idea:</strong>&nbsp;W&nbsp;<strong>posortowanej</strong>&nbsp;liście sprawdź środek. Jeśli szukany jest mniejszy, szukaj w lewej połowie, jeśli większy &#8211; w prawej.</p>



<p class="wp-block-paragraph"><strong>Złożoność:</strong></p>



<ul class="wp-block-list">
<li><strong>Czasowa:</strong> O(log n)</li>



<li><strong>Pamięciowa:</strong> O(1) &#8211; iteracyjna, O(log n) &#8211; rekurencyjna</li>
</ul>



<p class="wp-block-paragraph"><strong>Wymaganie:</strong>&nbsp;Lista&nbsp;<strong>MUSI</strong>&nbsp;być posortowana!</p>



<p class="wp-block-paragraph"><strong>Kiedy używać:</strong></p>



<ul class="wp-block-list">
<li>Duża, posortowana lista</li>



<li>Wielokrotne wyszukiwania</li>
</ul>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def binary_search(lista, szukany):
    """
    Przeszukiwanie binarne (iteracyjne).
    Wymaga posortowanej listy!
    """
    lewy = 0
    prawy = len(lista) - 1
    
    while lewy &lt;= prawy:
        # Znajdź środek
        srodek = (lewy + prawy) // 2
        
        # Sprawdź środkowy element
        if lista&#91;srodek] == szukany:
            return srodek
        elif lista&#91;srodek] &lt; szukany:
            # Szukaj w prawej połowie
            lewy = srodek + 1
        else:
            # Szukaj w lewej połowie
            prawy = srodek - 1
    
    return -1  # Nie znaleziono

# Test
dane = &#91;11, 15, 23, 45, 70]  # MUSI BYĆ POSORTOWANA!
wynik = binary_search(dane, 45)
print(f"Element 45 znajduje się na indeksie: {wynik}")  # 3</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="770" height="765" src="https://kamakaczmarek.net/wp-content/uploads/binary_search.png" alt="" class="wp-image-5101" srcset="https://kamakaczmarek.net/wp-content/uploads/binary_search.png 770w, https://kamakaczmarek.net/wp-content/uploads/binary_search-300x298.png 300w, https://kamakaczmarek.net/wp-content/uploads/binary_search-150x150.png 150w, https://kamakaczmarek.net/wp-content/uploads/binary_search-768x763.png 768w" sizes="(max-width: 770px) 100vw, 770px" /></figure>
</div>



<p class="wp-block-paragraph"><strong>Wizualizacja:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">Szukamy: 45
&#91;11, 15, 23, 45, 70]
 L       M       P    środek=23, 45&gt;23 → szukaj w prawo

         &#91;45, 70]
          L   P       środek=45, znaleziono! ✓
</code></pre>



<h3 class="wp-block-heading">Przeszukiwanie binarne &#8211; rekurencyjne</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def binary_search_recursive(lista, szukany, lewy=0, prawy=None):
    """Przeszukiwanie binarne (rekurencyjne)."""
    if prawy is None:
        prawy = len(lista) - 1
    
    # Warunek bazowy
    if lewy > prawy:
        return -1
    
    # Znajdź środek
    srodek = (lewy + prawy) // 2
    
    if lista&#91;srodek] == szukany:
        return srodek
    elif lista&#91;srodek] &lt; szukany:
        return binary_search_recursive(lista, szukany, srodek + 1, prawy)
    else:
        return binary_search_recursive(lista, szukany, lewy, srodek - 1)

# Test
dane = &#91;11, 15, 23, 45, 70]
wynik = binary_search_recursive(dane, 70)
print(f"Element 70 znajduje się na indeksie: {wynik}")  # 4</code></pre>



<h2 class="wp-block-heading">Porównanie przeszukiwania</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Algorytm</th><th>Złożoność</th><th>Wymagania</th><th>Najlepsze dla</th></tr></thead><tbody><tr><td><strong>Linear Search</strong></td><td>O(n)</td><td>Brak</td><td>Małe lub nieposortowane listy</td></tr><tr><td><strong>Binary Search</strong></td><td>O(log n)</td><td>Lista posortowana</td><td>Duże, posortowane listy</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Przykład:</strong>&nbsp;Dla n=1,000,000</p>



<ul class="wp-block-list">
<li>Linear: max 1,000,000 porównań</li>



<li>Binary: max ~20 porównań!</li>
</ul>



<h2 class="wp-block-heading">Praktyczne przykłady</h2>



<h3 class="wp-block-heading">Przykład 1: Benchmark sortowania</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import time
import random

def benchmark_sort(funkcja_sort, dane, nazwa):
    """Mierzy czas sortowania."""
    kopia = dane.copy()
    start = time.time()
    funkcja_sort(kopia)
    koniec = time.time()
    print(f"{nazwa}: {koniec - start:.4f}s")

# Wygeneruj dane
dane = &#91;random.randint(1, 1000) for _ in range(5000)]

print("Benchmark sortowania (5000 elementów):")
benchmark_sort(bubble_sort, dane, "Bubble Sort")
benchmark_sort(selection_sort, dane, "Selection Sort")
benchmark_sort(insertion_sort, dane, "Insertion Sort")
benchmark_sort(merge_sort, dane, "Merge Sort")
benchmark_sort(quick_sort, dane, "Quick Sort")
benchmark_sort(sorted, dane, "Python sorted()")</code></pre>



<h3 class="wp-block-heading">Przykład 2: Wyszukiwanie w bazie danych</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class BazaDanych:
    def __init__(self):
        self.dane = &#91;]
    
    def dodaj(self, rekord):
        self.dane.append(rekord)
        # Sortuj po dodaniu (dla binary search)
        self.dane.sort(key=lambda x: x&#91;'id'])
    
    def znajdz_linear(self, id):
        """Wyszukiwanie liniowe."""
        for rekord in self.dane:
            if rekord&#91;'id'] == id:
                return rekord
        return None
    
    def znajdz_binary(self, id):
        """Wyszukiwanie binarne."""
        lewy, prawy = 0, len(self.dane) - 1
        
        while lewy &lt;= prawy:
            srodek = (lewy + prawy) // 2
            if self.dane&#91;srodek]&#91;'id'] == id:
                return self.dane&#91;srodek]
            elif self.dane&#91;srodek]&#91;'id'] &lt; id:
                lewy = srodek + 1
            else:
                prawy = srodek - 1
        
        return None

# Test
db = BazaDanych()
db.dodaj({'id': 1, 'imie': 'Jan'})
db.dodaj({'id': 5, 'imie': 'Anna'})
db.dodaj({'id': 3, 'imie': 'Piotr'})

print(db.znajdz_binary(5))  # {'id': 5, 'imie': 'Anna'}</code></pre>



<h2 class="wp-block-heading">Wbudowane funkcje Pythona</h2>



<p class="wp-block-paragraph">Python ma wbudowane,&nbsp;<strong>bardzo zoptymalizowane</strong>&nbsp;funkcje sortowania.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># sorted() - zwraca nową posortowaną listę
dane = &#91;3, 1, 4, 1, 5, 9, 2, 6]
posortowane = sorted(dane)
print(posortowane)  # &#91;1, 1, 2, 3, 4, 5, 6, 9]

# sort() - sortuje in-place
dane = &#91;3, 1, 4, 1, 5, 9, 2, 6]
dane.sort()
print(dane)  # &#91;1, 1, 2, 3, 4, 5, 6, 9]

# Malejąco
dane.sort(reverse=True)
print(dane)  # &#91;9, 6, 5, 4, 3, 2, 1, 1]

# Sortowanie z kluczem
osoby = &#91;{'imie': 'Jan', 'wiek': 25}, 
         {'imie': 'Anna', 'wiek': 30}]
osoby.sort(key=lambda x: x&#91;'wiek'])
print(osoby)</code></pre>



<p class="wp-block-paragraph"><strong>Algorytm:</strong>&nbsp;Python używa&nbsp;<strong>Timsort</strong>&nbsp;(hybrydowy Merge Sort + Insertion Sort) &#8211; O(n log n).</p>



<h2 class="wp-block-heading">Podsumowanie</h2>



<p class="wp-block-paragraph"><strong>Sortowanie:</strong></p>



<ul class="wp-block-list">
<li><strong>Bubble Sort</strong> &#8211; O(n²), prosty, edukacyjny</li>



<li><strong>Selection Sort</strong> &#8211; O(n²), prosty</li>



<li><strong>Insertion Sort</strong> &#8211; O(n²), dobry dla małych/prawie posortowanych</li>



<li><strong>Merge Sort</strong> &#8211; O(n log n), stabilny, wymaga pamięci</li>



<li><strong>Quick Sort</strong> &#8211; O(n log n) średnio, najszybszy praktycznie</li>



<li><strong>Python sort()</strong> &#8211; Timsort, O(n log n), używaj tego!</li>
</ul>



<p class="wp-block-paragraph"><strong>Przeszukiwanie:</strong></p>



<ul class="wp-block-list">
<li><strong>Linear Search</strong> &#8211; O(n), dla nieposortowanych</li>



<li><strong>Binary Search</strong> &#8211; O(log n), dla posortowanych</li>
</ul>



<p class="wp-block-paragraph"><strong>Złożoność:</strong></p>



<ul class="wp-block-list">
<li>O(1) &lt; O(log n) &lt; O(n) &lt; O(n log n) &lt; O(n²) &lt; O(2^n)</li>
</ul>



<p class="wp-block-paragraph"><strong>Zasada:</strong>&nbsp;Dla małych danych (&lt; 1000) różnice są niewielkie. Dla dużych &#8211; algorytm ma ogromne znaczenie!</p>




<p>Artykuł <a href="https://kamakaczmarek.net/20-python-algorytmy-sortowanie-i-przeszukiwanie/">20. Python – Algorytmy: Sortowanie i Przeszukiwanie</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>19. Python – Wykresy (Matplotlib i Seaborn)</title>
		<link>https://kamakaczmarek.net/19-python-wykresy-matplotlib-i-seaborn/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 11:05:10 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=5057</guid>

					<description><![CDATA[<p>Wprowadzenie Wizualizacja&#160;danych&#160;to&#160;kluczowy&#160;element&#160;analizy&#160;&#8211;&#160;pozwala&#160;szybko&#160;zrozumieć&#160;dane&#160;i&#160;wyciągnąć&#160;wnioski. Biblioteki: Matplotlib&#160;&#8211;&#160;podstawy Instalacja Pierwszy&#160;wykres&#160;&#8211;&#160;linia Personalizacja&#160;linii Wiele&#160;linii&#160;na&#160;jednym&#160;wykresie Typy&#160;wykresów Wykres&#160;punktowy&#160;(scatter) Wykres&#160;słupkowy&#160;(bar) Wykres&#160;słupkowy&#160;poziomy Histogram Wykres&#160;kołowy&#160;(pie) Wyciągnięty&#160;kawałek&#160;(explode) Wykres&#160;pudełkowy&#160;(box&#160;plot) Wiele&#160;wykresów&#160;(subplots) Zapisywanie&#160;wykresów Pandas&#160;+&#160;Matplotlib Pandas&#160;ma&#160;wbudowaną&#160;integrację&#160;z&#160;Matplotlib. Seaborn&#160;&#8211;&#160;piękniejsze&#160;wykresy Instalacja Podstawy&#160;Seaborn Wykres&#160;z&#160;regresją&#160;liniową Wykres&#160;skrzypcowy&#160;(violin) Heatmapa&#160;(korelacja) Pair&#160;plot Praktyczne&#160;przykłady Przykład&#160;1:&#160;Analiza&#160;sprzedaży Przykład&#160;2:&#160;Porównanie&#160;produktów Przykład&#160;3:&#160;Rozkład&#160;wieku Przykład&#160;4:&#160;Dashboard&#160;z&#160;wieloma&#160;wykresami Podsumowanie Matplotlib: Personalizacja: Seaborn: Integracja&#160;z&#160;Pandas:</p>
<p>Artykuł <a href="https://kamakaczmarek.net/19-python-wykresy-matplotlib-i-seaborn/">19. Python – Wykresy (Matplotlib i Seaborn)</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Wprowadzenie</h2>



<p class="wp-block-paragraph"><strong>Wizualizacja&nbsp;danych</strong>&nbsp;to&nbsp;kluczowy&nbsp;element&nbsp;analizy&nbsp;&#8211;&nbsp;pozwala&nbsp;szybko&nbsp;zrozumieć&nbsp;dane&nbsp;i&nbsp;wyciągnąć&nbsp;wnioski.</p>



<p class="wp-block-paragraph"><strong>Biblioteki:</strong></p>



<ul class="wp-block-list">
<li><strong>Matplotlib</strong>&nbsp;&#8211;&nbsp;podstawowa,&nbsp;najpopularniejsza</li>



<li><strong>Seaborn</strong>&nbsp;&#8211;&nbsp;ładniejsze&nbsp;wykresy,&nbsp;bazuje&nbsp;na&nbsp;Matplotlib</li>



<li><strong>Plotly</strong>&nbsp;&#8211;&nbsp;interaktywne&nbsp;wykresy</li>
</ul>



<h2 class="wp-block-heading">Matplotlib&nbsp;&#8211;&nbsp;podstawy</h2>



<h3 class="wp-block-heading">Instalacja</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">pip install matplotlib</code></pre>



<h3 class="wp-block-heading">Pierwszy&nbsp;wykres&nbsp;&#8211;&nbsp;linia</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

# Dane
x = &#91;1, 2, 3, 4, 5]
y = &#91;2, 4, 6, 8, 10]

# Stwórz wykres
plt.plot(x, y)

# Opisy
plt.title('Mój pierwszy wykres')
plt.xlabel('Oś X')
plt.ylabel('Oś Y')

# Pokaż
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="638" height="475" src="https://kamakaczmarek.net/wp-content/uploads/wykres_linia.png" alt="" class="wp-image-5082" srcset="https://kamakaczmarek.net/wp-content/uploads/wykres_linia.png 638w, https://kamakaczmarek.net/wp-content/uploads/wykres_linia-300x223.png 300w" sizes="(max-width: 638px) 100vw, 638px" /></figure>
</div>



<h3 class="wp-block-heading">Personalizacja&nbsp;linii</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

x = &#91;1, 2, 3, 4, 5]
y = &#91;2, 4, 6, 8, 10]

# Styl linii
plt.plot(x, y, 
         color='red',          # Kolor
         linewidth=2,          # Grubość
         linestyle='--',       # Styl: '-', '--', '-.', ':'
         marker='o',           # Markery: 'o', 's', '^', '*'
         markersize=8,         # Rozmiar markerów
         label='Dane 1')       # Etykieta

plt.title('Wykres z personalizacją')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()  # Pokaż legendę
plt.grid(True)  # Siatka
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Personalizacja_linii.png" alt="" class="wp-image-5067" srcset="https://kamakaczmarek.net/wp-content/uploads/Personalizacja_linii.png 640w, https://kamakaczmarek.net/wp-content/uploads/Personalizacja_linii-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Wiele&nbsp;linii&nbsp;na&nbsp;jednym&nbsp;wykresie</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

x = &#91;1, 2, 3, 4, 5]
y1 = &#91;2, 4, 6, 8, 10]
y2 = &#91;1, 3, 5, 7, 9]
y3 = &#91;3, 5, 4, 6, 8]

plt.plot(x, y1, label='Linia 1', marker='o')
plt.plot(x, y2, label='Linia 2', marker='s')
plt.plot(x, y3, label='Linia 3', marker='^')

plt.title('Wiele linii')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.grid(True)
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Wiele_-linii.png" alt="" class="wp-image-5077" srcset="https://kamakaczmarek.net/wp-content/uploads/Wiele_-linii.png 640w, https://kamakaczmarek.net/wp-content/uploads/Wiele_-linii-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h2 class="wp-block-heading">Typy&nbsp;wykresów</h2>



<h3 class="wp-block-heading">Wykres&nbsp;punktowy&nbsp;(scatter)</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

x = &#91;1, 2, 3, 4, 5, 6]
y = &#91;2, 4, 5, 7, 8, 10]

plt.scatter(x, y, 
            s=100,           # Rozmiar punktów
            c='red',         # Kolor
            alpha=0.6,       # Przezroczystość
            edgecolors='black')  # Obramowanie

plt.title('Wykres punktowy')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/punktowy.png" alt="" class="wp-image-5073" srcset="https://kamakaczmarek.net/wp-content/uploads/punktowy.png 640w, https://kamakaczmarek.net/wp-content/uploads/punktowy-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Wykres&nbsp;słupkowy&nbsp;(bar)</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

kategorie = &#91;'A', 'B', 'C', 'D', 'E']
wartosci = &#91;23, 45, 56, 78, 32]

plt.bar(kategorie, wartosci, 
        color='skyblue',
        edgecolor='black',
        width=0.6)

plt.title('Wykres słupkowy')
plt.xlabel('Kategoria')
plt.ylabel('Wartość')
plt.show()</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/slupkowy.png" alt="" class="wp-image-5074" srcset="https://kamakaczmarek.net/wp-content/uploads/slupkowy.png 640w, https://kamakaczmarek.net/wp-content/uploads/slupkowy-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Wykres&nbsp;słupkowy&nbsp;poziomy</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

kategorie = &#91;'Produkt A', 'Produkt B', 'Produkt C']
wartosci = &#91;150, 230, 180]

plt.barh(kategorie, wartosci, color='lightgreen')
plt.title('Sprzedaż produktów')
plt.xlabel('Liczba sprzedanych')
plt.show()
</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/slupkowy_poziomy.png" alt="" class="wp-image-5075" srcset="https://kamakaczmarek.net/wp-content/uploads/slupkowy_poziomy.png 640w, https://kamakaczmarek.net/wp-content/uploads/slupkowy_poziomy-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Histogram</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt
import numpy as np

# Dane - rozkład normalny
dane = np.random.randn(1000)

plt.hist(dane, 
         bins=30,           # Liczba słupków
         color='purple',
         alpha=0.7,
         edgecolor='black')

plt.title('Histogram')
plt.xlabel('Wartość')
plt.ylabel('Częstość')
plt.show()</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Histogram.png" alt="" class="wp-image-5064" srcset="https://kamakaczmarek.net/wp-content/uploads/Histogram.png 640w, https://kamakaczmarek.net/wp-content/uploads/Histogram-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Wykres&nbsp;kołowy&nbsp;(pie)</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

kategorie = &#91;'Python', 'Java', 'JavaScript', 'C++']
udzialy = &#91;40, 25, 20, 15]

plt.pie(udzialy, 
        labels=kategorie,
        autopct='%1.1f%%',  # Pokaż procenty
        startangle=90,       # Kąt początkowy
        colors=&#91;'#ff9999', '#66b3ff', '#99ff99', '#ffcc99'])

plt.title('Popularne języki programowania')
plt.show()
</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Popularne-jezyki-programowania.png" alt="" class="wp-image-5068" srcset="https://kamakaczmarek.net/wp-content/uploads/Popularne-jezyki-programowania.png 640w, https://kamakaczmarek.net/wp-content/uploads/Popularne-jezyki-programowania-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Wyciągnięty&nbsp;kawałek&nbsp;(explode)</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

kategorie = &#91;'Python', 'Java', 'JavaScript', 'C++']
udzialy = &#91;40, 25, 20, 15]
explode = &#91;0.1, 0, 0, 0]  # Wyciągnij pierwszy

plt.pie(udzialy, 
        labels=kategorie,
        autopct='%1.1f%%',
        explode=explode,
        shadow=True)

plt.title('Języki programowania')
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Jezyki-programowania.png" alt="" class="wp-image-5065" srcset="https://kamakaczmarek.net/wp-content/uploads/Jezyki-programowania.png 640w, https://kamakaczmarek.net/wp-content/uploads/Jezyki-programowania-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Wykres&nbsp;pudełkowy&nbsp;(box&nbsp;plot)</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt
import numpy as np

# Dane dla różnych grup
dane1 = np.random.normal(100, 10, 200)
dane2 = np.random.normal(90, 20, 200)
dane3 = np.random.normal(80, 5, 200)

dane = &#91;dane1, dane2, dane3]

plt.boxplot(dane, labels=&#91;'Grupa A', 'Grupa B', 'Grupa C'])
plt.title('Box Plot')
plt.ylabel('Wartości')
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Box-Plot.png" alt="" class="wp-image-5062" srcset="https://kamakaczmarek.net/wp-content/uploads/Box-Plot.png 640w, https://kamakaczmarek.net/wp-content/uploads/Box-Plot-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h2 class="wp-block-heading">Wiele&nbsp;wykresów&nbsp;(subplots)</h2>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

# Stwórz siatkę 2x2
fig, axes = plt.subplots(2, 2, figsize=(10, 8))

# Wykres 1
axes&#91;0, 0].plot(x, np.sin(x))
axes&#91;0, 0].set_title('sin(x)')

# Wykres 2
axes&#91;0, 1].plot(x, np.cos(x), 'r')
axes&#91;0, 1].set_title('cos(x)')

# Wykres 3
axes&#91;1, 0].plot(x, x**2, 'g')
axes&#91;1, 0].set_title('x²')

# Wykres 4
axes&#91;1, 1].plot(x, np.exp(x/10), 'purple')
axes&#91;1, 1].set_title('e^(x/10)')

plt.tight_layout()  # Automatyczne dopasowanie
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1000" height="800" src="https://kamakaczmarek.net/wp-content/uploads/Wiele-wykresow.png" alt="" class="wp-image-5076" srcset="https://kamakaczmarek.net/wp-content/uploads/Wiele-wykresow.png 1000w, https://kamakaczmarek.net/wp-content/uploads/Wiele-wykresow-300x240.png 300w, https://kamakaczmarek.net/wp-content/uploads/Wiele-wykresow-768x614.png 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure>
</div>



<h2 class="wp-block-heading">Zapisywanie&nbsp;wykresów</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

x = &#91;1, 2, 3, 4, 5]
y = &#91;2, 4, 6, 8, 10]

plt.plot(x, y)
plt.title('Mój wykres')

# Zapisz do pliku
plt.savefig('wykres.png', dpi=300, bbox_inches='tight')
# plt.savefig('wykres.pdf')  # PDF
# plt.savefig('wykres.svg')  # SVG

print("Wykres zapisany!")</code></pre>



<h2 class="wp-block-heading">Pandas&nbsp;+&nbsp;Matplotlib</h2>



<p class="wp-block-paragraph">Pandas&nbsp;ma&nbsp;wbudowaną&nbsp;integrację&nbsp;z&nbsp;Matplotlib.</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd
import matplotlib.pyplot as plt

# DataFrame
df = pd.DataFrame({
    'Miesiąc': &#91;'Sty', 'Lut', 'Mar', 'Kwi', 'Maj'],
    'Sprzedaż': &#91;120, 150, 180, 160, 200]
})

# Wykres bezpośrednio z DataFrame
df.plot(x='Miesiąc', y='Sprzedaż', kind='bar', color='skyblue')
plt.title('Sprzedaż miesięczna')
plt.ylabel('Sprzedaż')
plt.show()

# Inne typy: 'line', 'bar', 'barh', 'hist', 'box', 'scatter', 'pie'</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Wykres-bezposrednio-z-DataFrame.png" alt="" class="wp-image-5078" srcset="https://kamakaczmarek.net/wp-content/uploads/Wykres-bezposrednio-z-DataFrame.png 640w, https://kamakaczmarek.net/wp-content/uploads/Wykres-bezposrednio-z-DataFrame-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h2 class="wp-block-heading">Seaborn&nbsp;&#8211;&nbsp;piękniejsze&nbsp;wykresy</h2>



<h3 class="wp-block-heading">Instalacja</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">pip install seaborn</code></pre>



<h3 class="wp-block-heading">Podstawy&nbsp;Seaborn</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import seaborn as sns
import matplotlib.pyplot as plt

# Ustaw styl
sns.set_style('darkgrid')  # 'darkgrid', 'whitegrid', 'dark', 'white', 'ticks'

# Dane
tips = sns.load_dataset('tips')  # Przykładowy zbiór danych

# Wykres punktowy z linią trendu
sns.scatterplot(data=tips, x='total_bill', y='tip')
plt.title('Rachunek vs Napiwek')
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Wykres-punktowy-z-linia-trendu.png" alt="" class="wp-image-5079" srcset="https://kamakaczmarek.net/wp-content/uploads/Wykres-punktowy-z-linia-trendu.png 640w, https://kamakaczmarek.net/wp-content/uploads/Wykres-punktowy-z-linia-trendu-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Wykres&nbsp;z&nbsp;regresją&nbsp;liniową</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import seaborn as sns
import matplotlib.pyplot as plt

tips = sns.load_dataset('tips')

# Scatter plot + linia trendu
sns.regplot(data=tips, x='total_bill', y='tip')
plt.title('Rachunek vs Napiwek (z trendem)')
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Wykres-z-regresja-liniowa.png" alt="" class="wp-image-5081" srcset="https://kamakaczmarek.net/wp-content/uploads/Wykres-z-regresja-liniowa.png 640w, https://kamakaczmarek.net/wp-content/uploads/Wykres-z-regresja-liniowa-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Wykres&nbsp;skrzypcowy&nbsp;(violin)</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import seaborn as sns
import matplotlib.pyplot as plt

tips = sns.load_dataset('tips')

sns.violinplot(data=tips, x='day', y='total_bill')
plt.title('Rachunki według dni tygodnia')
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Wykres-skrzypcowy.png" alt="" class="wp-image-5080" srcset="https://kamakaczmarek.net/wp-content/uploads/Wykres-skrzypcowy.png 640w, https://kamakaczmarek.net/wp-content/uploads/Wykres-skrzypcowy-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Heatmapa&nbsp;(korelacja)</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# Dane
df = pd.DataFrame({
    'A': &#91;1, 2, 3, 4, 5],
    'B': &#91;2, 4, 6, 8, 10],
    'C': &#91;5, 4, 3, 2, 1]
})

# Macierz korelacji
korelacja = df.corr()

# Heatmapa
sns.heatmap(korelacja, 
            annot=True,      # Pokaż wartości
            cmap='coolwarm', # Paleta kolorów
            center=0)        # Wyśrodkuj na 0

plt.title('Macierz korelacji')
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="640" height="480" src="https://kamakaczmarek.net/wp-content/uploads/Heatmapa.png" alt="" class="wp-image-5063" srcset="https://kamakaczmarek.net/wp-content/uploads/Heatmapa.png 640w, https://kamakaczmarek.net/wp-content/uploads/Heatmapa-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<h3 class="wp-block-heading">Pair&nbsp;plot</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import seaborn as sns
import matplotlib.pyplot as plt

# Załaduj dane
iris = sns.load_dataset('iris')

# Wykres wszystkich par zmiennych
sns.pairplot(iris, hue='species')
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1109" height="730" src="https://kamakaczmarek.net/wp-content/uploads/Pair-plot.png" alt="" class="wp-image-5066" srcset="https://kamakaczmarek.net/wp-content/uploads/Pair-plot.png 1109w, https://kamakaczmarek.net/wp-content/uploads/Pair-plot-300x197.png 300w, https://kamakaczmarek.net/wp-content/uploads/Pair-plot-1024x674.png 1024w, https://kamakaczmarek.net/wp-content/uploads/Pair-plot-768x506.png 768w" sizes="(max-width: 1109px) 100vw, 1109px" /></figure>
</div>



<h2 class="wp-block-heading">Praktyczne&nbsp;przykłady</h2>



<h3 class="wp-block-heading">Przykład&nbsp;1:&nbsp;Analiza&nbsp;sprzedaży</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd
import matplotlib.pyplot as plt

# Dane sprzedażowe
sprzedaz = pd.DataFrame({
    'Miesiąc': &#91;'Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze'],
    'Sprzedaż': &#91;12000, 15000, 13000, 18000, 22000, 25000],
    'Cel': &#91;15000, 15000, 15000, 20000, 20000, 20000]
})

# Wykres
plt.figure(figsize=(10, 6))
plt.plot(sprzedaz&#91;'Miesiąc'], sprzedaz&#91;'Sprzedaż'], 
         marker='o', linewidth=2, label='Rzeczywista')
plt.plot(sprzedaz&#91;'Miesiąc'], sprzedaz&#91;'Cel'], 
         marker='s', linewidth=2, linestyle='--', label='Cel')

plt.title('Sprzedaż vs Cel - 2024', fontsize=16)
plt.xlabel('Miesiąc')
plt.ylabel('Sprzedaż (PLN)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1000" height="600" src="https://kamakaczmarek.net/wp-content/uploads/Przyklad-1-Analiza-sprzedazy.png" alt="" class="wp-image-5069" srcset="https://kamakaczmarek.net/wp-content/uploads/Przyklad-1-Analiza-sprzedazy.png 1000w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-1-Analiza-sprzedazy-300x180.png 300w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-1-Analiza-sprzedazy-768x461.png 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure>



<h3 class="wp-block-heading">Przykład&nbsp;2:&nbsp;Porównanie&nbsp;produktów</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt

produkty = &#91;'Laptop', 'Telefon', 'Tablet', 'Monitor', 'Klawiatura']
sprzedaz_q1 = &#91;45, 78, 32, 56, 89]
sprzedaz_q2 = &#91;52, 85, 38, 61, 95]

x = range(len(produkty))
width = 0.35

plt.figure(figsize=(10, 6))
plt.bar(&#91;i - width/2 for i in x], sprzedaz_q1, width, label='Q1', color='skyblue')
plt.bar(&#91;i + width/2 for i in x], sprzedaz_q2, width, label='Q2', color='lightgreen')

plt.title('Sprzedaż produktów - Q1 vs Q2')
plt.xlabel('Produkt')
plt.ylabel('Liczba sprzedanych')
plt.xticks(x, produkty)
plt.legend()
plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1000" height="600" src="https://kamakaczmarek.net/wp-content/uploads/Przyklad-2-Porownanie-produktow.png" alt="" class="wp-image-5070" srcset="https://kamakaczmarek.net/wp-content/uploads/Przyklad-2-Porownanie-produktow.png 1000w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-2-Porownanie-produktow-300x180.png 300w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-2-Porownanie-produktow-768x461.png 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure>



<h3 class="wp-block-heading">Przykład&nbsp;3:&nbsp;Rozkład&nbsp;wieku</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt
import numpy as np

# Symulacja danych
wiek = np.random.normal(35, 10, 1000)  # Średnia 35, odchylenie 10

plt.figure(figsize=(10, 6))
plt.hist(wiek, bins=30, color='coral', edgecolor='black', alpha=0.7)
plt.axvline(wiek.mean(), color='red', linestyle='--', linewidth=2, label=f'Średnia: {wiek.mean():.1f}')

plt.title('Rozkład wieku pracowników')
plt.xlabel('Wiek')
plt.ylabel('Liczba osób')
plt.legend()
plt.grid(axis='y', alpha=0.3)
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1000" height="600" src="https://kamakaczmarek.net/wp-content/uploads/Przyklad-3-Rozklad-wieku.png" alt="" class="wp-image-5071" srcset="https://kamakaczmarek.net/wp-content/uploads/Przyklad-3-Rozklad-wieku.png 1000w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-3-Rozklad-wieku-300x180.png 300w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-3-Rozklad-wieku-768x461.png 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure>



<h3 class="wp-block-heading">Przykład&nbsp;4:&nbsp;Dashboard&nbsp;z&nbsp;wieloma&nbsp;wykresami</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import matplotlib.pyplot as plt
import pandas as pd

# Dane
df = pd.DataFrame({
    'Miesiąc': &#91;'Sty', 'Lut', 'Mar', 'Kwi'],
    'Przychód': &#91;12000, 15000, 13000, 18000],
    'Koszty': &#91;8000, 9000, 8500, 11000],
    'Klienci': &#91;120, 145, 130, 170]
})

df&#91;'Zysk'] = df&#91;'Przychód'] - df&#91;'Koszty']

# Stwórz dashboard
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle('Dashboard Sprzedażowy - Q1 2024', fontsize=16)

# Wykres 1: Przychód i koszty
axes&#91;0, 0].plot(df&#91;'Miesiąc'], df&#91;'Przychód'], marker='o', label='Przychód')
axes&#91;0, 0].plot(df&#91;'Miesiąc'], df&#91;'Koszty'], marker='s', label='Koszty')
axes&#91;0, 0].set_title('Przychód i Koszty')
axes&#91;0, 0].set_ylabel('PLN')
axes&#91;0, 0].legend()
axes&#91;0, 0].grid(True, alpha=0.3)

# Wykres 2: Zysk
axes&#91;0, 1].bar(df&#91;'Miesiąc'], df&#91;'Zysk'], color='green', alpha=0.7)
axes&#91;0, 1].set_title('Zysk')
axes&#91;0, 1].set_ylabel('PLN')
axes&#91;0, 1].grid(axis='y', alpha=0.3)

# Wykres 3: Liczba klientów
axes&#91;1, 0].plot(df&#91;'Miesiąc'], df&#91;'Klienci'], marker='D', color='purple', linewidth=2)
axes&#91;1, 0].set_title('Liczba klientów')
axes&#91;1, 0].set_ylabel('Klienci')
axes&#91;1, 0].grid(True, alpha=0.3)

# Wykres 4: Udział przychodów
axes&#91;1, 1].pie(df&#91;'Przychód'], labels=df&#91;'Miesiąc'], autopct='%1.1f%%', startangle=90)
axes&#91;1, 1].set_title('Udział przychodów')

plt.tight_layout()
plt.show()</code></pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1400" height="696" src="https://kamakaczmarek.net/wp-content/uploads/Przyklad-4-Dashboard-z-wieloma-wykresami.png" alt="" class="wp-image-5072" srcset="https://kamakaczmarek.net/wp-content/uploads/Przyklad-4-Dashboard-z-wieloma-wykresami.png 1400w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-4-Dashboard-z-wieloma-wykresami-300x149.png 300w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-4-Dashboard-z-wieloma-wykresami-1024x509.png 1024w, https://kamakaczmarek.net/wp-content/uploads/Przyklad-4-Dashboard-z-wieloma-wykresami-768x382.png 768w" sizes="(max-width: 1400px) 100vw, 1400px" /></figure>



<h2 class="wp-block-heading">Podsumowanie</h2>



<p class="wp-block-paragraph"><strong>Matplotlib:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">plt.plot()</code>&nbsp;&#8211;&nbsp;wykres&nbsp;liniowy</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">plt.scatter()</code>&nbsp;&#8211;&nbsp;wykres&nbsp;punktowy</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">plt.bar()</code>&nbsp;/&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">plt.barh()</code>&nbsp;&#8211;&nbsp;słupkowy</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">plt.hist()</code>&nbsp;&#8211;&nbsp;histogram</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">plt.pie()</code>&nbsp;&#8211;&nbsp;kołowy</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">plt.boxplot()</code>&nbsp;&#8211;&nbsp;pudełkowy</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">plt.subplots()</code>&nbsp;&#8211;&nbsp;wiele&nbsp;wykresów</li>
</ul>



<p class="wp-block-paragraph"><strong>Personalizacja:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">color</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">linewidth</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">linestyle</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">marker</code></li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">title()</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">xlabel()</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">ylabel()</code></li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">legend()</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">grid()</code></li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">savefig()</code>&nbsp;&#8211;&nbsp;zapis&nbsp;do&nbsp;pliku</li>
</ul>



<p class="wp-block-paragraph"><strong>Seaborn:</strong></p>



<ul class="wp-block-list">
<li>Ładniejsze&nbsp;style</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">scatterplot()</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">regplot()</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">violinplot()</code></li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">heatmap()</code>&nbsp;&#8211;&nbsp;korelacja</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">pairplot()</code>&nbsp;&#8211;&nbsp;wszystkie&nbsp;pary</li>
</ul>



<p class="wp-block-paragraph"><strong>Integracja&nbsp;z&nbsp;Pandas:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">df.plot()</code>&nbsp;&#8211;&nbsp;bezpośrednie&nbsp;wykresy&nbsp;z&nbsp;DataFrame</li>
</ul>
<p>Artykuł <a href="https://kamakaczmarek.net/19-python-wykresy-matplotlib-i-seaborn/">19. Python – Wykresy (Matplotlib i Seaborn)</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>18. Python &#8211; Analiza danych: CSV i Pandas</title>
		<link>https://kamakaczmarek.net/18-python-analiza-danych-csv-i-pandas/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 10:56:22 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=5055</guid>

					<description><![CDATA[<p>Analiza danych&#160;to proces przetwarzania, czyszczenia i interpretowania danych w celu wyciągnięcia użytecznych informacji. Python jest jednym z najpopularniejszych języków do analizy danych. Format CSV CSV&#160;(Comma-Separated Values) to prosty format przechowywania danych tabelarycznych w pliku tekstowym. Struktura: Python ma wbudowany moduł&#160;csv&#160;do czytania i zapisywania plików CSV. Odczyt pliku CSV Odczyt jako słownik Zapis do CSV Ważne: [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/18-python-analiza-danych-csv-i-pandas/">18. Python &#8211; Analiza danych: CSV i Pandas</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Analiza danych</strong>&nbsp;to proces przetwarzania, czyszczenia i interpretowania danych w celu wyciągnięcia użytecznych informacji. Python jest jednym z najpopularniejszych języków do analizy danych.</p>



<h2 class="wp-block-heading">Format CSV</h2>



<p class="wp-block-paragraph"><strong>CSV</strong>&nbsp;(Comma-Separated Values) to prosty format przechowywania danych tabelarycznych w pliku tekstowym.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">Imie,Nazwisko,Wiek,Miasto
Jan,Kowalski,25,Warszawa
Anna,Nowak,30,Kraków
Piotr,Wiśniewski,28,Gdańsk</code></pre>



<p class="wp-block-paragraph"><strong>Struktura:</strong></p>



<ul class="wp-block-list">
<li>Pierwszy wiersz = nagłówki kolumn</li>



<li>Kolejne wiersze = dane</li>



<li>Separator (najczęściej przecinek)</li>
</ul>



<p class="wp-block-paragraph">Python ma wbudowany moduł&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">csv</code>&nbsp;do czytania i zapisywania plików CSV.</p>



<h3 class="wp-block-heading">Odczyt pliku CSV</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import csv

# Odczyt CSV jako lista list
with open('dane.csv', 'r', encoding='utf-8') as plik:
    czytnik = csv.reader(plik)
    
    # Pierwszy wiersz - nagłówki
    naglowki = next(czytnik)
    print(naglowki)  # &#91;'Imie', 'Nazwisko', 'Wiek', 'Miasto']
    
    # Pozostałe wiersze - dane
    for wiersz in czytnik:
        print(wiersz)
        # &#91;'Jan', 'Kowalski', '25', 'Warszawa']
        # &#91;'Anna', 'Nowak', '30', 'Kraków']</code></pre>



<h3 class="wp-block-heading">Odczyt jako słownik</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import csv

# DictReader - każdy wiersz jako słownik
with open('dane.csv', 'r', encoding='utf-8') as plik:
    czytnik = csv.DictReader(plik)
    
    for wiersz in czytnik:
        print(wiersz)
        # {'Imie': 'Jan', 'Nazwisko': 'Kowalski', 'Wiek': '25', 'Miasto': 'Warszawa'}
        
        # Dostęp po kluczu
        print(f"{wiersz&#91;'Imie']} {wiersz&#91;'Nazwisko']}, {wiersz&#91;'Wiek']} lat")</code></pre>



<h3 class="wp-block-heading">Zapis do CSV</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import csv

dane = &#91;
    &#91;'Imie', 'Nazwisko', 'Wiek', 'Miasto'],
    &#91;'Jan', 'Kowalski', 25, 'Warszawa'],
    &#91;'Anna', 'Nowak', 30, 'Kraków'],
    &#91;'Piotr', 'Wiśniewski', 28, 'Gdańsk']
]

# Zapis do CSV
with open('nowe_dane.csv', 'w', newline='', encoding='utf-8') as plik:
    writer = csv.writer(plik)
    writer.writerows(dane)

print("Plik zapisany!")</code></pre>



<p class="wp-block-paragraph"><strong>Ważne:</strong><code class="prettyprint lang-sql" style="font-size: 0.85em;"> newline=''</code> zapobiega pustym liniom w Windows</p>



<h3 class="wp-block-heading">Zapis słowników</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import csv

dane = &#91;
    {'Imie': 'Jan', 'Nazwisko': 'Kowalski', 'Wiek': 25},
    {'Imie': 'Anna', 'Nazwisko': 'Nowak', 'Wiek': 30},
    {'Imie': 'Piotr', 'Nazwisko': 'Wiśniewski', 'Wiek': 28}
]

with open('slowniki.csv', 'w', newline='', encoding='utf-8') as plik:
    naglowki = &#91;'Imie', 'Nazwisko', 'Wiek']
    writer = csv.DictWriter(plik, fieldnames=naglowki)
    
    writer.writeheader()  # Zapisz nagłówki
    writer.writerows(dane)  # Zapisz dane

print("Plik zapisany!")</code></pre>



<h3 class="wp-block-heading">Różne separatory</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import csv

# CSV z średnikiem jako separator
with open('dane_sredniki.csv', 'r', encoding='utf-8') as plik:
    czytnik = csv.reader(plik, delimiter=';')
    for wiersz in czytnik:
        print(wiersz)

# Zapis z tabulatorem
with open('dane_tab.csv', 'w', newline='', encoding='utf-8') as plik:
    writer = csv.writer(plik, delimiter='\t')
    writer.writerow(&#91;'Kolumna1', 'Kolumna2', 'Kolumna3'])</code></pre>



<h2 class="wp-block-heading">Pandas &#8211; profesjonalna analiza danych</h2>



<p class="wp-block-paragraph"><strong>Pandas</strong>&nbsp;to najpopularniejsza biblioteka do analizy danych w Pythonie.</p>



<h3 class="wp-block-heading">Instalacja</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">pip install pandas</code></pre>



<h3 class="wp-block-heading">Podstawowe struktury danych</h3>



<p class="wp-block-paragraph"><strong>Pandas ma dwie główne struktury:</strong></p>



<ul class="wp-block-list">
<li><strong>Series</strong> &#8211; jednowymiarowa (jak lista z indeksami)</li>



<li><strong>DataFrame</strong> &#8211; dwuwymiarowa (tabela)</li>
</ul>



<h2 class="wp-block-heading">Series &#8211; jednowymiarowa seria</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

# Tworzenie Series
s = pd.Series(&#91;10, 20, 30, 40, 50])
print(s)
# 0    10
# 1    20
# 2    30
# 3    40
# 4    50
# dtype: int64

# Series z własnymi indeksami
s2 = pd.Series(&#91;10, 20, 30], index=&#91;'a', 'b', 'c'])
print(s2)
# a    10
# b    20
# c    30

# Dostęp do elementów
print(s2&#91;'a'])  # 10
print(s2&#91;0])    # 10</code></pre>



<h2 class="wp-block-heading">DataFrame &#8211; tabela danych</h2>



<p class="wp-block-paragraph"><strong>DataFrame</strong>&nbsp;to główna struktura w Pandas &#8211; dwuwymiarowa tabela z kolumnami.</p>



<h3 class="wp-block-heading">Tworzenie DataFrame</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

# Ze słownika
dane = {
    'Imie': &#91;'Jan', 'Anna', 'Piotr'],
    'Wiek': &#91;25, 30, 28],
    'Miasto': &#91;'Warszawa', 'Kraków', 'Gdańsk']
}

df = pd.DataFrame(dane)
print(df)
#     Imie  Wiek    Miasto
# 0    Jan    25  Warszawa
# 1   Anna    30    Kraków
# 2  Piotr    28    Gdańsk</code></pre>



<h3 class="wp-block-heading">Z listy list &#8211; zagnieżdżone listy</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

dane = &#91;
    &#91;'Jan', 25, 'Warszawa'],
    &#91;'Anna', 30, 'Kraków'],
    &#91;'Piotr', 28, 'Gdańsk']
]

df = pd.DataFrame(dane, columns=&#91;'Imie', 'Wiek', 'Miasto'])
print(df)
</code></pre>



<h3 class="wp-block-heading">Z listy słowników</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

dane = &#91;
    {'Imie': 'Jan', 'Wiek': 25, 'Miasto': 'Warszawa'},
    {'Imie': 'Anna', 'Wiek': 30, 'Miasto': 'Kraków'},
    {'Imie': 'Piotr', 'Wiek': 28, 'Miasto': 'Gdańsk'}
]

df = pd.DataFrame(dane)
print(df)
</code></pre>



<h2 class="wp-block-heading">Wczytywanie danych z plików</h2>



<h3 class="wp-block-heading">CSV</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

# Wczytaj CSV
df = pd.read_csv('dane.csv')
print(df)

# Z różnymi opcjami
df = pd.read_csv('dane.csv', 
                 encoding='utf-8',      # Kodowanie
                 sep=';',               # Separator
                 decimal=',',           # Separator dziesiętny
                 thousands=' ')         # Separator tysięcy

# Bez nagłówków
df = pd.read_csv('dane.csv', header=None)

# Własne nazwy kolumn
df = pd.read_csv('dane.csv', names=&#91;'Col1', 'Col2', 'Col3'])
</code></pre>



<h3 class="wp-block-heading">Excel</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

# Wymaga: pip install openpyxl

# Wczytaj Excel
df = pd.read_excel('dane.xlsx')

# Konkretny arkusz
df = pd.read_excel('dane.xlsx', sheet_name='Arkusz1')
</code></pre>



<h3 class="wp-block-heading">JSON</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

# Wczytaj JSON
df = pd.read_json('dane.json')

# Z różnymi orientacjami
df = pd.read_json('dane.json', orient='records')
</code></pre>



<h2 class="wp-block-heading">Podstawowe operacje na DataFrame</h2>



<h3 class="wp-block-heading">Podgląd danych</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.read_csv('dane.csv')

# Pierwsze 5 wierszy
print(df.head())

# Pierwsze n wierszy
print(df.head(10))

# Ostatnie 5 wierszy
print(df.tail())

# Informacje o DataFrame
print(df.info())
# Wyświetli: typy kolumn, liczbę niepustych wartości

# Statystyki opisowe (dla kolumn numerycznych)
print(df.describe())
# Wyświetli: count, mean, std, min, max, quartiles

# Wymiary (wiersze, kolumny)
print(df.shape)  # (100, 5)

# Nazwy kolumn
print(df.columns)  # Index(&#91;'Imie', 'Wiek', 'Miasto'])

# Typy danych
print(df.dtypes)
</code></pre>



<h3 class="wp-block-heading">Dostęp do kolumn</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Imie': &#91;'Jan', 'Anna', 'Piotr'],
    'Wiek': &#91;25, 30, 28],
    'Miasto': &#91;'Warszawa', 'Kraków', 'Gdańsk']
})

# Jedna kolumna (Series)
print(df&#91;'Imie'])
# 0      Jan
# 1     Anna
# 2    Piotr

# Lub jako atrybut
print(df.Imie)

# Wiele kolumn (DataFrame)
print(df&#91;&#91;'Imie', 'Wiek']])
#     Imie  Wiek
# 0    Jan    25
# 1   Anna    30
# 2  Piotr    28
</code></pre>



<h3 class="wp-block-heading">Dostęp do wierszy</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Imie': &#91;'Jan', 'Anna', 'Piotr'],
    'Wiek': &#91;25, 30, 28],
    'Miasto': &#91;'Warszawa', 'Kraków', 'Gdańsk']
})

# Po indeksie liczbowym - iloc
print(df.iloc&#91;0])  # Pierwszy wiersz
# Imie          Jan
# Wiek           25
# Miasto    Warszawa

print(df.iloc&#91;0:2])  # Pierwsze dwa wiersze

# Po etykiecie indeksu - loc
df_indexed = df.set_index('Imie')
print(df_indexed.loc&#91;'Anna'])
# Wiek          30
# Miasto    Kraków

# Konkretna komórka
print(df.iloc&#91;0, 1])  # Wiersz 0, kolumna 1 → 25
print(df.loc&#91;0, 'Wiek'])  # Wiersz 0, kolumna 'Wiek' → 25
</code></pre>



<h2 class="wp-block-heading">Filtrowanie danych</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Imie': &#91;'Jan', 'Anna', 'Piotr', 'Ewa'],
    'Wiek': &#91;25, 30, 28, 22],
    'Miasto': &#91;'Warszawa', 'Kraków', 'Gdańsk', 'Warszawa']
})

# Filtruj wiek &gt; 25
starsi = df&#91;df&#91;'Wiek'] &gt; 25]
print(starsi)
#     Imie  Wiek   Miasto
# 1   Anna    30   Kraków
# 2  Piotr    28   Gdańsk

# Filtruj miasto
warszawiacy = df&#91;df&#91;'Miasto'] == 'Warszawa']
print(warszawiacy)

# Wiele warunków (&amp; = and, | = or)
mlodzi_z_warszawy = df&#91;(df&#91;'Wiek'] &lt; 30) &amp; (df&#91;'Miasto'] == 'Warszawa')]
print(mlodzi_z_warszawy)

# isin() - czy wartość w liście
krakowskie = df&#91;df&#91;'Miasto'].isin(&#91;'Kraków', 'Gdańsk'])]
print(krakowskie)
</code></pre>



<h2 class="wp-block-heading">Dodawanie i usuwanie kolumn</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Imie': &#91;'Jan', 'Anna', 'Piotr'],
    'Wiek': &#91;25, 30, 28]
})

# Dodaj nową kolumnę
df&#91;'Pensja'] = &#91;5000, 6000, 5500]
print(df)
#     Imie  Wiek  Pensja
# 0    Jan    25    5000
# 1   Anna    30    6000
# 2  Piotr    28    5500

# Oblicz nową kolumnę z istniejącej
df&#91;'Wiek_za_10_lat'] = df&#91;'Wiek'] + 10
print(df)

# Usuń kolumnę
df = df.drop('Wiek_za_10_lat', axis=1)
# Lub in-place
df.drop('Pensja', axis=1, inplace=True)
print(df)</code></pre>



<h2 class="wp-block-heading">Sortowanie</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Imie': &#91;'Jan', 'Anna', 'Piotr'],
    'Wiek': &#91;25, 30, 28],
    'Pensja': &#91;5000, 6000, 5500]
})

# Sortuj po wieku (rosnąco)
df_sorted = df.sort_values('Wiek')
print(df_sorted)

# Sortuj malejąco
df_sorted = df.sort_values('Wiek', ascending=False)
print(df_sorted)

# Sortuj po wielu kolumnach
df_sorted = df.sort_values(&#91;'Wiek', 'Pensja'], ascending=&#91;True, False])
print(df_sorted)

# In-place
df.sort_values('Wiek', inplace=True)</code></pre>



<h2 class="wp-block-heading">Grupowanie i agregacja</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Miasto': &#91;'Warszawa', 'Kraków', 'Warszawa', 'Gdańsk', 'Kraków'],
    'Wiek': &#91;25, 30, 28, 22, 35],
    'Pensja': &#91;5000, 6000, 5500, 4500, 6500]
})

# Grupuj po mieście i oblicz średnią
srednie = df.groupby('Miasto')&#91;'Pensja'].mean()
print(srednie)
# Miasto
# Gdańsk       4500.0
# Kraków       6250.0
# Warszawa     5250.0

# Wiele agregacji
agregacja = df.groupby('Miasto').agg({
    'Wiek': 'mean',
    'Pensja': &#91;'min', 'max', 'mean']
})
print(agregacja)

# Policz wystąpienia
liczebnosc = df.groupby('Miasto').size()
print(liczebnosc)</code></pre>



<h2 class="wp-block-heading">Brakujące dane</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd
import numpy as np

df = pd.DataFrame({
    'A': &#91;1, 2, np.nan, 4],
    'B': &#91;5, np.nan, 7, 8],
    'C': &#91;9, 10, 11, 12]
})

# Sprawdź brakujące wartości
print(df.isnull())
#        A      B      C
# 0  False  False  False
# 1  False   True  False
# 2   True  False  False
# 3  False  False  False

# Zlicz brakujące
print(df.isnull().sum())
# A    1
# B    1
# C    0

# Usuń wiersze z brakującymi
df_clean = df.dropna()
print(df_clean)

# Wypełnij brakujące wartością
df_filled = df.fillna(0)
print(df_filled)

# Wypełnij średnią
df&#91;'A'] = df&#91;'A'].fillna(df&#91;'A'].mean())
print(df)
</code></pre>



<h2 class="wp-block-heading">Zapisywanie danych</h2>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Imie': &#91;'Jan', 'Anna', 'Piotr'],
    'Wiek': &#91;25, 30, 28]
})

# Do CSV
df.to_csv('wynik.csv', index=False)  # index=False = bez numeru wiersza

# Do Excel
df.to_excel('wynik.xlsx', index=False, sheet_name='Dane')

# Do JSON
df.to_json('wynik.json', orient='records', indent=2)

print("Pliki zapisane!")
</code></pre>



<h2 class="wp-block-heading">Praktyczne przykłady</h2>



<h3 class="wp-block-heading">Przykład 1: Analiza sprzedaży</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

# Dane sprzedażowe
sprzedaz = pd.DataFrame({
    'Produkt': &#91;'Laptop', 'Mysz', 'Klawiatura', 'Laptop', 'Mysz'],
    'Cena': &#91;3000, 50, 200, 3000, 50],
    'Ilosc': &#91;2, 10, 5, 1, 15],
    'Miasto': &#91;'Warszawa', 'Kraków', 'Warszawa', 'Gdańsk', 'Kraków']
})

# Wartość sprzedaży
sprzedaz&#91;'Wartosc'] = sprzedaz&#91;'Cena'] * sprzedaz&#91;'Ilosc']

# Całkowita sprzedaż
print(f"Całkowita sprzedaż: {sprzedaz&#91;'Wartosc'].sum()} zł")

# Sprzedaż po produktach
po_produktach = sprzedaz.groupby('Produkt')&#91;'Wartosc'].sum()
print("\nSprzedaż po produktach:")
print(po_produktach)

# Najlepiej sprzedający się produkt
najlepszy = po_produktach.idxmax()
print(f"\nNajlepszy produkt: {najlepszy}")
</code></pre>



<h3 class="wp-block-heading">Przykład 2: Czyszczenie danych</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd
import numpy as np

# Dane z błędami
df = pd.DataFrame({
    'Imie': &#91;'Jan', 'ANNA', 'piotr', '  Ewa  '],
    'Wiek': &#91;25, 200, -5, 30],  # Błędne wartości
    'Email': &#91;'jan@test.com', 'invalid', 'piotr@test.com', 'ewa@test.com']
})

print("PRZED czyszczeniem:")
print(df)

# Normalizuj imiona
df&#91;'Imie'] = df&#91;'Imie'].str.strip().str.title()

# Popraw wiek (ustal realistyczne granice)
df.loc&#91;(df&#91;'Wiek'] &lt; 0) | (df&#91;'Wiek'] &gt; 120), 'Wiek'] = np.nan
df&#91;'Wiek'] = df&#91;'Wiek'].fillna(df&#91;'Wiek'].median())

# Waliduj email (prosty sposób)
df&#91;'Email_OK'] = df&#91;'Email'].str.contains('@')

print("\nPO czyszczeniu:")
print(df)
</code></pre>



<h3 class="wp-block-heading">Przykład 3: Analiza ocen uczniów</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

oceny = pd.DataFrame({
    'Uczen': &#91;'Jan', 'Anna', 'Piotr', 'Jan', 'Anna', 'Piotr'],
    'Przedmiot': &#91;'Matematyka', 'Matematyka', 'Matematyka', 
                  'Polski', 'Polski', 'Polski'],
    'Ocena': &#91;4, 5, 3, 5, 4, 4]
})

# Średnia po uczniach
srednie_uczniow = oceny.groupby('Uczen')&#91;'Ocena'].mean()
print("Średnie uczniów:")
print(srednie_uczniow)

# Średnia po przedmiotach
srednie_przedmiotow = oceny.groupby('Przedmiot')&#91;'Ocena'].mean()
print("\nŚrednie przedmiotów:")
print(srednie_przedmiotow)

# Najlepszy uczeń
najlepszy = srednie_uczniow.idxmax()
print(f"\nNajlepszy uczeń: {najlepszy} (średnia: {srednie_uczniow.max():.2f})")

# Tabela przestawna
pivot = oceny.pivot_table(
    values='Ocena',
    index='Uczen',
    columns='Przedmiot',
    aggfunc='mean'
)
print("\nTabela przestawna:")
print(pivot)
</code></pre>



<h3 class="wp-block-heading">Przykład 4: Łączenie danych</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

# Dane uczniów
uczniowie = pd.DataFrame({
    'ID': &#91;1, 2, 3],
    'Imie': &#91;'Jan', 'Anna', 'Piotr']
})

# Dane ocen
oceny = pd.DataFrame({
    'ID_ucznia': &#91;1, 1, 2, 3],
    'Przedmiot': &#91;'Matematyka', 'Polski', 'Matematyka', 'Polski'],
    'Ocena': &#91;4, 5, 5, 3]
})

# Połącz (merge) - jak JOIN w SQL
polaczone = pd.merge(uczniowie, oceny, 
                      left_on='ID', 
                      right_on='ID_ucznia')

print(polaczone)
#    ID  Imie  ID_ucznia   Przedmiot  Ocena
# 0   1   Jan          1  Matematyka      4
# 1   1   Jan          1      Polski      5
# 2   2  Anna          2  Matematyka      5
# 3   3 Piotr          3      Polski      3
</code></pre>



<h2 class="wp-block-heading">Pandas &#8211; przydatne metody</h2>



<h3 class="wp-block-heading">Unikalne wartości</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Miasto': &#91;'Warszawa', 'Kraków', 'Warszawa', 'Gdańsk', 'Kraków']
})

# Unikalne wartości
print(df&#91;'Miasto'].unique())
# &#91;'Warszawa' 'Kraków' 'Gdańsk']

# Liczba unikalnych
print(df&#91;'Miasto'].nunique())  # 3

# Zlicz wystąpienia
print(df&#91;'Miasto'].value_counts())
# Warszawa    2
# Kraków      2
# Gdańsk      1
</code></pre>



<h3 class="wp-block-heading">Zastosuj funkcję</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Liczba': &#91;1, 2, 3, 4, 5]
})

# apply() - zastosuj funkcję do każdego elementu
df&#91;'Kwadrat'] = df&#91;'Liczba'].apply(lambda x: x ** 2)
print(df)

# apply() z własną funkcją
def klasyfikuj(x):
    if x &lt; 3:
        return 'Mała'
    else:
        return 'Duża'

df&#91;'Kategoria'] = df&#91;'Liczba'].apply(klasyfikuj)
print(df)
</code></pre>



<h3 class="wp-block-heading">Zastąp wartości</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import pandas as pd

df = pd.DataFrame({
    'Ocena': &#91;'A', 'B', 'C', 'A', 'B']
})

# Zamień wartości
mapping = {'A': 5, 'B': 4, 'C': 3}
df&#91;'Ocena_numeryczna'] = df&#91;'Ocena'].replace(mapping)
print(df)
</code></pre>



<h2 class="wp-block-heading">Podsumowanie</h2>



<p class="wp-block-paragraph"><strong>Format CSV:</strong></p>



<ul class="wp-block-list">
<li>Prosty format tabelaryczny</li>



<li>Moduł <code class="prettyprint lang-sql" style="font-size: 0.85em;">csv</code> do odczytu/zapisu</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">csv.reader()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">csv.DictReader()</code></li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">csv.writer()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">csv.DictWriter()</code></li>
</ul>



<p class="wp-block-paragraph"><strong>Pandas &#8211; podstawy:</strong></p>



<ul class="wp-block-list">
<li><strong>Series</strong> &#8211; jednowymiarowa</li>



<li><strong>DataFrame</strong> &#8211; dwuwymiarowa tabela</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">pd.read_csv()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">pd.read_excel()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">pd.read_json()</code></li>
</ul>



<p class="wp-block-paragraph"><strong>Operacje DataFrame:</strong></p>



<ul class="wp-block-list">
<li>Podgląd: <code class="prettyprint lang-sql" style="font-size: 0.85em;">head()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">tail()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">info()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">describe()</code></li>



<li>Dostęp: <code class="prettyprint lang-sql" style="font-size: 0.85em;">df['kolumna']</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">df.iloc[]</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">df.loc[]</code></li>



<li>Filtrowanie: <code class="prettyprint lang-sql" style="font-size: 0.85em;">df[df['kolumna'] > wartość]</code></li>



<li>Sortowanie: <code class="prettyprint lang-sql" style="font-size: 0.85em;">sort_values()</code></li>



<li>Grupowanie: <code class="prettyprint lang-sql" style="font-size: 0.85em;">groupby()</code></li>
</ul>



<p class="wp-block-paragraph"><strong>Brakujące dane:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">isnull()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">dropna()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">fillna()</code></li>
</ul>



<p class="wp-block-paragraph"><strong>Zapis:</strong></p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">to_csv()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">to_excel()</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">to_json()</code></li>
</ul>



<p class="wp-block-paragraph"><strong>Zastosowania:</strong></p>



<ul class="wp-block-list">
<li>Analiza sprzedaży</li>



<li>Czyszczenie danych</li>



<li>Raporty i statystyki</li>



<li>Przygotowanie danych do wizualizacji</li>
</ul>



<h1 class="wp-block-heading">Ćwiczenia &#8211; CSV i Pandas</h1>



<h2 class="wp-block-heading">Moduł csv</h2>



<ol class="wp-block-list">
<li>Stwórz plik CSV z danymi 5 osób (imię, nazwisko, wiek, miasto).</li>



<li>Wczytaj plik CSV i wyświetl wszystkie dane.</li>



<li>Wczytaj CSV jako słowniki (DictReader) i wyświetl.</li>



<li>Dodaj nową osobę do istniejącego pliku CSV.</li>



<li>Policz ile osób jest z konkretnego miasta.</li>



<li>Znajdź najstarszą osobę w pliku CSV.</li>



<li>Wyfiltruj osoby starsze niż 25 lat i zapisz do nowego CSV.</li>



<li>Stwórz CSV z danymi produktów (nazwa, cena, ilość).</li>



<li>Oblicz wartość magazynu (cena × ilość) i zapisz do nowego CSV.</li>



<li>Wczytaj CSV z różnym separatorem (średnik).</li>
</ol>



<h2 class="wp-block-heading">Pandas &#8211; podstawy</h2>



<ol start="11" class="wp-block-list">
<li>Stwórz DataFrame z danymi 3 osób (słownik).</li>



<li>Stwórz DataFrame z listy list.</li>



<li>Wyświetl pierwsze 3 wiersze DataFrame.</li>



<li>Wyświetl ostatnie 2 wiersze DataFrame.</li>



<li>Wyświetl informacje o DataFrame (info()).</li>



<li>Wyświetl statystyki opisowe (describe()).</li>



<li>Wyświetl nazwy kolumn DataFrame.</li>



<li>Wyświetl wymiary DataFrame (shape).</li>



<li>Wyświetl typy danych kolumn (dtypes).</li>



<li>Stwórz Series z listy liczb.</li>
</ol>



<h2 class="wp-block-heading">Wczytywanie danych</h2>



<ol start="21" class="wp-block-list">
<li>Wczytaj plik CSV do DataFrame.</li>



<li>Wczytaj CSV bez nagłówków i dodaj własne.</li>



<li>Wczytaj tylko pierwsze 10 wierszy z CSV.</li>



<li>Wczytaj CSV z separatorem średnikowym.</li>



<li>Wczytaj plik Excel do DataFrame.</li>
</ol>



<h2 class="wp-block-heading">Dostęp do danych</h2>



<ol start="26" class="wp-block-list">
<li>Wyświetl pojedynczą kolumnę DataFrame.</li>



<li>Wyświetl dwie wybrane kolumny DataFrame.</li>



<li>Wyświetl pierwszy wiersz DataFrame (iloc).</li>



<li>Wyświetl wiersze od 2 do 5 (iloc).</li>



<li>Wyświetl konkretną komórkę DataFrame.</li>
</ol>



<h2 class="wp-block-heading">Filtrowanie</h2>



<ol start="31" class="wp-block-list">
<li>Wyfiltruj osoby starsze niż 25 lat.</li>



<li>Wyfiltruj osoby z konkretnego miasta.</li>



<li>Wyfiltruj osoby młodsze niż 30 AND z Warszawy.</li>



<li>Wyfiltruj osoby starsze niż 25 OR z Krakowa.</li>



<li>Wyfiltruj osoby z listy miast (isin).</li>



<li>Wyfiltruj wiersze gdzie pensja > 5000.</li>



<li>Znajdź osoby których imię zaczyna się na 'A&#8217;.</li>



<li>Wyfiltruj produkty droższe niż 100 zł.</li>



<li>Znajdź zamówienia z ostatniego miesiąca.</li>



<li>Wyfiltruj niepuste wartości w kolumnie.</li>
</ol>



<h2 class="wp-block-heading">Dodawanie i usuwanie</h2>



<ol start="41" class="wp-block-list">
<li>Dodaj nową kolumnę do DataFrame.</li>



<li>Oblicz nową kolumnę na podstawie istniejącej (np. wiek + 10).</li>



<li>Usuń kolumnę z DataFrame.</li>



<li>Usuń wiersz po indeksie.</li>



<li>Zmień nazwę kolumny (rename).</li>
</ol>



<h2 class="wp-block-heading">Sortowanie</h2>



<ol start="46" class="wp-block-list">
<li>Posortuj DataFrame po wieku (rosnąco).</li>



<li>Posortuj DataFrame po imieniu (alfabetycznie).</li>



<li>Posortuj DataFrame po wieku (malejąco).</li>



<li>Posortuj po dwóch kolumnach (wiek, pensja).</li>



<li>Posortuj indeks DataFrame.</li>
</ol>



<h2 class="wp-block-heading">Grupowanie i agregacja</h2>



<ol start="51" class="wp-block-list">
<li>Zgrupuj po mieście i oblicz średni wiek.</li>



<li>Zgrupuj po kategorii produktu i oblicz sumę sprzedaży.</li>



<li>Policz ile osób jest w każdym mieście (size).</li>



<li>Zgrupuj i oblicz min, max, mean dla pensji.</li>



<li>Stwórz tabelę przestawną (pivot_table).</li>
</ol>



<h2 class="wp-block-heading">Brakujące dane</h2>



<ol start="56" class="wp-block-list">
<li>Stwórz DataFrame z brakującymi wartościami (np.nan).</li>



<li>Sprawdź które wiersze mają brakujące dane (isnull).</li>



<li>Policz brakujące wartości w każdej kolumnie.</li>



<li>Usuń wiersze z brakującymi wartościami (dropna).</li>



<li>Wypełnij brakujące wartości zerem (fillna).</li>



<li>Wypełnij brakujące wartości średnią kolumny.</li>



<li>Usuń kolumny z więcej niż 50% braków.</li>



<li>Wykryj duplikaty wierszy (duplicated).</li>



<li>Usuń duplikaty (drop_duplicates).</li>



<li>Zastąp wartości None średnią.</li>
</ol>



<h2 class="wp-block-heading">Zapisywanie</h2>



<ol start="66" class="wp-block-list">
<li>Zapisz DataFrame do CSV bez indeksu.</li>



<li>Zapisz DataFrame do Excel.</li>



<li>Zapisz DataFrame do JSON.</li>



<li>Zapisz tylko wybrane kolumny do CSV.</li>



<li>Zapisz DataFrame z innym separatorem.</li>
</ol>



<h2 class="wp-block-heading">Operacje na tekście</h2>



<ol start="71" class="wp-block-list">
<li>Zamień wszystkie imiona na wielkie litery (str.upper).</li>



<li>Usuń spacje z początku i końca (str.strip).</li>



<li>Sprawdź czy email zawiera '@&#8217; (str.contains).</li>



<li>Podziel kolumnę na dwie (str.split).</li>



<li>Wyciągnij pierwsze 3 znaki z tekstu (str[:3]).</li>
</ol>



<h2 class="wp-block-heading">Unikalne wartości</h2>



<ol start="76" class="wp-block-list">
<li>Wyświetl unikalne wartości kolumny 'Miasto&#8217;.</li>



<li>Policz liczbę unikalnych miast (nunique).</li>



<li>Zlicz wystąpienia każdej wartości (value_counts).</li>



<li>Znajdź najczęściej występującą wartość.</li>



<li>Usuń duplikaty z kolumny.</li>
</ol>



<h2 class="wp-block-heading">Apply i transform</h2>



<ol start="81" class="wp-block-list">
<li>Zastosuj funkcję lambda do kolumny (apply).</li>



<li>Stwórz kategorię na podstawie wieku (apply).</li>



<li>Zastosuj własną funkcję do DataFrame.</li>



<li>Oblicz nową kolumnę używając apply.</li>



<li>Zamień wartości używając replace.</li>
</ol>



<h2 class="wp-block-heading">Łączenie danych</h2>



<ol start="86" class="wp-block-list">
<li>Połącz dwa DataFrame wertykalnie (concat).</li>



<li>Połącz dwa DataFrame horyzontalnie (concat axis=1).</li>



<li>Wykonaj merge (inner join) dwóch DataFrame.</li>



<li>Wykonaj left join.</li>



<li>Wykonaj outer join.</li>
</ol>



<h2 class="wp-block-heading">Zadania analityczne</h2>



<ol start="91" class="wp-block-list">
<li>Wczytaj dane sprzedażowe i oblicz całkowitą wartość sprzedaży.</li>



<li>Znajdź 5 najlepiej sprzedających się produktów.</li>



<li>Oblicz średnią cenę produktów w każdej kategorii.</li>



<li>Stwórz raport miesięczny sprzedaży.</li>



<li>Znajdź klientów którzy wydali najwięcej.</li>



<li>Oblicz procent sprzedaży dla każdego produktu.</li>



<li>Wyfiltruj zamówienia z ostatnich 30 dni.</li>



<li>Znajdź produkty których nie ma na stanie.</li>



<li>Oblicz średnią ocen dla każdego produktu.</li>



<li>Stwórz ranking najlepszych sprzedawców.</li>
</ol>



<h2 class="wp-block-heading">Zadania kompleksowe</h2>



<ol start="101" class="wp-block-list">
<li>Wczytaj dane uczniów i ocen, oblicz średnie, znajdź najlepszego.</li>



<li>Analiza danych o pracownikach: średnia pensja, najstarszy, podział po działach.</li>



<li>Dane sprzedażowe: najlepszy miesiąc, najbardziej dochodowy produkt, trend.</li>



<li>Czyszczenie danych: usuń duplikaty, wypełnij braki, normalizuj tekst.</li>



<li>Analiza ankiety: zlicz odpowiedzi, procenty, wykres rozkładu.</li>



<li>Połącz dane z dwóch źródeł (merge) i stwórz raport.</li>



<li>Analiza logów: zlicz błędy, najczęstsze typy, wykres czasowy.</li>



<li>Dane finansowe: oblicz przychody, koszty, zysk netto.</li>



<li>Segmentacja klientów: podziel na grupy wiekowe, oblicz statystyki.</li>



<li>Time series: analiza sprzedaży w czasie, trendy, sezonowość.</li>
</ol>
<p>Artykuł <a href="https://kamakaczmarek.net/18-python-analiza-danych-csv-i-pandas/">18. Python &#8211; Analiza danych: CSV i Pandas</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>17. Python &#8211; bazy danych &#8211; sqlite</title>
		<link>https://kamakaczmarek.net/17-python-bazy-danych-sqlite/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Tue, 02 Jun 2026 12:38:28 +0000</pubDate>
				<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=4448</guid>

					<description><![CDATA[<p>Czym jest SQLite3? SQLite3 to lekka, wbudowana relacyjna baza danych SQL Nie wymaga osobnego serwera &#8211; cała baza to jeden plik Python ma wbudowany moduł sqlite3 &#8211; nie trzeba nic instalować Idealna do nauki, prototypów i małych/średnich aplikacji SQLite3 to lekka, wbudowana relacyjna baza danych SQL Nie wymaga osobnego serwera &#8211; cała baza to jeden [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/17-python-bazy-danych-sqlite/">17. Python &#8211; bazy danych &#8211; sqlite</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading"><strong>Czym jest SQLite3?</strong></h2>



<ul>
<li>SQLite3 to lekka, wbudowana relacyjna baza danych SQL</li>
<li>Nie wymaga osobnego serwera &#8211; cała baza to jeden plik</li>
<li>Python ma wbudowany moduł sqlite3 &#8211; nie trzeba nic instalować</li>
<li>Idealna do nauki, prototypów i małych/średnich aplikacji</li>
</ul>



<p class="wp-block-paragraph">SQLite3 to lekka, wbudowana relacyjna baza danych SQL</p>



<p class="wp-block-paragraph">Nie wymaga osobnego serwera &#8211; cała baza to jeden plik</p>



<p class="wp-block-paragraph">Python ma wbudowany moduł sqlite3 &#8211; nie trzeba nic instalować</p>



<p class="wp-block-paragraph">Idealna do nauki, prototypów i małych/średnich aplikacji</p>



<h3 class="wp-block-heading"><strong>Podstawowe pojęcia:</strong></h3>



<p class="wp-block-paragraph">Połączenie (Connection) &#8211; łącze z plikiem bazy danych</p>



<p class="wp-block-paragraph">Kursor (Cursor) &#8211; obiekt do wykonywania poleceń SQL</p>



<p class="wp-block-paragraph">Commit &#8211; zatwierdzenie zmian w bazie</p>



<p>Rollback &#8211; cofnięcie niezatwierdzonych zmian</p>



<h3 class="wp-block-heading"><strong>Analogia ze świata rzeczywistego:</strong></h3>



<p>Wyobraź sobie, że:</p>
<ul>
<li>Baza danych = Biblioteka pełna książek</li>
<li>Connection (połączenie) = Karta biblioteczna (pozwala Ci wejść do biblioteki)</li>
<li>Cursor (kursor) = Bibliotekarz, który wykonuje dla Ciebie konkretne zadania</li>
<li>Dlaczego potrzebujemy kursora?</li>
</ul>
<p>Nie możesz bezpośrednio rozmawiać z bazą danych! Potrzebujesz &#8222;pośrednika&#8221;, który:</p>
<ul>
<li>Zaniesie Twoje polecenie do bazy danych</li>
<li>Wykona operację (znajdzie dane, doda coś, usunie)</li>
<li>Przyniesie Ci wyniki</li>
</ul>
<p>Tym pośrednikiem jest właśnie KURSOR.</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sqlite3
# KROK 1: Otwierasz drzwi do biblioteki (połączenie)
conn = sqlite3.connect('mojabaza.db')
# Teraz jesteś w bibliotece, ale jeszcze nic nie możesz zrobić
# KROK 2: Wzywasz bibliotekarza (tworzysz kursor)
cursor = conn.cursor()
# Teraz masz "pomocnika", któremu możesz wydawać polecenia
# KROK 3: Wydajesz polecenie bibliotekarzowi
cursor.execute('SELECT * FROM ksiazki WHERE autor LIKE ?', ('%Tolkien%',))
# Bibliotekarz idzie, szuka książek Tolkiena
# KROK 4: Bibliotekarz przynosi Ci wyniki
wyniki = cursor.fetchall()
print(wyniki)
# KROK 5: Wychodzisz z biblioteki
conn.close()</code></pre>



<h2 class="wp-block-heading"><strong>PRZYKŁADY PRAKTYCZNE</strong></h2>



<p class="wp-block-paragraph">Przykład 1: Podstawowe operacje CRUD</p>



<p>tworzymy plik o nazwie crud_basics.py</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sqlite3
# Połączenie z bazą (tworzy plik jeśli nie istnieje)
conn = sqlite3.connect('mojabaza.db')
cursor = conn.cursor()
# CREATE - Tworzenie tabeli
cursor.execute('''
CREATE TABLE IF NOT EXISTS pracownicy (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    imie TEXT NOT NULL,
    nazwisko TEXT NOT NULL,
    wiek INTEGER,
    wynagrodzenie REAL
)
''')
# INSERT - Wstawianie pojedynczego rekordu
cursor.execute('''
    INSERT INTO pracownicy (imie, nazwisko, wiek, wynagrodzenie)
    VALUES (?, ?, ?, ?)
''', ('Jan', 'Kowalski', 35, 5500.50))
# INSERT - Wstawianie wielu rekordów
dane = &#91;
    ('Anna', 'Nowak', 28, 6200.00),
    ('Kacper', 'Malinowski', 22, 4100.75),
    ('Maria', 'Wiśniewska', 45, 7800.00)
]
cursor.executemany('''
    INSERT INTO pracownicy (imie, nazwisko, wiek, wynagrodzenie)
    VALUES (?, ?, ?, ?)
''', dane)
# Zatwierdzenie zmian
conn.commit()
# SELECT - Pobieranie wszystkich danych
cursor.execute('SELECT * FROM pracownicy')
wyniki = cursor.fetchall()
print("Wszyscy pracownicy:")
for wiersz in wyniki:
    print(wiersz)
# SELECT - Pobieranie z warunkiem
cursor.execute('SELECT imie, nazwisko FROM pracownicy WHERE wiek &gt; ?', (30,))
starsi = cursor.fetchall()
print("\nPracownicy powyżej 30 lat:")
for osoba in starsi:
    print(f"{osoba&#91;0]} {osoba&#91;1]}")
# UPDATE - Aktualizacja danych
cursor.execute('''
    UPDATE pracownicy
    SET wynagrodzenie = wynagrodzenie * 1.1
    WHERE wiek &lt; 30
''')
conn.commit()
# DELETE - Usuwanie danych
cursor.execute('DELETE FROM pracownicy WHERE id = ?', (1,))
conn.commit()
# Zamknięcie połączenia
conn.close()</code></pre>



<p class="wp-block-paragraph">Przykład 2: Context Manager (zalecane podejście)</p>



<p>tworzymy plik o nazwie context_manager.py</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sqlite3
 # Automatyczne zarządzanie połączeniem
with sqlite3.connect('sklep.db') as conn:
    cursor = conn.cursor()
   
    # Tworzenie tabeli produktów
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS produkty (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        nazwa TEXT NOT NULL,
        cena REAL NOT NULL,
        ilosc INTEGER DEFAULT 0
    )
    ''')
   
    # Dane są automatycznie commitowane przy wyjściu z bloku 'with'
    cursor.execute('INSERT INTO produkty (nazwa, cena, ilosc) VALUES (?, ?, ?)',
                   ('Laptop', 3500.00, 5))
   
    # Pobieranie z użyciem row_factory dla dostępu jak do słownika
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM produkty')
   
    for row in cursor:
        print(f"Produkt: {row&#91;'nazwa']}, Cena: {row&#91;'cena']} zł")</code></pre>



<p class="wp-block-paragraph">Przykład 3: Zaawansowane zapytania</p>



<p class="wp-block-paragraph">tworzymy plik o nazwie advanced_queries.py</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sqlite3
 with sqlite3.connect('firma.db') as conn:
    cursor = conn.cursor()
   
    # Tworzenie dwóch powiązanych tabel
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS dzialy (
        id INTEGER PRIMARY KEY,
        nazwa TEXT NOT NULL
    )
    ''')
   
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS pracownicy (
        id INTEGER PRIMARY KEY,
        imie TEXT NOT NULL,
        nazwisko TEXT NOT NULL,
        dzial_id INTEGER,
        FOREIGN KEY (dzial_id) REFERENCES dzialy(id)
    )
    ''')
   
    # Wstawienie działów
    dzialy = &#91;(1, 'IT'), (2, 'HR'), (3, 'Sprzedaż')]
    cursor.executemany('INSERT OR IGNORE INTO dzialy VALUES (?, ?)', dzialy)
   
    # Wstawienie pracowników
    pracownicy = &#91;
        ('Jan', 'Kowalski', 1),
        ('Anna', 'Nowak', 2),
        ('Piotr', 'Wiśniewski', 1)
    ]
    cursor.executemany('INSERT INTO pracownicy (imie, nazwisko, dzial_id) VALUES (?, ?, ?)', pracownicy)
   
    # JOIN - łączenie tabel
    cursor.execute('''
    SELECT p.imie, p.nazwisko, d.nazwa
    FROM pracownicy p
    JOIN dzialy d ON p.dzial_id = d.id
    WHERE d.nazwa = 'IT'
    ''')
   
    print("Pracownicy działu IT:")
    for row in cursor.fetchall():
        print(f"{row&#91;0]} {row&#91;1]} - {row&#91;2]}")
   
    # GROUP BY - agregacja
    cursor.execute('''
    SELECT d.nazwa, COUNT(p.id) as liczba_pracownikow
    FROM dzialy d
    LEFT JOIN pracownicy p ON d.id = p.dzial_id
    GROUP BY d.nazwa
    ''')
   
    print("\nLiczba pracowników w działach:")
    for row in cursor.fetchall():
        print(f"{row&#91;0]}: {row&#91;1]}")</code></pre>



<p class="wp-block-paragraph">Przykład 4: Obsługa błędów</p>



<p>tworzymy plik o nazwie error_handling.py</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sqlite3
 try:
    with sqlite3.connect('test.db') as conn:
        cursor = conn.cursor()
       
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY,
            email TEXT UNIQUE NOT NULL
        )
        ''')
       
        # Próba wstawienia duplikatu
        cursor.execute('INSERT INTO users (email) VALUES (?)', ('jan@example.com',))
        cursor.execute('INSERT INTO users (email) VALUES (?)', ('jan@example.com',))
       
except sqlite3.IntegrityError as e:
    print(f"Błąd integralności danych: {e}")
except sqlite3.OperationalError as e:
    print(f"Błąd operacyjny: {e}")
except sqlite3.Error as e:
    print(f"Błąd bazy danych: {e}")</code></pre>



<h4 class="wp-block-heading">Typy wyjątków:</h4>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><span style="font-size: 12pt;">sqlite3.Warning</span></td><td><span style="font-size: 12pt;">Ostrzeżenie</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.Error</span></td><td><span style="font-size: 12pt;">Bazowy wyjątek dla wszystkich błędów</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.InterfaceError</span></td><td><span style="font-size: 12pt;">Błąd interfejsu bazy</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.DatabaseError</span></td><td><span style="font-size: 12pt;">Błąd związany z bazą</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.DataError</span></td><td><span style="font-size: 12pt;">Błąd danych (np. dzielenie przez zero)</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.OperationalError</span></td><td><span style="font-size: 12pt;">Błąd operacyjny (np. brak tabeli)</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.IntegrityError</span></td><td><span style="font-size: 12pt;">Naruszenie integralności (np. UNIQUE)</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.InternalError</span></td><td><span style="font-size: 12pt;">Błąd wewnętrzny SQLite</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.ProgrammingError</span></td><td><span style="font-size: 12pt;">Błąd programowania (np. zły SQL)</span></td></tr><tr><td><span style="font-size: 12pt;">sqlite3.NotSupportedError</span></td><td><span style="font-size: 12pt;">Nieobsługiwana operacja</span></td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Przykład 5:</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">#https://pypi.org/project/sqlite-database/
#shift + ctrl + p -&gt; wpisujemy sqlite i wybieramy naszą bazę (test.db) - po lewej na dole pokazuje się dostęp do bazy
#tworzymy połączenie z bazą
import sqlite3

conn = sqlite3.connect('test1.db') #tworzymy połączenie z bazą danych przechowywaną w pliku na dysku (test.db, nazwa pliku jest dowolona) lub w pamięci, jeśli podamy ':memory:'
conn.row_factory = sqlite3.Row #dostęp do kolumn (pól tabel) nie tylko przez indeksy, ale również przez nazwy
db = conn.cursor() #obiekt kursora do wykonywania operacji na bazie danych
print(db)
#tworzymy tabele
#pojedyncze polecenia SQL-a wykonujemy za pomocą metody .execute()
db.execute("DROP TABLE IF EXISTS klasa;")

db.execute("""
    CREATE TABLE IF NOT EXISTS klasa (
        id INTEGER PRIMARY KEY ASC,
        nazwa varchar(250) NOT NULL,
        profil varchar(250) DEFAULT ''
    )""")

#wiele instrukcji wykonujemy za pomocą metody .executescript()
db.executescript("""
    DROP TABLE IF EXISTS uczen;
    CREATE TABLE IF NOT EXISTS uczen (
        id INTEGER PRIMARY KEY ASC,
        imie varchar(250) NOT NULL,
        nazwisko varchar(250) NOT NULL,
        klasa_id INTEGER NOT NULL,
        FOREIGN KEY(klasa_id) REFERENCES klasa(id)
    )""")
#po uruchomieniu kodu baza pojawi się w katalogu

# wstawiamy jeden rekord danych
db.execute('INSERT INTO klasa VALUES(NULL, ?, ?);', ('1A', 'matematyczny'))
db.execute('INSERT INTO klasa VALUES(NULL, ?, ?);', ('1B', 'humanistyczny'))

#Polecenia CREATE TABLE (a także DROP TABLE, ALTER TABLE) są traktowane przez SQLite jako DDL (Data Definition Language) i są automatycznie zatwierdzane — SQLite implicitnie wykonuje COMMIT po każdej takiej operacji.Ale już INSERT, UPDATE, DELETE tego nie robią automatycznie: Te operacje to DML (Data Manipulation Language) i wymagają jawnego conn.commit(), jeśli chcesz, żeby zmiany zostały zapisane na stałe.
conn.commit()

# Wyświetlamy zawartość tabeli klasa
print("Zawartość tabeli 'klasa':")
for row in db.execute('SELECT * FROM klasa'):
    print(dict(row))  # wypisujemy jako słownik, żeby było czytelniej


# wykonujemy zapytanie SQL, które pobierze id klasy "1A" z tabeli "klasa".
db.execute('SELECT id FROM klasa WHERE nazwa = ?', ('1A',))
klasa_id = db.fetchone()&#91;0]

# tupla "uczniowie" zawiera tuple z danymi poszczególnych uczniów
uczniowie = (
    (None, 'Tomasz', 'Nowak', klasa_id),
    (None, 'Jan', 'Kos', klasa_id),
    (None, 'Piotr', 'Kowalski', klasa_id)
)

# wstawiamy wiele rekordów
db.executemany('INSERT INTO uczen VALUES(?,?,?,?)', uczniowie)



# pobieranie danych z bazy
def czytajdane():
    """Funkcja pobiera i wyświetla dane z bazy."""
    #poniżej potrójny cudzysłów został wykorzystany do zapisania długielo zapytania SQL
    db.execute(
        """
        SELECT uczen.id,imie,nazwisko,nazwa FROM uczen,klasa
        WHERE uczen.klasa_id=klasa.id
        """)
    
    uczniowie = db.fetchall()
    for uczen in uczniowie:
        print(uczen&#91;'id'], uczen&#91;'imie'], uczen&#91;'nazwisko'], uczen&#91;'nazwa'])
    print()    

czytajdane()

# zmiana klasy ucznia o identyfikatorze 2res
db.execute('SELECT id FROM klasa WHERE nazwa = ?', ('1B',))
klasa_id = db.fetchone()&#91;0]
db.execute('UPDATE uczen SET klasa_id=? WHERE id=?', (klasa_id, 2))

# usunięcie ucznia o identyfikatorze 3
# db.execute('DELETE FROM uczen WHERE id=?', (3,))

czytajdane()

# zatwierdzamy zmiany w bazie
conn.commit()
# Zamykamy połączenie
conn.close()</code></pre>



<h2 class="wp-block-heading">ĆWICZENIA</h2>



<p><strong>Ćwiczenie 1: Biblioteka książek (Podstawowe)</strong></p>
<p>Utwórz bazę danych biblioteki z tabelą ksiażki zawierającą:</p>
<p>id (PRIMARY KEY)</p>
<p>tytul (TEXT)</p>
<p>autor (TEXT)</p>
<p>rok_wydania (INTEGER)</p>
<p>dostepna (INTEGER &#8211; 0 lub 1)</p>
<p>&nbsp;</p>
<p><em><strong>Zadania:</strong></em></p>
<p>Dodaj 5 książek do tabeli</p>
<p>Wyświetl wszystkie książki wydane po 2000 roku</p>
<p>Oznacz książkę jako wypożyczoną (dostepna = 0)</p>
<p>Policz ile jest dostępnych książek</p>
<p>&nbsp;</p>
<p><strong>Ćwiczenie 2: Sklep internetowy (Średniozaawansowane)</strong></p>
<p>Stwórz system zarządzania produktami z bazą o nazwie sklep.db. Utwórz dwie tabele: kategorie i produkty.</p>
<p>Tabela kategorie: id, nazwa</p>
<p>Tabela produkty: id, nazwa, cena, kategoria_id, stan_magazynowy</p>
<p>Utwórz obie tabele z odpowiednimi kluczami obcymi</p>
<p>&nbsp;</p>
<p><em><strong>Zadania:</strong></em></p>
<p>Dodaj 3 kategorie (Elektronika, Odzież, Książki)</p>
<p>Dodaj po 3 produkty do każdej kategorii</p>
<p>Napisz zapytanie wyświetlające produkty wraz z nazwą kategorii</p>
<p>Oblicz średnią cenę produktów w każdej kategorii</p>
<p>Znajdź najdroższy produkt w bazie</p>
<p>&nbsp;</p>
<p><strong>Ćwiczenie 3: System zarządzania studentami z relacjami wiele-do-wielu: (Zaawansowane)</strong></p>
<p>Utwórz bazę o nazwie uczelnia.db z trzema tabelami: studenci, kursy, zapisy (tabela łącząca)</p>
<p>Utwórz wszystkie trzy tabele z odpowiednimi kluczami obcymi i ograniczeniem UNIQUE(student_id, kurs_id)</p>
<p>Zaimplementuj funkcje:</p>
<p>dodaj_studenta(imie, nazwisko, rok_studiow)</p>
<p>dodaj_kurs(nazwa, punkty_ects)</p>
<p>zapisz_na_kurs(student_id, kurs_id, ocena)</p>
<p>wyswietl_kursy_studenta(student_id)</p>
<p>oblicz_srednia_studenta(student_id)</p>
<p>Użyj transakcji do zapisania studenta na wiele kursów jednocześnie</p>



<h2 class="wp-block-heading">NAJWAŻNIEJSZE ZASADY</h2>



<p class="wp-block-paragraph">1. Bezpieczeństwo &#8211; SQL Injection</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">#ŹLE - podatne na SQL Injection
nazwa = input("Podaj nazwę: ")
cursor.execute(f"SELECT * FROM users WHERE name = '{nazwa}'")
 
#DOBRZE - używaj parametrów
nazwa = input("Podaj nazwę: ")
cursor.execute("SELECT * FROM users WHERE name = ?", (nazwa,))</code></pre>



<p class="wp-block-paragraph">2. Zawsze używaj commit()</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">cursor.execute('INSERT INTO ...')
conn.commit()  # BEZ TEGO dane nie zostaną zapisane!</code></pre>



<p class="wp-block-paragraph">3. Zamykaj połączenia</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">#Sposób 1: Manualnie
conn = sqlite3.connect('db.db')
... operacje ...
conn.close()
 
#Sposób 2: Context manager (zalecane)
with sqlite3.connect('db.db') as conn:
    ... operacje ...
    Automatyczne zamknięcie</code></pre>



<h2 class="wp-block-heading">PRZYDATNE METODY</h2>



<figure class="wp-block-table has-small-font-size"><table class="has-fixed-layout"><tbody><tr><td>execute(sql, params)</td><td>Wykonuje pojedyncze polecenie SQL z opcjonalnymi parametrami</td></tr><tr><td>executemany(sql, seq_of_parameters)</td><td>Wstawia wiele rekordów</td></tr><tr><td>executescript(sql)</td><td>Wykonuje wiele poleceń SQL</td></tr><tr><td>fetchone()</td><td>Pobiera jeden wiersz</td></tr><tr><td>fetchall()</td><td>Pobiera wszystkie wiersze</td></tr><tr><td>fetchmany(n)</td><td>Pobiera n wierszy</td></tr><tr><td>lastrowid</td><td>ID ostatnio wstawionego rekordu</td></tr><tr><td>rowcount</td><td>Liczba zmienionych wierszy</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Dlaczego dwa kroki? (Connection + Cursor)</h2>



<p class="wp-block-paragraph">Dlaczego nie może być tak:</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">conn = sqlite3.connect('baza.db')
conn.execute('SELECT...')  # Czy to nie wystarczy?</code></pre>



<p class="wp-block-paragraph">Może być! Ale to jest skrót:</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">#Sposób 1: SKRÓT (Python robi to za Ciebie)
conn.execute('SELECT * FROM users')
 
# Sposób 2: PEŁNY (tak naprawdę działa)
cursor = conn.cursor()
cursor.execute('SELECT * FROM users')
 
# Python w skrócie automatycznie tworzy kursor, ale go nie widzisz!</code></pre>



<p>Możesz mieć WIELU BIBLIOTEKARZY naraz (wiele kursorów) i każdy może wykonywać różne zadania, ale wszyscy korzystają z tej samej karty bibliotecznej (połączenia). To pozwala na równoczesną pracę z bazą danych.</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">conn = sqlite3.connect('baza.db')
 
# Pierwszy bibliotekarz zajmuje się użytkownikami
cursor1 = conn.cursor()
cursor1.execute('SELECT * FROM users')
 
# Drugi bibliotekarz zajmuje się zamówieniami
cursor2 = conn.cursor()
cursor2.execute('SELECT * FROM orders')
 
# Każdy robi swoją robotę niezależnie!
users = cursor1.fetchall()
orders = cursor2.fetchall()
 
# Kursor "pamięta" wyniki swoich zapytań, więc możesz mieć wielu kursorów, a każdy z nich będzie miał swoje własne wyniki.
cursor = conn.cursor()
cursor.execute('SELECT * FROM users')
 
# Pobierasz wyniki STOPNIOWO
pierwszy = cursor.fetchone()   # Pobiera 1 wiersz
drugi = cursor.fetchone()      # Pobiera kolejny wiersz
reszta = cursor.fetchall()     # Pobiera wszystkie pozostałe
 
# Gdybyś użył conn.execute(), nie miałbyś takiej kontroli nad kursorami i wynikami.</code></pre>



<h3 class="wp-block-heading">Pamiętaj</h3>



<ul class="wp-block-list">
<li>pojedyncze polecenia SQL-a wykonujemy za pomocą metody .execute() np. <code class="prettyprint lang-sql" style="font-size: 0.85em;">DROP TABLE IF EXISTS uczen;</code></li>



<li>wiele instrukcji wykonujemy za pomocą metody .executescript() np. <code class="prettyprint lang-sql" style="font-size: 0.85em;">DROP TABLE IF EXISTS uczen; CREATE TABLE IF NOT EXISTS uczen (...);</code></li>



<li>dodanie wielu rekordów do tabeli wykonujemy za pomocą metody .executemany()</li>



<li>Polecenia CREATE TABLE (a także DROP TABLE, ALTER TABLE) oraz SELECT są traktowane przez SQLite jako DDL (Data Definition Language) i są automatycznie zatwierdzane — SQLite implicitnie wykonuje COMMIT po każdej takiej operacji.Ale już INSERT, UPDATE, DELETE tego nie robią automatycznie: Te operacje to DML (Data Manipulation Language) i wymagają jawnego conn.commit(), jeśli chcesz, żeby zmiany zostały zapisane na stałe.</li>
</ul>



<h2 class="wp-block-heading">ROZWIĄZANIA</h2>



<p class="wp-block-paragraph">Rozwiązanie ćwiczenia 1: Biblioteka książek</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sqlite3
 
with sqlite3.connect('biblioteka.db') as conn:
    c = conn.cursor()
   
    # 1. Tworzenie tabeli
    c.execute('''
    CREATE TABLE IF NOT EXISTS ksiazki (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        tytul TEXT NOT NULL,
        autor TEXT NOT NULL,
        rok_wydania INTEGER,
        dostepna INTEGER DEFAULT 1
    )
    ''')
   
    # 2. Dodawanie książek
    ksiazki = &#91;
        ('Władca Pierścieni', 'J.R.R. Tolkien', 1954, 1),
        ('Harry Potter', 'J.K. Rowling', 1997, 1),
        ('Wiedźmin', 'Andrzej Sapkowski', 1990, 1),
        ('Metro 2033', 'Dmitry Glukhovsky', 2005, 1),
        ('Kod Da Vinci', 'Dan Brown', 2003, 1)
    ]
    c.executemany('INSERT INTO ksiazki (tytul, autor, rok_wydania, dostepna) VALUES (?, ?, ?, ?)', ksiazki)
   
    # 3. Książki po 2000 roku
    print("Książki wydane po 2000 roku:")
    c.execute('SELECT tytul, autor, rok_wydania FROM ksiazki WHERE rok_wydania &gt; 2000')
    for row in c.fetchall():
        print(f"- {row&#91;0]} ({row&#91;1]}, {row&#91;2]})")
   
    # 4. Wypożyczenie książki
    c.execute('UPDATE ksiazki SET dostepna = 0 WHERE tytul = ?', ('Metro 2033',))
   
    # 5. Liczba dostępnych książek
    c.execute('SELECT COUNT(*) FROM ksiazki WHERE dostepna = 1')
    liczba = c.fetchone()&#91;0]
    print(f"\nDostępnych książek: {liczba}")
</code></pre>



<p class="wp-block-paragraph">Rozwiązanie ćwiczenia 2: Sklep internetowy</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sqlite3
 
with sqlite3.connect('sklep.db') as conn:
    c = conn.cursor()
   
    # 1. Tworzenie tabel
    c.execute('''
    CREATE TABLE IF NOT EXISTS kategorie (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        nazwa TEXT NOT NULL UNIQUE
    )
    ''')
   
    c.execute('''
    CREATE TABLE IF NOT EXISTS produkty (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        nazwa TEXT NOT NULL,
        cena REAL NOT NULL,
        kategoria_id INTEGER,
        stan_magazynowy INTEGER DEFAULT 0,
        FOREIGN KEY (kategoria_id) REFERENCES kategorie(id)
    )
    ''')
   
    # 2. Dodawanie kategorii
    kategorie = &#91;('Elektronika',), ('Odzież',), ('Książki',)]
    c.executemany('INSERT OR IGNORE INTO kategorie (nazwa) VALUES (?)', kategorie)
   
    # 3. Dodawanie produktów
    produkty = &#91;
        ('Laptop', 3500.00, 1, 10),
        ('Smartphone', 2200.00, 1, 15),
        ('Słuchawki', 450.00, 1, 25),
        ('Koszulka', 89.99, 2, 50),
        ('Spodnie', 199.99, 2, 30),
        ('Kurtka', 499.00, 2, 20),
        ('Python dla każdego', 59.99, 3, 100),
        ('Clean Code', 89.00, 3, 75),
        ('Algorytmy', 120.00, 3, 40)
    ]
    c.executemany('INSERT INTO produkty (nazwa, cena, kategoria_id, stan_magazynowy) VALUES (?, ?, ?, ?)', produkty)
   
    # 4. Produkty z kategoriami
    print("Produkty z kategoriami:")
    c.execute('''
    SELECT p.nazwa, p.cena, k.nazwa
    FROM produkty p
    JOIN kategorie k ON p.kategoria_id = k.id
    ORDER BY k.nazwa
    ''')
    for row in c.fetchall():
        print(f"{row&#91;0]} ({row&#91;2]}) - {row&#91;1]} zł")
   
    # 5. Średnia cena w kategoriach
    print("\nŚrednia cena w kategoriach:")
    c.execute('''
    SELECT k.nazwa, ROUND(AVG(p.cena), 2) as srednia
    FROM kategorie k
    JOIN produkty p ON k.id = p.kategoria_id
    GROUP BY k.nazwa
    ''')
    for row in c.fetchall():
        print(f"{row&#91;0]}: {row&#91;1]} zł")
   
    # 6. Najdroższy produkt
    c.execute('SELECT nazwa, cena FROM produkty ORDER BY cena DESC LIMIT 1')
    najdrozszy = c.fetchone()
    print(f"\nNajdroższy produkt: {najdrozszy&#91;0]} ({najdrozszy&#91;1]} zł)")</code></pre>



<p class="wp-block-paragraph">Rozwiązanie ćwiczenia 3: System zarządzania studentami</p>



<pre class="wp-block-code prettyprint has-small-font-size"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import sqlite3

class SystemStudentow:
    def __init__(self, db_name='uczelnia.db'):
        # Polaczenie z baza danych
        self.conn = sqlite3.connect(db_name)
        # Ustawienie row_factory dla dostepu do kolumn jak do slownika
        self.conn.row_factory = sqlite3.Row
        self._utworz_tabele()
    
    def _utworz_tabele(self):
        # Utworzenie kursora
        cursor = self.conn.cursor()
        
        # Tworzenie tabeli studenci
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS studenci (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            imie TEXT NOT NULL,
            nazwisko TEXT NOT NULL,
            rok_studiow INTEGER
        )
        ''')
        
        # Tworzenie tabeli kursy
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS kursy (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            nazwa TEXT NOT NULL,
            punkty_ects INTEGER
        )
        ''')
        
        # Tworzenie tabeli zapisy (relacja wiele-do-wielu)
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS zapisy (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            student_id INTEGER,
            kurs_id INTEGER,
            ocena REAL,
            FOREIGN KEY (student_id) REFERENCES studenci(id),
            FOREIGN KEY (kurs_id) REFERENCES kursy(id),
            UNIQUE(student_id, kurs_id)
        )
        ''')
        
        # Zatwierdzenie zmian
        self.conn.commit()
    
    def dodaj_studenta(self, imie, nazwisko, rok_studiow):
        cursor = self.conn.cursor()
        # Wstawienie studenta
        cursor.execute(
            'INSERT INTO studenci (imie, nazwisko, rok_studiow) VALUES (?, ?, ?)',
            (imie, nazwisko, rok_studiow)
        )
        self.conn.commit()
        # Zwrocenie ID dodanego rekordu
        return cursor.lastrowid
    
    def dodaj_kurs(self, nazwa, punkty_ects):
        cursor = self.conn.cursor()
        # Wstawienie kursu
        cursor.execute(
            'INSERT INTO kursy (nazwa, punkty_ects) VALUES (?, ?)',
            (nazwa, punkty_ects)
        )
        self.conn.commit()
        return cursor.lastrowid
    
    def zapisz_na_kurs(self, student_id, kurs_id, ocena=None):
        cursor = self.conn.cursor()
        try:
            # Wstawienie zapisu studenta na kurs
            cursor.execute(
                'INSERT INTO zapisy (student_id, kurs_id, ocena) VALUES (?, ?, ?)',
                (student_id, kurs_id, ocena)
            )
            self.conn.commit()
            return True
        except sqlite3.IntegrityError:
            print("Student jest juz zapisany na ten kurs")
            return False
    
    def ustaw_ocene(self, student_id, kurs_id, ocena):
        cursor = self.conn.cursor()
        # Aktualizacja oceny
        cursor.execute('''
            UPDATE zapisy 
            SET ocena = ? 
            WHERE student_id = ? AND kurs_id = ?
        ''', (ocena, student_id, kurs_id))
        
        # Sprawdzenie czy rekord zostal zaktualizowany
        if cursor.rowcount == 0:
            print("Student nie jest zapisany na ten kurs")
            return False
        
        self.conn.commit()
        return True
    
    def wyswietl_kursy_studenta(self, student_id):
        cursor = self.conn.cursor()
        # Zapytanie JOIN laczace tabele zapisy i kursy
        cursor.execute('''
        SELECT k.nazwa, k.punkty_ects, z.ocena
        FROM zapisy z
        JOIN kursy k ON z.kurs_id = k.id
        WHERE z.student_id = ?
        ''', (student_id,))
        
        print(f"\nKursy studenta (ID: {student_id}):")
        # Odczyt wszystkich wierszy
        for row in cursor.fetchall():
            ocena_str = f"{row&#91;'ocena']}" if row&#91;'ocena'] else "brak"
            print(f"- {row&#91;'nazwa']} ({row&#91;'punkty_ects']} ECTS) - Ocena: {ocena_str}")
    
    def oblicz_srednia_studenta(self, student_id):
        cursor = self.conn.cursor()
        # Zapytanie z funkcja agregujaca AVG
        cursor.execute('''
        SELECT AVG(ocena) as srednia
        FROM zapisy
        WHERE student_id = ? AND ocena IS NOT NULL
        ''', (student_id,))
        
        # Odczyt jednego wiersza
        wynik = cursor.fetchone()
        return round(wynik&#91;'srednia'], 2) if wynik&#91;'srednia'] else 0
    
    def zapisz_na_wiele_kursow(self, student_id, kursy_ids):
        try:
            cursor = self.conn.cursor()
            # Transakcja - wstawienie wielu rekordow
            for kurs_id in kursy_ids:
                cursor.execute(
                    'INSERT INTO zapisy (student_id, kurs_id) VALUES (?, ?)',
                    (student_id, kurs_id)
                )
            self.conn.commit()
            print(f"Student zapisany na {len(kursy_ids)} kursow")
        except sqlite3.Error as e:
            # Wycofanie zmian w przypadku bledu
            self.conn.rollback()
            print(f"Blad: {e}")
    
    def __del__(self):
        # Zamkniecie polaczenia
        self.conn.close()


if __name__ == '__main__':
    import os
    
    # Usuniecie starej bazy danych
    if os.path.exists('uczelnia.db'):
        os.remove('uczelnia.db')
    
    system = SystemStudentow()
    
    # Dodawanie studentow
    student1 = system.dodaj_studenta('Jan', 'Kowalski', 2)
    student2 = system.dodaj_studenta('Anna', 'Nowak', 1)
    student3 = system.dodaj_studenta('Piotr', 'Wisniewski', 3)
    
    # Dodawanie kursow
    kurs1 = system.dodaj_kurs('Bazy Danych', 6)
    kurs2 = system.dodaj_kurs('Algorytmy', 5)
    kurs3 = system.dodaj_kurs('Sieci Komputerowe', 4)
    
    # Zapisanie studenta 1 na wszystkie kursy
    system.zapisz_na_wiele_kursow(student1, &#91;kurs1, kurs2, kurs3])
    
    # Ustawienie ocen dla studenta 1
    system.ustaw_ocene(student1, kurs1, 4.5)
    system.ustaw_ocene(student1, kurs2, 5.0)
    system.ustaw_ocene(student1, kurs3, 3.5)
    
    # Zapisanie studenta 2 na 2 kursy z ocenami
    system.zapisz_na_kurs(student2, kurs1, 4.0)
    system.zapisz_na_kurs(student2, kurs2, 5.0)
    
    # Zapisanie studenta 3 na 1 kurs bez oceny
    system.zapisz_na_kurs(student3, kurs1)
    
    # Wyswietlanie kursow studentow
    system.wyswietl_kursy_studenta(student1)
    srednia1 = system.oblicz_srednia_studenta(student1)
    print(f"\nSrednia ocen: {srednia1}")
    
    system.wyswietl_kursy_studenta(student2)
    srednia2 = system.oblicz_srednia_studenta(student2)
    print(f"\nSrednia ocen: {srednia2}")
    
    system.wyswietl_kursy_studenta(student3)
    srednia3 = system.oblicz_srednia_studenta(student3)
    print(f"\nSrednia ocen: {srednia3}")</code></pre>




<p>Artykuł <a href="https://kamakaczmarek.net/17-python-bazy-danych-sqlite/">17. Python &#8211; bazy danych &#8211; sqlite</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>16. Python &#8211; obiektowo</title>
		<link>https://kamakaczmarek.net/16-python-obiektowo/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Tue, 02 Jun 2026 12:02:13 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[obiekty]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=3640</guid>

					<description><![CDATA[<p>Programowanie obiektowe&#160;(Object-Oriented Programming, OOP) to paradygmat programowania, który organizuje kod wokół&#160;obiektów&#160;i&#160;klas. Zamiast myśleć o programie jako o sekwencji instrukcji, myślisz o nim jako o zbiorze obiektów, które ze sobą współpracują. O tym po co nam programie obiektowe możesz przeczytać niżej w materiale. Kluczowe koncepcje: Analogia: Klasa i obiekt Czym jest klasa? Klasa&#160;to szablon/wzorzec definiujący: Analogia:&#160;Klasa [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/16-python-obiektowo/">16. Python &#8211; obiektowo</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Programowanie obiektowe</strong>&nbsp;(Object-Oriented Programming, OOP) to paradygmat programowania, który organizuje kod wokół&nbsp;<strong>obiektów</strong>&nbsp;i&nbsp;<strong>klas</strong>. Zamiast myśleć o programie jako o sekwencji instrukcji, myślisz o nim jako o zbiorze obiektów, które ze sobą współpracują.</p>



<p class="wp-block-paragraph">O tym po co nam programie obiektowe możesz przeczytać niżej w materiale.</p>



<p class="wp-block-paragraph"><strong>Kluczowe koncepcje:</strong></p>



<ul class="wp-block-list">
<li><strong>Klasa</strong>&nbsp;&#8211; szablon/przepis na obiekt</li>



<li><strong>Obiekt</strong>&nbsp;&#8211; konkretna instancja klasy</li>



<li><strong>Atrybuty</strong>&nbsp;&#8211; dane/właściwości obiektu</li>



<li><strong>Metody</strong>&nbsp;&#8211; funkcje należące do obiektu</li>
</ul>



<p class="wp-block-paragraph"><strong>Analogia:</strong></p>



<ul class="wp-block-list">
<li><strong>Klasa</strong>&nbsp;= Przepis na ciasto</li>



<li><strong>Obiekt</strong>&nbsp;= Konkretne ciasto upieczone według przepisu</li>



<li><strong>Atrybuty</strong>&nbsp;= Składniki ciasta (mąka, jajka, cukier)</li>



<li><strong>Metody</strong>&nbsp;= Akcje (pieczenie, dekorowanie)</li>
</ul>



<h2 class="wp-block-heading">Klasa i obiekt</h2>



<h3 class="wp-block-heading">Czym jest klasa?</h3>



<p class="wp-block-paragraph"><strong>Klasa</strong>&nbsp;to szablon/wzorzec definiujący:</p>



<ul class="wp-block-list">
<li>Jakie dane będzie przechowywać obiekt (atrybuty)</li>



<li>Jakie operacje może wykonać (metody)</li>
</ul>



<p class="wp-block-paragraph"><strong>Analogia:</strong>&nbsp;Klasa to formularz, obiekt to wypełniony formularz.</p>



<h3 class="wp-block-heading">Tworzenie pierwszej klasy</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Kot:
    pass  # Pusta klasa

# Tworzenie obiektu (instancji)
mruczek = Kot()
print(type(mruczek))  # &lt;class '__main__.Kot'&gt;</code></pre>



<h3 class="wp-block-heading">Klasa z atrybutami</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Test:
    # Atrybuty klasy (wspólne dla wszystkich instancji)
    wlasnosc = "Jestem własnością klasy Test"
    lista = &#91;"kot", "pies", "królik"]
    slownik = {"k1": "v1", "k2": "v2"}

# Tworzenie obiektu
obiekt = Test()

# Dostęp do atrybutów
print(obiekt.wlasnosc)  # Jestem własnością klasy Test
print(obiekt.lista&#91;0])  # kot
print(obiekt.slownik&#91;"k1"])  # v1</code></pre>



<h3 class="wp-block-heading">Prywatne atrybuty</h3>



<p class="wp-block-paragraph">W Pythonie nie ma prawdziwych modyfikatorów dostępu. Używamy konwencji:</p>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">nazwa</code>&nbsp;&#8211; publiczne</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">_nazwa</code>&nbsp;&#8211; chronione (konwencja, nie używaj poza klasą)</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">__nazwa</code>&nbsp;&#8211; prywatne (name mangling)</li>
</ul>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Test:
    publiczne = "Dostępne wszędzie"
    _chronione = "Konwencja - nie używaj"
    __prywatne = "Trudno dostępne"

obiekt = Test()
print(obiekt.publiczne)  # OK
# print(obiekt.__prywatne)  # AttributeError

# Można dostać się, ale to złamanie konwencji
print(obiekt._Test__prywatne)  # Zadziała, ale nie rób tego!</code></pre>



<h2 class="wp-block-heading">Metody</h2>



<p class="wp-block-paragraph"><strong>Metoda</strong>&nbsp;to funkcja zdefiniowana wewnątrz klasy.</p>



<h3 class="wp-block-heading">Podstawowa metoda</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Pies:
    def szczekaj(self):
        # self - odwołanie do instancji obiektu
        print("Hau hau!")

azor = Pies()
azor.szczekaj()  # Hau hau!</code></pre>



<p class="wp-block-paragraph"><strong>Ważne:</strong>&nbsp;Pierwszy parametr metody to zawsze&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">self</code>&nbsp;(konwencja).</p>



<h3 class="wp-block-heading">Metody z parametrami</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Kalkulator:
    def dodaj(self, a, b):
        return a + b
    
    def odejmij(self, a, b):
        return a - b

kalk = Kalkulator()
print(kalk.dodaj(5, 3))     # 8
print(kalk.odejmij(10, 4))  # 6</code></pre>



<h3 class="wp-block-heading">Metody korzystające z atrybutów</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Osoba:
    imie = "Jan"
    
    def przywitaj(self):
        # self.imie - dostęp do atrybutu
        print(f"Cześć, jestem {self.imie}!")

osoba = Osoba()
osoba.przywitaj()  # Cześć, jestem Jan!</code></pre>



<h2 class="wp-block-heading">Konstruktor &#8211;&nbsp;<strong>init</strong></h2>



<p class="wp-block-paragraph"><strong>Konstruktor</strong>&nbsp;to specjalna metoda wywoływana automatycznie przy tworzeniu obiektu.</p>



<h3 class="wp-block-heading">Podstawowy konstruktor</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Kot:
    def __init__(self, imie, wiek):
        """Konstruktor - inicjalizuje obiekt"""
        self.imie = imie  # Atrybut instancji
        self.wiek = wiek
    
    def info(self):
        print(f"{self.imie} ma {self.wiek} lat")

# Podczas tworzenia obiekt wywołuje __init__
mruczek = Kot("Mruczek", 3)
mruczek.info()  # Mruczek ma 3 lata

puszek = Kot("Puszek", 5)
puszek.info()  # Puszek ma 5 lat</code></pre>



<h3 class="wp-block-heading">Konstruktor z wartościami domyślnymi</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Gracz:
    def __init__(self, nick, hp=100, lvl=1):
        self.nick = nick
        self.hp = hp
        self.lvl = lvl
    
    def __str__(self):
        return f"{self.nick} (HP: {self.hp}, Lvl: {self.lvl})"

# Z domyślnymi wartościami
gracz1 = Gracz("Warrior")
print(gracz1)  # Warrior (HP: 100, Lvl: 1)

# Nadpisanie domyślnych
gracz2 = Gracz("Mage", hp=80, lvl=5)
print(gracz2)  # Mage (HP: 80, Lvl: 5)</code></pre>



<h2 class="wp-block-heading">Metody magiczne (dunder methods)</h2>



<p class="wp-block-paragraph"><strong>Metody magiczne</strong>&nbsp;to specjalne metody otoczone podwójnymi podkreślnikami:&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">__nazwa__</code>.</p>



<h3 class="wp-block-heading"><strong>str</strong>&nbsp;&#8211; reprezentacja tekstowa</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Ksiazka:
    def __init__(self, tytul, autor):
        self.tytul = tytul
        self.autor = autor
    
    def __str__(self):
        """Wywoływane przez print() i str()"""
        return f'"{self.tytul}" - {self.autor}'

ksiazka = Ksiazka("Wiedźmin", "Andrzej Sapkowski")
print(ksiazka)  # "Wiedźmin" - Andrzej Sapkowski</code></pre>



<h3 class="wp-block-heading"><strong>repr</strong>&nbsp;&#8211; reprezentacja techniczna</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Ksiazka:
    def __init__(self, tytul, autor, rok):
        self.tytul = tytul
        self.autor = autor
        self.rok = rok
    
    def __str__(self):
        # Dla użytkownika
        return f'"{self.tytul}" - {self.autor} ({self.rok})'
    
    def __repr__(self):
        # Dla programisty/debugowania
        return f'Ksiazka(tytul="{self.tytul}", autor="{self.autor}", rok={self.rok})'

ksiazka = Ksiazka("Wiedźmin", "Sapkowski", 1990)
print(str(ksiazka))   # "Wiedźmin" - Sapkowski (1990)
print(repr(ksiazka))  # Ksiazka(tytul="Wiedźmin", autor="Sapkowski", rok=1990)</code></pre>



<h3 class="wp-block-heading"><strong>len</strong>&nbsp;&#8211; długość obiektu</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Playlista:
    def __init__(self, nazwa):
        self.nazwa = nazwa
        self.utwory = &#91;]
    
    def dodaj(self, utwor):
        self.utwory.append(utwor)
    
    def __len__(self):
        """Wywoływane przez len()"""
        return len(self.utwory)

pl = Playlista("Rock")
pl.dodaj("Song 1")
pl.dodaj("Song 2")
print(len(pl))  # 2</code></pre>



<h3 class="wp-block-heading">Operatory porównania</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Osoba:
    def __init__(self, imie, wiek):
        self.imie = imie
        self.wiek = wiek
    
    def __eq__(self, other):
        """Operator =="""
        return self.wiek == other.wiek
    
    def __lt__(self, other):
        """Operator &lt;"""
        return self.wiek &lt; other.wiek
    
    def __gt__(self, other):
        """Operator &gt;"""
        return self.wiek &gt; other.wiek

anna = Osoba("Anna", 25)
jan = Osoba("Jan", 30)

print(anna &lt; jan)   # True
print(jan &gt; anna)   # True
print(anna == jan)  # False</code></pre>



<h3 class="wp-block-heading"><strong>getitem</strong>&nbsp;i&nbsp;<strong>setitem</strong>&nbsp;&#8211; indeksowanie</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Lista:
    def __init__(self):
        self.dane = &#91;]
    
    def __getitem__(self, index):
        """Wywoływane przez lista&#91;index]"""
        return self.dane&#91;index]
    
    def __setitem__(self, index, value):
        """Wywoływane przez lista&#91;index] = value"""
        self.dane&#91;index] = value
    
    def dodaj(self, element):
        self.dane.append(element)

lista = Lista()
lista.dodaj("Python")
lista.dodaj("Java")
lista.dodaj("C++")

print(lista&#91;0])  # Python - wywołuje __getitem__
lista&#91;1] = "JavaScript"  # Wywołuje __setitem__
print(lista&#91;1])  # JavaScript</code></pre>



<h3 class="wp-block-heading">Operatory matematyczne</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Wektor:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        """Operator +"""
        return Wektor(self.x + other.x, self.y + other.y)
    
    def __mul__(self, skalar):
        """Operator *"""
        return Wektor(self.x * skalar, self.y * skalar)
    
    def __str__(self):
        return f"({self.x}, {self.y})"

v1 = Wektor(1, 2)
v2 = Wektor(3, 4)

v3 = v1 + v2  # Wywołuje __add__
print(v3)     # (4, 6)

v4 = v1 * 3   # Wywołuje __mul__
print(v4)     # (3, 6)</code></pre>



<h3 class="wp-block-heading"><strong>call</strong>&nbsp;&#8211; obiekt jako funkcja</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Mnoznik:
    def __init__(self, mnoznik):
        self.mnoznik = mnoznik
    
    def __call__(self, x):
        """Pozwala wywołać obiekt jak funkcję"""
        return x * self.mnoznik

razy_2 = Mnoznik(2)
razy_10 = Mnoznik(10)

print(razy_2(5))   # 10
print(razy_10(5))  # 50</code></pre>



<h3 class="wp-block-heading">Tabela metod magicznych</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Metoda</th><th>Wywołanie</th><th>Opis</th></tr></thead><tbody><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__init__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj = Klasa()</code></td><td>Konstruktor</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__str__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">print(obj)</code>,&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">str(obj)</code></td><td>Reprezentacja tekstowa</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__repr__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">repr(obj)</code></td><td>Reprezentacja techniczna</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__len__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">len(obj)</code></td><td>Długość</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__eq__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj1 == obj2</code></td><td>Równość</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__lt__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj1 &lt; obj2</code></td><td>Mniejsze niż</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__gt__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj1 &gt; obj2</code></td><td>Większe niż</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__add__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj1 + obj2</code></td><td>Dodawanie</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__sub__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj1 - obj2</code></td><td>Odejmowanie</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__mul__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj1 * obj2</code></td><td>Mnożenie</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__getitem__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj[key]</code></td><td>Dostęp przez indeks</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__setitem__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj[key] = val</code></td><td>Ustawianie przez indeks</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__call__</code></td><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">obj()</code></td><td>Wywołanie jak funkcja</td></tr><tr><td><code class="prettyprint lang-sql" style="font-size: 0.85em;">__del__</code></td><td>Usuwanie obiektu</td><td>Destruktor</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Modyfikatory dostępu</h2>



<p class="wp-block-paragraph">Python&nbsp;<strong>nie ma</strong>&nbsp;prawdziwych modyfikatorów dostępu jak Java czy C++. Używa konwencji:</p>



<h3 class="wp-block-heading">Publiczne (brak podkreślników)</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Osoba:
    def __init__(self, imie):
        self.imie = imie  # Publiczne

osoba = Osoba("Jan")
print(osoba.imie)  # OK
osoba.imie = "Anna"  # OK</code></pre>



<h3 class="wp-block-heading">Chronione (jeden podkreślnik)</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Osoba:
    def __init__(self, imie):
        self._imie = imie  # Chronione (konwencja)
    
    def _metoda_wewnetrzna(self):
        print("Używana tylko wewnątrz")

osoba = Osoba("Jan")
print(osoba._imie)  # Technicznie działa, ale nie powinieneś</code></pre>



<p class="wp-block-paragraph"><strong>Konwencja:</strong>&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">_nazwa</code>&nbsp;sugeruje &#8222;nie używaj tego poza klasą&#8221;.</p>



<h3 class="wp-block-heading">Prywatne (dwa podkreślniki)</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Osoba:
    def __init__(self, imie):
        self.__imie = imie  # Prywatne
    
    def __metoda_prywatna(self):
        print("Prywatna metoda")
    
    def pokaz_imie(self):
        print(self.__imie)  # OK wewnątrz klasy

osoba = Osoba("Jan")
# print(osoba.__imie)  # AttributeError

# Python zmienia nazwę (name mangling)
print(osoba._Osoba__imie)  # Działa, ale nie rób tego!</code></pre>



<p class="wp-block-paragraph"><strong>Name mangling:</strong>&nbsp;Python zmienia&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">__nazwa</code>&nbsp;na&nbsp;<code class="prettyprint lang-sql" style="font-size: 0.85em;">_NazwaKlasy__nazwa</code>.</p>



<h2 class="wp-block-heading">Dziedziczenie</h2>



<p class="wp-block-paragraph"><strong>Dziedziczenie</strong>&nbsp;pozwala tworzyć nowe klasy bazując na istniejących.</p>



<h3 class="wp-block-heading">Podstawowe dziedziczenie</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Zwierze:
    def __init__(self, imie):
        self.imie = imie
    
    def dzwiek(self):
        return "Jakiś dźwięk"

class Pies(Zwierze):  # Pies dziedziczy po Zwierze
    def dzwiek(self):
        return "Hau hau!"

class Kot(Zwierze):
    def dzwiek(self):
        return "Miau!"

pies = Pies("Azor")
kot = Kot("Mruczek")

print(f"{pies.imie}: {pies.dzwiek()}")  # Azor: Hau hau!
print(f"{kot.imie}: {kot.dzwiek()}")    # Mruczek: Miau!</code></pre>



<h3 class="wp-block-heading">super() &#8211; wywołanie metod rodzica</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Pojazd:
    def __init__(self, marka):
        self.marka = marka
        print(f"Utworzono pojazd: {marka}")
    
    def info(self):
        return f"Pojazd marki {self.marka}"

class Samochod(Pojazd):
    def __init__(self, marka, model):
        super().__init__(marka)  # Wywołanie konstruktora rodzica
        self.model = model
    
    def info(self):
        # Wywołanie metody rodzica
        podstawowa_info = super().info()
        return f"{podstawowa_info}, model {self.model}"

auto = Samochod("Toyota", "Corolla")
# Utworzono pojazd: Toyota
print(auto.info())
# Pojazd marki Toyota, model Corolla</code></pre>



<h3 class="wp-block-heading">isinstance() &#8211; sprawdzanie typu</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Zwierze:
    pass

class Pies(Zwierze):
    pass

class Kot(Zwierze):
    pass

pies = Pies()
kot = Kot()

print(isinstance(pies, Pies))      # True
print(isinstance(pies, Zwierze))   # True (dziedziczy!)
print(isinstance(pies, Kot))       # False
print(isinstance(pies, object))    # True (wszystko dziedziczy po object)</code></pre>



<h3 class="wp-block-heading">Wielodziedziczenie</h3>



<p class="wp-block-paragraph">Python obsługuje dziedziczenie z wielu klas (ostrożnie!).</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Latanie:
    def lataj(self):
        print("Lecę!")

class Plywanie:
    def plywaj(self):
        print("Pływam!")

class Kaczka(Latanie, Plywanie):
    def kwacz(self):
        print("Kwa kwa!")

kaczka = Kaczka()
kaczka.lataj()   # Lecę!
kaczka.plywaj()  # Pływam!
kaczka.kwacz()   # Kwa kwa!</code></pre>



<h2 class="wp-block-heading">Kompozycja vs Dziedziczenie</h2>



<p class="wp-block-paragraph">W OOP (programowaniu obiektowym) <strong>dziedziczenie</strong> i <strong>kompozycja</strong> to dwa sposoby budowania relacji między klasami.</p>



<p class="wp-block-paragraph">Zadaj sobie pytanie:</p>



<p class="wp-block-paragraph"><strong>Czy mogę powiedzieć:</strong> X jest Y</p>



<p class="wp-block-paragraph">Przykłady:</p>



<ul class="wp-block-list">
<li>Pies jest zwierzęciem &#8211; tak</li>



<li>Student jest człowiekiem &#8211; tak</li>



<li>Samochód jest pojazdem &#8211; tak</li>
</ul>



<p class="wp-block-paragraph">→ <strong>dziedziczenie</strong></p>



<p class="wp-block-paragraph"><strong>Czy mogę powiedzieć:</strong> X ma Y</p>



<p class="wp-block-paragraph">Przykłady:</p>



<ul class="wp-block-list">
<li>Samochód ma silnik &#8211; tak</li>



<li>Dom ma okna &#8211; tak</li>



<li>Komputer ma procesor &#8211; tak</li>
</ul>



<p class="wp-block-paragraph">→ <strong>kompozycja</strong></p>



<h3 class="wp-block-heading">Kiedy używać dziedziczenia?</h3>



<p class="wp-block-paragraph">Relacja &#8222;JEST&#8221; (is-a):</p>



<ul class="wp-block-list">
<li>Pies&nbsp;<strong>JEST</strong>&nbsp;Zwierzęciem</li>



<li>Samochód&nbsp;<strong>JEST</strong>&nbsp;Pojazdem</li>
</ul>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Zwierze:
    pass

class Pies(Zwierze):  # Pies JEST Zwierzęciem
    pass</code></pre>



<h3 class="wp-block-heading">Kiedy używać kompozycji?</h3>



<p class="wp-block-paragraph">Relacja &#8222;MA&#8221; (has-a):</p>



<ul class="wp-block-list">
<li>Samochód&nbsp;<strong>MA</strong>&nbsp;Silnik</li>



<li>Osoba&nbsp;<strong>MA</strong>&nbsp;Adres</li>
</ul>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Silnik:
    def __init__(self, moc):
        self.moc = moc
    
    def uruchom(self):
        print(f"Silnik {self.moc}KM uruchomiony")

class Samochod:
    def __init__(self, marka, moc_silnika):
        self.marka = marka
        self.silnik = Silnik(moc_silnika)  # MA silnik
    
    def uruchom(self):
        print(f"Uruchamiam {self.marka}")
        self.silnik.uruchom()

auto = Samochod("Toyota", 150)
auto.uruchom()
# Uruchamiam Toyota
# Silnik 150KM uruchomiony</code></pre>



<h3 class="wp-block-heading">Problem z dziedziczeniem</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># ŹLE - nadmierne dziedziczenie
class Ptak:
    def lataj(self):
        print("Lecę")

class Pingwin(Ptak):
    # Problem! Pingwin nie lata, ale dziedziczy lataj()
    pass

pingwin = Pingwin()
pingwin.lataj()  # Pingwin lata? To błąd logiczny!</code></pre>



<h3 class="wp-block-heading">Rozwiązanie &#8211; kompozycja</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># DOBRZE - kompozycja
class Latanie:
    def lataj(self):
        print("Lecę w powietrzu")

class Plywanie:
    def plywaj(self):
        print("Pływam w wodzie")

class Orzel:
    def __init__(self):
        self.latanie = Latanie()  # MA zdolność latania
    
    def wykonaj_lot(self):
        self.latanie.lataj()

class Pingwin:
    def __init__(self):
        self.plywanie = Plywanie()  # MA zdolność pływania
    
    def wykonaj_plywanie(self):
        self.plywanie.plywaj()

orzel = Orzel()
orzel.wykonaj_lot()  # Lecę w powietrzu

pingwin = Pingwin()
pingwin.wykonaj_plywanie()  # Pływam w wodzie</code></pre>



<p class="wp-block-paragraph"><strong>Złota zasada:</strong>&nbsp;&#8222;Prefer composition over inheritance&#8221; (Preferuj kompozycję nad dziedziczeniem)</p>



<h2 class="wp-block-heading">Klasy abstrakcyjne</h2>



<p class="wp-block-paragraph"><strong>Klasa abstrakcyjna</strong> to klasa, która:</p>



<ul class="wp-block-list">
<li>Nie może być instancjonowana (nie można z niej tworzyć obiektów)</li>



<li>Służy jako szablon dla klas potomnych</li>



<li>Może zawierać metody abstrakcyjne (bez implementacji)</li>
</ul>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from abc import ABC, abstractmethod

class Zwierze(ABC):
    def __init__(self, imie):
        self.imie = imie
    
    @abstractmethod
    def dzwiek(self):
        """Metoda abstrakcyjna - musi być zaimplementowana"""
        pass
    
    def przedstaw_sie(self):
        print(f"Jestem {self.imie} i mówię {self.dzwiek()}")

# zwierze = Zwierze("Test")  # TypeError! Nie można utworzyć

class Pies(Zwierze):
    def dzwiek(self):
        return "Hau hau!"

class Kot(Zwierze):
    def dzwiek(self):
        return "Miau!"

pies = Pies("Azor")
pies.przedstaw_sie()  # Jestem Azor i mówię Hau hau!</code></pre>



<h2 class="wp-block-heading">Dekorator @property</h2>



<p class="wp-block-paragraph"><strong>@property</strong> pozwala traktować metodę jak atrybut.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Prostokat:
    def __init__(self, szerokosc, wysokosc):
        self.szerokosc = szerokosc
        self.wysokosc = wysokosc
    
    @property
    def pole(self):
        """Metoda jako właściwość"""
        return self.szerokosc * self.wysokosc
    
    @property
    def obwod(self):
        return 2 * (self.szerokosc + self.wysokosc)

prostokat = Prostokat(5, 10)
# Wywołanie bez nawiasów!
print(prostokat.pole)    # 50
print(prostokat.obwod)   # 30</code></pre>



<h3 class="wp-block-heading">Getter i setter</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Osoba:
    def __init__(self, imie, wiek):
        self._imie = imie
        self._wiek = wiek
    
    @property
    def wiek(self):
        """Getter"""
        return self._wiek
    
    @wiek.setter
    def wiek(self, wartosc):
        """Setter z walidacją"""
        if wartosc &lt; 0:
            raise ValueError("Wiek nie może być ujemny!")
        self._wiek = wartosc

osoba = Osoba("Jan", 25)
print(osoba.wiek)  # 25 - wywołuje getter

osoba.wiek = 30    # Wywołuje setter
print(osoba.wiek)  # 30

# osoba.wiek = -5  # ValueError!</code></pre>



<h2 class="wp-block-heading">Paradygmaty OOP</h2>



<h3 class="wp-block-heading">1. Abstrakcja</h3>



<p class="wp-block-paragraph">Ukrywanie skomplikowanych szczegółów, pokazywanie tylko tego co potrzebne.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Telefon:
    def __init__(self, model):
        self.model = model
        self.__system = "Android"  # Ukryte
    
    def dzwon(self, numer):
        """Prosty interfejs - nie musisz wiedzieć jak działa"""
        self.__polacz_z_sieciami()
        self.__wyslij_sygnal(numer)
        print(f"Dzwonię na {numer}")
    
    def __polacz_z_sieciami(self):
        """Ukryte szczegóły"""
        pass
    
    def __wyslij_sygnal(self, numer):
        """Ukryte szczegóły"""
        pass

telefon = Telefon("iPhone")
telefon.dzwon("123456789")  # Prosta, ukrywa złożoność</code></pre>



<h3 class="wp-block-heading">2. Enkapsulacja</h3>



<p class="wp-block-paragraph">Ukrywanie danych i kontrolowanie dostępu do nich.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class KontoBankowe:
    def __init__(self, saldo):
        self.__saldo = saldo  # Prywatne - enkapsulacja
    
    def wplata(self, kwota):
        if kwota > 0:
            self.__saldo += kwota
            return True
        return False
    
    def wyplata(self, kwota):
        if 0 &lt; kwota &lt;= self.__saldo:
            self.__saldo -= kwota
            return True
        return False
    
    @property
    def saldo(self):
        """Kontrolowany dostęp tylko do odczytu"""
        return self.__saldo

konto = KontoBankowe(1000)
konto.wplata(500)
print(konto.saldo)  # 1500
# konto.__saldo = 999999  # Nie działa - chronione!</code></pre>



<h3 class="wp-block-heading">3. Dziedziczenie</h3>



<p class="wp-block-paragraph">Tworzenie hierarchii klas, współdzielenie kodu.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Pojazd:
    def __init__(self, marka):
        self.marka = marka
    
    def info(self):
        return f"Pojazd {self.marka}"

class Samochod(Pojazd):
    def __init__(self, marka, model):
        super().__init__(marka)
        self.model = model
    
    def info(self):
        return f"Samochód {self.marka} {self.model}"

class Motocykl(Pojazd):
    def info(self):
        return f"Motocykl {self.marka}"</code></pre>



<h3 class="wp-block-heading">4. Polimorfizm</h3>



<p class="wp-block-paragraph">Różne obiekty reagują na tę samą metodę w różny sposób.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Pies:
    def dzwiek(self):
        return "Hau hau!"

class Kot:
    def dzwiek(self):
        return "Miau!"

class Krowa:
    def dzwiek(self):
        return "Muuu!"

# Polimorfizm - ta sama metoda, różne zachowania
zwierzeta = &#91;Pies(), Kot(), Krowa()]

for zwierze in zwierzeta:
    print(zwierze.dzwiek())
# Hau hau!
# Miau!
# Muuu!</code></pre>



<h2 class="wp-block-heading">Przykłady praktyczne</h2>



<h3 class="wp-block-heading">Zadanie 1: Klasa Trójkąt</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import random

class Trojkat:
    def __init__(self):
        self.wysokosc = random.randint(1, 20)
        self.podstawa = random.randint(1, 20)
    
    def oblicz_pole(self):
        return (self.podstawa * self.wysokosc) / 2
    
    def __str__(self):
        return f"Trójkąt(podstawa={self.podstawa}, wysokość={self.wysokosc})"

trojkat1 = Trojkat()
trojkat2 = Trojkat()

pole1 = trojkat1.oblicz_pole()
pole2 = trojkat2.oblicz_pole()

print(f"{trojkat1} - Pole: {pole1} cm²")
print(f"{trojkat2} - Pole: {pole2} cm²")

if pole1 > pole2:
    print(f"Trójkąt 1 jest większy")
else:
    print(f"Trójkąt 2 jest większy")</code></pre>



<h3 class="wp-block-heading">Zadanie 2: Okrąg i Koło</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">from math import pi

class Okrag:
    def __init__(self, promien):
        self.promien = promien
    
    def obwod(self):
        return 2 * pi * self.promien

class Kolo(Okrag):
    def pole(self):
        return pi * self.promien ** 2

kolo = Kolo(10)
print(f"Obwód: {kolo.obwod():.2f}")
print(f"Pole: {kolo.pole():.2f}")</code></pre>



<h3 class="wp-block-heading">Zadanie 3: Gracz RPG</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">import random

class Gracz:
    def __init__(self, nick):
        self.nick = nick
        self.poziom = 1
        self.hp = 100
        self.exp = 0
    
    def atak(self, cel):
        obrazenia = random.randint(10, 25)
        print(f"{self.nick} atakuje {cel.nick}!")
        cel.otrzymaj_obrazenia(obrazenia)
    
    def otrzymaj_obrazenia(self, ilosc):
        self.hp -= ilosc
        if self.hp &lt; 0:
            self.hp = 0
        print(f"{self.nick} ma {self.hp} HP")
    
    def zdobadz_exp(self, ilosc):
        self.exp += ilosc
        if self.exp >= 100:
            self.poziom += 1
            self.exp = 0
            print(f"{self.nick} awansował na poziom {self.poziom}!")
    
    def __str__(self):
        return f"{self.nick} | Poziom: {self.poziom} | HP: {self.hp} | EXP: {self.exp}"

gracz1 = Gracz("Warrior")
gracz2 = Gracz("Mage")
gracz1.atak(gracz2)</code></pre>



<h2 class="wp-block-heading">Po co programowanie obiektowe?</h2>



<h3 class="wp-block-heading">1. Organizacja i modularność</h3>



<p class="wp-block-paragraph">Kod podzielony na logiczne części (klasy) jest bardziej przejrzysty.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Bez OOP - wszystko w jednym miejscu
gracz_imie = "Jan"
gracz_hp = 100
gracz_lvl = 1

przeciwnik_imie = "Goblin"
przeciwnik_hp = 50
przeciwnik_lvl = 1

# Z OOP - każdy obiekt osobno
class Postac:
    def __init__(self, imie, hp, lvl):
        self.imie = imie
        self.hp = hp
        self.lvl = lvl

gracz = Postac("Jan", 100, 1)
przeciwnik = Postac("Goblin", 50, 1)</code></pre>



<h3 class="wp-block-heading">2. Reużywalność kodu</h3>



<p class="wp-block-paragraph">Możesz wykorzystywać klasy wielokrotnie.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Pojazd:
    def __init__(self, marka):
        self.marka = marka
    
    def jedz(self):
        print(f"{self.marka} jedzie")

# Możesz utworzyć wiele obiektów tej samej klasy
samochod1 = Pojazd("Toyota")
samochod2 = Pojazd("BMW")
samochod3 = Pojazd("Audi")</code></pre>



<h3 class="wp-block-heading">3. Łatwiejsze rozwijanie aplikacji</h3>



<p class="wp-block-paragraph">Zmiany w jednej klasie nie wpływają na inne.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Dodanie nowej funkcjonalności tylko w jednym miejscu
class Samochod:
    def __init__(self, marka):
        self.marka = marka
        self.predkosc = 0
    
    def przyspiesz(self, ile):
        self.predkosc += ile
        print(f"Prędkość: {self.predkosc} km/h")</code></pre>



<h3 class="wp-block-heading">4. Enkapsulacja &#8211; ukrywanie szczegółów</h3>



<p class="wp-block-paragraph">Dane są chronione, dostęp tylko przez metody.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class KontoBankowe:
    def __init__(self, saldo):
        self.__saldo = saldo  # Prywatne
    
    def wplac(self, kwota):
        if kwota &gt; 0:
            self.__saldo += kwota
    
    def pobierz_saldo(self):
        return self.__saldo

# Nie można bezpośrednio zmieniać salda
konto = KontoBankowe(1000)
konto.wplac(500)  # OK
# konto.__saldo = 999999  # Nie zadziała!</code></pre>



<h3 class="wp-block-heading">5. Naturalne odwzorowanie rzeczywistości</h3>



<p class="wp-block-paragraph">OOP naśladuje sposób myślenia o świecie.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class Kot:
    def __init__(self, imie, kolor):
        self.imie = imie
        self.kolor = kolor
    
    def miaucz(self):
        print(f"{self.imie}: Miauuu!")

mruczek = Kot("Mruczek", "rudy")
mruczek.miaucz()  # Mruczek: Miauuu!</code></pre>



<h2 class="wp-block-heading">Podsumowanie</h2>



<h3 class="wp-block-heading"><strong>Podstawy OOP:</strong></h3>



<ul class="wp-block-list">
<li><strong>Klasa</strong> &#8211; szablon obiektu</li>



<li><strong>Obiekt</strong> &#8211; instancja klasy</li>



<li><strong>Atrybuty</strong> &#8211; dane obiektu</li>



<li><strong>Metody</strong> &#8211; funkcje obiektu</li>



<li><strong>self</strong> &#8211; odniesienie do instancji</li>
</ul>



<h3 class="wp-block-heading"><strong>Metody specjalne:</strong></h3>



<ul class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">__init__</code> &#8211; konstruktor</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">__str__</code> &#8211; reprezentacja tekstowa</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">__len__</code> &#8211; długość</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">__eq__</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">__lt__</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">__gt__</code> &#8211; porównania</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">__add__</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">__mul__</code> &#8211; operatory matematyczne</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">__getitem__</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">__setitem__</code> &#8211; indeksowanie</li>
</ul>



<h3 class="wp-block-heading"><strong>Zaawansowane:</strong></h3>



<ul class="wp-block-list">
<li><strong>Dziedziczenie</strong> &#8211; tworzenie hierarchii klas</li>



<li><strong>super()</strong> &#8211; wywołanie metod rodzica</li>



<li><strong>Kompozycja</strong> &#8211; obiekty zawierają inne obiekty</li>



<li><strong>Klasy abstrakcyjne</strong> &#8211; szablony dla klas potomnych</li>



<li><strong>@property</strong> &#8211; metody jako atrybuty</li>
</ul>



<h3 class="wp-block-heading"><strong>Paradygmaty OOP:</strong></h3>



<ul class="wp-block-list">
<li><strong>Abstrakcja</strong> &#8211; ukrywanie szczegółów</li>



<li><strong>Enkapsulacja</strong> &#8211; ochrona danych</li>



<li><strong>Dziedziczenie</strong> &#8211; współdzielenie kodu</li>



<li><strong>Polimorfizm</strong> &#8211; jedna metoda, różne zachowania</li>
</ul>



<h3 class="wp-block-heading"><strong>Dobre praktyki:</strong></h3>



<ul class="wp-block-list">
<li>Jedna klasa = jedna odpowiedzialność</li>



<li>Preferuj kompozycję nad dziedziczeniem</li>



<li>Używaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">@property</code> dla computed properties</li>



<li>Dokumentuj klasy docstringami</li>



<li>Nazwy klas PascalCase</li>
</ul>



<h2 class="wp-block-heading">Ćwiczenia &#8211; Programowanie obiektowe</h2>



<h3 class="wp-block-heading">Podstawy klas i obiektów</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Punkt</code> z atrybutami x i y. Dodaj metodę wyświetlającą współrzędne.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Prostokat</code> z atrybutami szerokość i wysokość. Dodaj metody obliczające pole i obwód.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Kolo</code> z atrybutem promień. Dodaj metody obliczające pole i obwód.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Student</code> z atrybutami: imię, nazwisko, numer_indeksu. Dodaj metodę wyświetlającą pełne dane.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Ksiazka</code> z atrybutami: tytuł, autor, rok_wydania, liczba_stron.</li>
</ol>



<h3 class="wp-block-heading">Konstruktor <strong>init</strong></h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Samochod</code> z konstruktorem przyjmującym markę, model i rok_produkcji.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pracownik</code> z konstruktorem ustawiającym imię, nazwisko, pensję.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Uzytkownik</code> z konstruktorem i domyślnymi wartościami (aktywny=True, rola=&#8221;user&#8221;).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Produkt</code> z konstruktorem walidującym cenę (musi być > 0).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Data</code> z konstruktorem przyjmującym dzień, miesiąc, rok i walidującym je.</li>
</ol>



<h3 class="wp-block-heading">Metody</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Licznik</code> z metodami zwiększ(), zmniejsz(), reset(), pokaz_wartosc().</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Temperatura</code> z metodą konwertującą Celsjusz na Fahrenheit.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Haslo</code> z metodą sprawdzającą siłę hasła (długość, znaki specjalne).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Email</code> z metodą walidującą adres email (@, kropka).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Kalkulator</code> z metodami: dodaj, odejmij, pomnoz, podziel.</li>
</ol>



<h3 class="wp-block-heading">Metody <strong>str</strong> i <strong>repr</strong></h3>



<ol class="wp-block-list">
<li>Dodaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">__str__</code> do klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Osoba</code> wyświetlający &#8222;Imię Nazwisko, wiek: X lat&#8221;.</li>



<li>Dodaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">__str__</code> i <code class="prettyprint lang-sql" style="font-size: 0.85em;">__repr__</code> do klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Produkt</code>.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Czas</code> (godzina, minuta) z <code class="prettyprint lang-sql" style="font-size: 0.85em;">__str__</code> formatującym na &#8222;HH:MM&#8221;.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Data</code> z <code class="prettyprint lang-sql" style="font-size: 0.85em;">__str__</code> formatującym na &#8222;DD/MM/YYYY&#8221;.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Ulamek</code> (licznik, mianownik) z czytelnym <code class="prettyprint lang-sql" style="font-size: 0.85em;">__str__</code>.</li>
</ol>



<h3 class="wp-block-heading">Atrybuty prywatne</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">KontoBankowe</code> z prywatnym atrybutem __saldo.</li>



<li>Dodaj do <code class="prettyprint lang-sql" style="font-size: 0.85em;">KontoBankowe</code> metody wplata() i wyplata() z walidacją.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Haslo</code> z prywatnym atrybutem __haslo i metodą sprawdz().</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Uzytkownik</code> z prywatnym __email i publiczną metodą get_email().</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Sejf</code> z prywatnym kodem i metodą otwierania.</li>
</ol>



<h3 class="wp-block-heading">Metody magiczne &#8211; porównania</h3>



<ol class="wp-block-list">
<li>Dodaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">__eq__</code> do klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Osoba</code> (porównanie po wieku).</li>



<li>Dodaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">__lt__</code> i <code class="prettyprint lang-sql" style="font-size: 0.85em;">__gt__</code> do klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Produkt</code> (porównanie po cenie).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Ocena</code> z metodami porównania (<code class="prettyprint lang-sql" style="font-size: 0.85em;">__eq__</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">__lt__</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">__gt__</code>).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Data</code> z możliwością porównywania dat.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Prostokat</code> z porównywaniem pól powierzchni.</li>
</ol>



<h3 class="wp-block-heading">Metody magiczne &#8211; operatory</h3>



<ol class="wp-block-list">
<li>Dodaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">__add__</code> do klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Wektor2D</code> (dodawanie wektorów).</li>



<li>Dodaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">__mul__</code> do klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Wektor2D</code> (mnożenie przez skalar).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Czas</code> z możliwością dodawania (<code class="prettyprint lang-sql" style="font-size: 0.85em;">__add__</code>).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pieniadze</code> z możliwością dodawania i odejmowania.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Macierz2x2</code> z operacjami dodawania i mnożenia.</li>
</ol>



<h3 class="wp-block-heading">Metody magiczne &#8211; kolekcje</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Lista</code> z <code class="prettyprint lang-sql" style="font-size: 0.85em;">__len__</code> zwracającym liczbę elementów.</li>



<li>Dodaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">__getitem__</code> do klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Lista</code> (dostęp przez indeks).</li>



<li>Dodaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">__setitem__</code> do klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Lista</code> (ustawianie przez indeks).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Slownik</code> z <code class="prettyprint lang-sql" style="font-size: 0.85em;">__getitem__</code> i <code class="prettyprint lang-sql" style="font-size: 0.85em;">__setitem__</code>.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Playlista</code> z <code class="prettyprint lang-sql" style="font-size: 0.85em;">__len__</code> i iteracją po utworach.</li>
</ol>



<h3 class="wp-block-heading">@property</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Prostokat</code> z @property dla pola powierzchni.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Kolo</code> z @property dla pola i obwodu.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Osoba</code> z @property dla pełnego imienia (imię + nazwisko).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Temperatura</code> z @property dla Fahrenheita (obliczane z Celsjusza).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Produkt</code> z @property i setterem dla ceny (walidacja > 0).</li>
</ol>



<h3 class="wp-block-heading">Dziedziczenie &#8211; podstawy</h3>



<ol class="wp-block-list">
<li>Stwórz klasę bazową <code class="prettyprint lang-sql" style="font-size: 0.85em;">Zwierze</code> i klasy potomne <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pies</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">Kot</code>.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pojazd</code> i klasy potomne <code class="prettyprint lang-sql" style="font-size: 0.85em;">Samochod</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">Motocykl</code>.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Figura</code> i klasy potomne <code class="prettyprint lang-sql" style="font-size: 0.85em;">Kwadrat</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">Kolo</code>.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Osoba</code> i klasy potomne <code class="prettyprint lang-sql" style="font-size: 0.85em;">Student</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pracownik</code>.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Konto</code> i klasy potomne <code class="prettyprint lang-sql" style="font-size: 0.85em;">KontoOszczednosciowe</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">KontoBiezace</code>.</li>
</ol>



<h3 class="wp-block-heading">Dziedziczenie z super()</h3>



<ol class="wp-block-list">
<li>W klasie <code class="prettyprint lang-sql" style="font-size: 0.85em;">Samochod</code> (dziedziczy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pojazd</code>) użyj super() w konstruktorze.</li>



<li>Nadpisz metodę w klasie potomnej i wywołaj metodę rodzica przez super().</li>



<li>Stwórz łańcuch dziedziczenia: <code class="prettyprint lang-sql" style="font-size: 0.85em;">Zwierze</code> → <code class="prettyprint lang-sql" style="font-size: 0.85em;">Ssak</code> → <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pies</code>, użyj super().</li>



<li>Rozszerz konstruktor klasy potomnej o dodatkowe atrybuty używając super().</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">PracownikZPremią</code> dziedziczącą <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pracownik</code> i rozszerzającą metodę oblicz_wynagrodzenie().</li>
</ol>



<h3 class="wp-block-heading">Kompozycja</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Silnik</code> i klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Samochod</code> zawierającą obiekt Silnik.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Adres</code> i klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Osoba</code> zawierającą obiekt Adres.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Telefon</code> i klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Kontakt</code> zawierającą listę telefonów.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Skladnik</code> i klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Przepis</code> zawierającą listę składników.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Gracz</code> i klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Druzyna</code> zawierającą listę graczy.</li>
</ol>



<h3 class="wp-block-heading">Klasy abstrakcyjne</h3>



<ol class="wp-block-list">
<li>Stwórz abstrakcyjną klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Figura</code> z metodą abstrakcyjną pole().</li>



<li>Stwórz abstrakcyjną klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Platnosc</code> z metodą abstrakcyjną przetworz().</li>



<li>Stwórz abstrakcyjną klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Zwierze</code> z metodą abstrakcyjną dzwiek().</li>



<li>Stwórz abstrakcyjną klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Pojazd</code> z metodami abstrakcyjnymi jedz() i zatrzymaj().</li>



<li>Stwórz abstrakcyjną klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Baza</code> z metodami abstrakcyjnymi polacz() i rozlacz().</li>
</ol>



<h3 class="wp-block-heading">isinstance() i type()</h3>



<ol class="wp-block-list">
<li>Sprawdź isinstance() dla obiektów różnych klas z dziedziczeniem.</li>



<li>Napisz funkcję przyjmującą tylko obiekty typu Prostokat (walidacja isinstance).</li>



<li>Napisz funkcję działającą różnie dla różnych typów (isinstance).</li>



<li>Sprawdź czy obiekt jest instancją klasy bazowej lub potomnej.</li>



<li>Użyj isinstance() do walidacji argumentów metody.</li>
</ol>



<h3 class="wp-block-heading">Zadania praktyczne &#8211; Biblioteka</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Ksiazka</code> z atrybutami i metodą <code class="prettyprint lang-sql" style="font-size: 0.85em;">__str__</code>.</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Biblioteka</code> przechowującą listę książek.</li>



<li>Dodaj metody dodaj_ksiazke(), usun_ksiazke() do Biblioteki.</li>



<li>Dodaj metodę wyszukaj_po_tytule() do Biblioteki.</li>



<li>Dodaj metodę wyszukaj_po_autorze() do Biblioteki.</li>



<li>Dodaj atrybut wypozyczona do Ksiazki i metody wypozycz()/zwroc().</li>



<li>Dodaj do Biblioteki metodę dostepne_ksiazki().</li>



<li>Dodaj licznik wypożyczeń do Ksiazki.</li>



<li>Dodaj metodę najpopularniejsza_ksiazka() do Biblioteki.</li>



<li>Zapisz bibliotekę do pliku JSON.</li>
</ol>



<h3 class="wp-block-heading">Zadania praktyczne &#8211; Sklep</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Produkt</code> (nazwa, cena, ilosc_w_magazynie).</li>



<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Koszyk</code> przechowującą produkty do zakupu.</li>



<li>Dodaj metody dodaj_do_koszyka(), usun_z_koszyka().</li>



<li>Dodaj metodę oblicz_wartosc_koszyka().</li>



<li>Dodaj metodę zrealizuj_zamowienie() (zmniejsza stan magazynowy).</li>



<li>Dodaj kategorie produktów (kompozycja lub dziedziczenie).</li>



<li>Dodaj kody rabatowe (klasa Rabat).</li>



<li>Dodaj historię zamówień (klasa Zamowienie).</li>



<li>Stwórz system logowania (klasa Uzytkownik).</li>



<li>Dodaj oceny produktów.</li>
</ol>



<h3 class="wp-block-heading">Zadania praktyczne &#8211; Gra RPG</h3>



<ol class="wp-block-list">
<li>Stwórz klasę <code class="prettyprint lang-sql" style="font-size: 0.85em;">Postac</code> (imię, hp, atak, obrona).</li>



<li>Dodaj metody atakuj() i otrzymaj_obrazenia().</li>



<li>Stwórz klasy <code class="prettyprint lang-sql" style="font-size: 0.85em;">Wojownik</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">Mag</code>, <code class="prettyprint lang-sql" style="font-size: 0.85em;">Lucznik</code> dziedziczące po Postac.</li>



<li>Dodaj system poziomów i doświadczenia.</li>



<li>Dodaj ekwipunek (kompozycja &#8211; klasa Przedmiot).</li>



<li>Dodaj broń zwiększającą atak (klasa Bron).</li>



<li>Dodaj zbroje zwiększające obronę (klasa Zbroja).</li>



<li>Dodaj umiejętności specjalne dla każdej klasy postaci.</li>



<li>Stwórz system walki turowej.</li>



<li>Dodaj zapisywanie stanu gry do pliku.</li>
</ol>



<h3 class="wp-block-heading">Zadania zaawansowane</h3>



<ol class="wp-block-list">
<li>Stwórz system zarządzania studentami i kursami (wiele klas współpracujących).</li>



<li>Stwórz symulator banku z różnymi typami kont.</li>



<li>Stwórz system rezerwacji hotelu (pokoje, rezerwacje, goście).</li>



<li>Stwórz prosty system CMS (artykuły, autorzy, kategorie).</li>



<li>Stwórz system zarządzania projektami (projekty, zadania, użytkownicy).</li>



<li>Stwórz symulator farmy (rośliny, zwierzęta, zasoby).</li>



<li>Stwórz system biblioteki muzycznej (utwory, albumy, artyści, playlisty).</li>



<li>Stwórz prosty system e-learningowy (kursy, lekcje, quizy).</li>



<li>Stwórz system zarządzania restauracją (menu, zamówienia, stoły).</li>



<li>Stwórz grę tekstową z systemem lokacji, przedmiotów i postaci.</li>
</ol>
<p>Artykuł <a href="https://kamakaczmarek.net/16-python-obiektowo/">16. Python &#8211; obiektowo</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>15. Python &#8211; obsługa błędów i wyjątków</title>
		<link>https://kamakaczmarek.net/15-python-obsluga-bledow-i-wyjatkow/</link>
		
		<dc:creator><![CDATA[Kama]]></dc:creator>
		<pubDate>Tue, 02 Jun 2026 09:22:26 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://kamakaczmarek.net/?p=3991</guid>

					<description><![CDATA[<p>Błędy (errors) i wyjątki (exceptions) to sytuacje, które przerywają normalne wykonanie programu. Bez odpowiedniej obsługi program po prostu się &#8222;wysypie&#8221; i zakończy działanie. Dlaczego ważna jest obsługa błędów? Przykład bez obsługi błędu: Z obsługą błędu: Struktura try-except Podstawowa składnia Pełna struktura Kolejność: Podstawowe typy błędów FileNotFoundError &#8211; brak pliku Obsługa: KeyError &#8211; brak klucza w słowniku Obsługa: IndexError [&#8230;]</p>
<p>Artykuł <a href="https://kamakaczmarek.net/15-python-obsluga-bledow-i-wyjatkow/">15. Python &#8211; obsługa błędów i wyjątków</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Błędy</strong> (errors) i <strong>wyjątki</strong> (exceptions) to sytuacje, które przerywają normalne wykonanie programu. Bez odpowiedniej obsługi program po prostu się &#8222;wysypie&#8221; i zakończy działanie.</p>



<p class="wp-block-paragraph"><strong>Dlaczego ważna jest obsługa błędów?</strong></p>



<ul class="wp-block-list">
<li>Program nie kończy działania przy błędzie</li>



<li>Możesz reagować na błędy (np. prosić użytkownika o poprawne dane)</li>



<li>Lepsze doświadczenie użytkownika</li>



<li>Łatwiejsze debugowanie</li>



<li>Profesjonalny kod produkcyjny</li>
</ul>



<p class="wp-block-paragraph"><strong>Przykład bez obsługi błędu:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Program się wysypie jeśli plik nie istnieje
with open("nieistniejacy.txt") as file:
    content = file.read()
# FileNotFoundError - program kończy działanie</code></pre>



<p class="wp-block-paragraph"><strong>Z obsługą błędu:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Program kontynuuje działanie
try:
    with open("nieistniejacy.txt") as file:
        content = file.read()
except FileNotFoundError:
    print("Plik nie istnieje, tworzę nowy")
    with open("nieistniejacy.txt", "w") as file:
        file.write("Nowa zawartość")</code></pre>



<h2 class="wp-block-heading">Struktura try-except</h2>



<p class="wp-block-paragraph">Podstawowa składnia</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    # Kod, który może wywołać błąd
    ryzykowna_operacja()
except:
    # Kod wykonywany gdy wystąpi błąd
    obsluga_bledu()</code></pre>



<p class="wp-block-paragraph">Pełna struktura</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    # Spróbuj wykonać ten kod
    kod_ktory_moze_wywolac_blad()
except TypBledu:
    # Wykonaj gdy wystąpi konkretny błąd
    obsluga_bledu()
else:
    # Wykonaj TYLKO jeśli NIE było błędu
    kod_gdy_sukces()
finally:
    # Wykonaj ZAWSZE (bez względu na błędy)
    sprzatanie()</code></pre>



<p class="wp-block-paragraph"><strong>Kolejność:</strong></p>



<ol class="wp-block-list">
<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">try</code> &#8211; zawsze jako pierwsze</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">except</code> &#8211; jeden lub więcej</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">else</code> &#8211; opcjonalnie, tylko jeśli nie było błędu</li>



<li><code class="prettyprint lang-sql" style="font-size: 0.85em;">finally</code> &#8211; opcjonalnie, wykonuje się zawsze</li>
</ol>



<h2 class="wp-block-heading">Podstawowe typy błędów</h2>



<h3 class="wp-block-heading">FileNotFoundError &#8211; brak pliku</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Błąd: próba otwarcia nieistniejącego pliku
with open("nieistniejacy.txt") as file:
    content = file.read()
# FileNotFoundError: &#91;Errno 2] No such file or directory: 'nieistniejacy.txt'</code></pre>



<p class="wp-block-paragraph"><strong>Obsługa:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    with open("nieistniejacy.txt") as file:
        content = file.read()
except FileNotFoundError:
    print("Plik nie istnieje!")</code></pre>



<h3 class="wp-block-heading">KeyError &#8211; brak klucza w słowniku</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Błąd: próba dostępu do nieistniejącego klucza
slownik = {"imie": "Jan", "wiek": 25}
miasto = slownik&#91;"miasto"]
# KeyError: 'miasto'</code></pre>



<p class="wp-block-paragraph"><strong>Obsługa:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">slownik = {"imie": "Jan", "wiek": 25}

try:
    miasto = slownik&#91;"miasto"]
except KeyError:
    print("Klucz 'miasto' nie istnieje")
    miasto = "Nieznane"</code></pre>



<h3 class="wp-block-heading">IndexError &#8211; indeks poza zakresem</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Błąd: próba dostępu do nieistniejącego indeksu
lista = &#91;"Python", "Java", "C++"]
jezyk = lista&#91;5]
# IndexError: list index out of range</code></pre>



<p class="wp-block-paragraph"><strong>Obsługa:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">lista = &#91;"Python", "Java", "C++"]

try:
    jezyk = lista&#91;5]
except IndexError:
    print("Indeks poza zakresem listy")</code></pre>



<h3 class="wp-block-heading">ValueError &#8211; nieprawidłowa wartość</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Błąd: konwersja niepoprawnej wartości
wiek = int("dwadzieścia")
# ValueError: invalid literal for int() with base 10: 'dwadzieścia'</code></pre>



<p class="wp-block-paragraph"><strong>Obsługa:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    wiek = int(input("Podaj wiek: "))
except ValueError:
    print("To nie jest liczba!")
    wiek = 0</code></pre>



<h3 class="wp-block-heading">TypeError &#8211; nieprawidłowy typ</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Błąd: dodawanie string + int
tekst = "Python"
wynik = tekst + 5
# TypeError: can only concatenate str (not "int") to str</code></pre>



<p class="wp-block-paragraph"><strong>Obsługa:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">tekst = "Python"

try:
    wynik = tekst + 5
except TypeError:
    print("Nie można dodać liczby do tekstu")
    wynik = tekst + str(5)</code></pre>



<h3 class="wp-block-heading">ZeroDivisionError &#8211; dzielenie przez zero</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Błąd: dzielenie przez 0
wynik = 10 / 0
# ZeroDivisionError: division by zero</code></pre>



<p class="wp-block-paragraph"><strong>Obsługa:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    wynik = 10 / 0
except ZeroDivisionError:
    print("Nie można dzielić przez zero!")
    wynik = None</code></pre>



<h2 class="wp-block-heading">Przechwytywanie konkretnych błędów</h2>



<h3 class="wp-block-heading">ŹLE &#8211; ogólny except</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># ŹLE - łapie WSZYSTKIE błędy
try:
    with open("plik.txt") as file:
        content = file.read()
    slownik = {"klucz": "wartość"}
    print(slownik&#91;"nieistniejacy"])
except:
    print("Jakiś błąd")  # Który? Nie wiadomo!</code></pre>



<p class="wp-block-paragraph"><strong>Problemy:</strong></p>



<ul class="wp-block-list">
<li>Nie wiesz jaki błąd wystąpił</li>



<li>Trudno debugować</li>



<li>Możesz ukryć poważne błędy</li>



<li>Nie możesz różnie reagować na różne błędy</li>
</ul>



<h3 class="wp-block-heading">DOBRZE &#8211; konkretne except</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># DOBRZE - konkretne błędy
try:
    with open("plik.txt") as file:
        content = file.read()
    slownik = {"klucz": "wartość"}
    print(slownik&#91;"nieistniejacy"])
except FileNotFoundError:
    print("Plik nie istnieje")
except KeyError as e:
    print(f"Klucz {e} nie istnieje w słowniku")</code></pre>



<h3 class="wp-block-heading">Wiele except</h3>



<p class="wp-block-paragraph">Możesz mieć wiele bloków <code class="prettyprint lang-sql" style="font-size: 0.85em;">except</code> dla różnych błędów.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    liczba = int(input("Podaj liczbę: "))
    wynik = 100 / liczba
    print(f"Wynik: {wynik}")
except ValueError:
    print("To nie jest liczba!")
except ZeroDivisionError:
    print("Nie można dzielić przez zero!")
except KeyboardInterrupt:
    print("\nPrzerwano przez użytkownika")</code></pre>



<h3 class="wp-block-heading">Przypisanie błędu do zmiennej</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    slownik = {"imie": "Jan"}
    print(slownik&#91;"nazwisko"])
except KeyError as error:
    print(f"Błąd: brak klucza '{error}'")
    # Błąd: brak klucza 'nazwisko'</code></pre>



<p class="wp-block-paragraph"><strong>Inne przykłady:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    plik = open("nieistniejacy.txt")
except FileNotFoundError as e:
    print(f"Szczegóły błędu: {e}")

try:
    wynik = int("abc")
except ValueError as e:
    print(f"Błąd konwersji: {e}")</code></pre>



<h3 class="wp-block-heading">Jeden except dla wielu błędów</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;"># Obsługa wielu błędów tym samym kodem
try:
    # Kod ryzykowny
    operacja()
except (ValueError, TypeError, KeyError) as e:
    print(f"Wystąpił błąd: {e}")</code></pre>



<h2 class="wp-block-heading">Blok else</h2>



<p class="wp-block-paragraph">Blok <code class="prettyprint lang-sql" style="font-size: 0.85em;">else</code> wykonuje się <strong>TYLKO</strong> gdy w <code class="prettyprint lang-sql" style="font-size: 0.85em;">try</code> <strong>NIE</strong> było błędu.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    with open("plik.txt") as file:
        content = file.read()
except FileNotFoundError:
    print("Plik nie istnieje")
else:
    # Wykonuje się TYLKO gdy plik został poprawnie otwarty
    print("Zawartość pliku:")
    print(content)</code></pre>



<h3 class="wp-block-heading">Przykład &#8211; walidacja danych</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    wiek = int(input("Podaj wiek: "))
except ValueError:
    print("To nie jest liczba!")
else:
    # Wykonuje się tylko gdy konwersja się powiodła
    if wiek >= 18:
        print("Jesteś pełnoletni")
    else:
        print("Jesteś niepełnoletni")</code></pre>



<h2 class="wp-block-heading">Blok finally</h2>



<p class="wp-block-paragraph">Blok <code class="prettyprint lang-sql" style="font-size: 0.85em;">finally</code> wykonuje się <strong>ZAWSZE</strong>, niezależnie czy był błąd czy nie.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    plik = open("dane.txt", "w")
    plik.write("Dane")
except IOError:
    print("Błąd zapisu")
else:
    print("Zapis udany")
finally:
    # ZAWSZE zamknij plik (czy był błąd czy nie)
    plik.close()
    print("Plik zamknięty")</code></pre>



<p class="wp-block-paragraph"><strong>Typowe zastosowania <code class="prettyprint lang-sql" style="font-size: 0.85em;">finally</code>:</strong></p>



<ul class="wp-block-list">
<li>Zamykanie plików</li>



<li>Zamykanie połączeń z bazą danych</li>



<li>Zwalnianie zasobów</li>



<li>Sprzątanie po operacji</li>
</ul>



<h3 class="wp-block-heading">Przykład &#8211; finally zawsze się wykona</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    print("Try")
    raise ValueError("Błąd!")
except ValueError:
    print("Except - złapano błąd")
else:
    print("Else - nie wykona się (był błąd)")
finally:
    print("Finally - zawsze się wykona")</code></pre>



<p class="wp-block-paragraph"><strong>Wynik:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">Try
Except - złapano błąd
Finally - zawsze się wykona</code></pre>



<h2 class="wp-block-heading">Wywoływanie własnych błędów &#8211; raise</h2>



<p class="wp-block-paragraph">Możesz <strong>ręcznie wywołać błąd</strong> używając słowa kluczowego <code class="prettyprint lang-sql" style="font-size: 0.85em;">raise</code>.</p>



<p class="wp-block-paragraph">Podstawowa składnia</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">raise TypBledu("Komunikat błędu")</code></pre>



<h3 class="wp-block-heading">Przykład &#8211; walidacja wzrostu</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def oblicz_bmi(waga, wzrost):
    """Oblicza BMI z walidacją danych."""
    
    if wzrost > 3:
        raise ValueError("Wzrost człowieka nie przekracza 3 metrów!")
    
    if wzrost &lt;= 0:
        raise ValueError("Wzrost musi być większy od 0!")
    
    if waga &lt;= 0:
        raise ValueError("Waga musi być większa od 0!")
    
    bmi = waga / (wzrost ** 2)
    return bmi

# Użycie
try:
    wynik = oblicz_bmi(70, 3.5)
except ValueError as e:
    print(f"Błąd: {e}")
    # Błąd: Wzrost człowieka nie przekracza 3 metrów!</code></pre>



<h3 class="wp-block-heading">Przykład &#8211; funkcja z walidacją</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def podziel(a, b):
    """Dzieli dwie liczby z walidacją."""
    
    if not isinstance(a, (int, float)):
        raise TypeError("Pierwszy argument musi być liczbą")
    
    if not isinstance(b, (int, float)):
        raise TypeError("Drugi argument musi być liczbą")
    
    if b == 0:
        raise ZeroDivisionError("Nie można dzielić przez zero")
    
    return a / b

# Użycie
try:
    wynik = podziel(10, 0)
except ZeroDivisionError as e:
    print(f"Błąd: {e}")</code></pre>



<h3 class="wp-block-heading">Re-raise &#8211; ponowne wywołanie błędu</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">try:
    wynik = 10 / 0
except ZeroDivisionError:
    print("Logowanie błędu...")
    raise  # Ponownie wywołaj ten sam błąd</code></pre>



<h2 class="wp-block-heading">Przykłady praktyczne</h2>



<h3 class="wp-block-heading">Przykład 1: Bezpieczny input liczby</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def pobierz_liczbe(komunikat):
    """Pobiera liczbę od użytkownika z walidacją."""
    while True:
        try:
            liczba = float(input(komunikat))
            return liczba
        except ValueError:
            print("To nie jest liczba! Spróbuj ponownie.")

# Użycie
wiek = pobierz_liczbe("Podaj wiek: ")
print(f"Twój wiek: {wiek}")</code></pre>



<h3 class="wp-block-heading">Przykład 2: Kalkulator z obsługą błędów</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def kalkulator():
    """Prosty kalkulator z obsługą błędów."""
    try:
        a = float(input("Pierwsza liczba: "))
        b = float(input("Druga liczba: "))
        operator = input("Operator (+, -, *, /): ")
        
        if operator == "+":
            wynik = a + b
        elif operator == "-":
            wynik = a - b
        elif operator == "*":
            wynik = a * b
        elif operator == "/":
            if b == 0:
                raise ZeroDivisionError("Nie można dzielić przez zero!")
            wynik = a / b
        else:
            raise ValueError(f"Nieznany operator: {operator}")
        
        print(f"Wynik: {wynik}")
        
    except ValueError as e:
        print(f"Błąd wartości: {e}")
    except ZeroDivisionError as e:
        print(f"Błąd dzielenia: {e}")
    except Exception as e:
        print(f"Nieoczekiwany błąd: {e}")

kalkulator()</code></pre>



<h3 class="wp-block-heading">Przykład 3: Bezpieczne otwieranie pliku</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def wczytaj_plik(nazwa):
    """Bezpiecznie wczytuje plik."""
    try:
        with open(nazwa, 'r', encoding='utf-8') as plik:
            return plik.read()
    except FileNotFoundError:
        print(f"Plik {nazwa} nie istnieje")
        return None
    except PermissionError:
        print(f"Brak uprawnień do pliku {nazwa}")
        return None
    except Exception as e:
        print(f"Nieoczekiwany błąd: {e}")
        return None

# Użycie
zawartosc = wczytaj_plik("dane.txt")
if zawartosc:
    print(zawartosc)</code></pre>



<h3 class="wp-block-heading">Przykład 4: Słownik z domyślnymi wartościami</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def pobierz_wartosc(slownik, klucz, domyslna=None):
    """Pobiera wartość ze słownika z obsługą błędów."""
    try:
        return slownik&#91;klucz]
    except KeyError:
        print(f"Klucz '{klucz}' nie istnieje, zwracam wartość domyślną")
        return domyslna

# Użycie
dane = {"imie": "Jan", "wiek": 25}
miasto = pobierz_wartosc(dane, "miasto", "Warszawa")
print(f"Miasto: {miasto}")  # Miasto: Warszawa</code></pre>



<h3 class="wp-block-heading">Przykład 5: Lista z bezpiecznym dostępem</h3>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def bezpieczny_dostep(lista, indeks):
    """Bezpieczny dostęp do elementu listy."""
    try:
        return lista&#91;indeks]
    except IndexError:
        print(f"Indeks {indeks} poza zakresem (0-{len(lista)-1})")
        return None
    except TypeError:
        print("Lista jest None lub indeks nie jest liczbą")
        return None

# Użycie
owoce = &#91;"jabłko", "banan", "gruszka"]
owoc = bezpieczny_dostep(owoce, 5)
print(owoc)  # None</code></pre>



<h3 class="wp-block-heading">Przykład 6: Przechwyć błędy w funkcji make_pie</h3>



<p class="wp-block-paragraph"><strong>Problem:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">fruits = &#91;"Apple", "Pear", "Orange"]

def make_pie(index):
    fruit = fruits&#91;index]
    print(fruit + " pie")

make_pie(4)  # IndexError!</code></pre>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">fruits = &#91;"Apple", "Pear", "Orange"]

def make_pie(index):
    try:
        fruit = fruits&#91;index]
    except IndexError:
        print(f"Nie mamy takiego składnika. Wybierz 0-{len(fruits)-1}")
    else:
        print(fruit + " pie")

make_pie(4)  # Nie mamy takiego składnika. Wybierz 0-2
make_pie(1)  # Pear pie</code></pre>



<h3 class="wp-block-heading">Przykład 7: Zapobiegnij błędom w postach</h3>



<p class="wp-block-paragraph"><strong>Problem:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">facebook_posts = &#91;
    {'Likes': 21, 'Comments': 2},
    {'Likes': 13, 'Comments': 2, 'Shares': 1},
    {'Likes': 33, 'Comments': 8, 'Shares': 3},
    {'Comments': 4, 'Shares': 2},  # Brak 'Likes'
    {'Comments': 1, 'Shares': 1},  # Brak 'Likes'
    {'Likes': 19, 'Comments': 3}
]

total_likes = 0
for post in facebook_posts:
    total_likes = total_likes + post&#91;'Likes']  # KeyError!</code></pre>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">facebook_posts = &#91;
    {'Likes': 21, 'Comments': 2},
    {'Likes': 13, 'Comments': 2, 'Shares': 1},
    {'Likes': 33, 'Comments': 8, 'Shares': 3},
    {'Comments': 4, 'Shares': 2},
    {'Comments': 1, 'Shares': 1},
    {'Likes': 19, 'Comments': 3}
]

total_likes = 0

for post in facebook_posts:
    try:
        total_likes += post&#91;'Likes']
    except KeyError:
        # Post nie ma 'Likes', pomijamy
        pass

print(f"Łączna liczba polubień: {total_likes}")
# Łączna liczba polubień: 86</code></pre>



<p class="wp-block-paragraph"><strong>Alternatywne rozwiązanie (bez try-except):</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">total_likes = 0
for post in facebook_posts:
    total_likes += post.get('Likes', 0)
print(f"Łączna liczba polubień: {total_likes}")</code></pre>



<h3 class="wp-block-heading">Przykład 8: Program dzielący liczby</h3>



<p class="wp-block-paragraph"><strong>Wymagania:</strong></p>



<ul class="wp-block-list">
<li>Pobierz dwie liczby</li>



<li>Podziel pierwszą przez drugą</li>



<li>Obsłuż: zły format, dzielenie przez 0, inne błędy</li>
</ul>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def dziel_liczby():
    """Program dzielący dwie liczby z pełną obsługą błędów."""
    try:
        # Pobranie liczb
        a = float(input("Podaj pierwszą liczbę: "))
        b = float(input("Podaj drugą liczbę: "))
        
        # Dzielenie
        wynik = a / b
        
    except ValueError:
        print("Błąd: Podano nieprawidłowy format liczby!")
    except ZeroDivisionError:
        print("Błąd: Nie można dzielić przez zero!")
    except KeyboardInterrupt:
        print("\nProgram przerwany przez użytkownika")
    except Exception as e:
        print(f"Nieoczekiwany błąd: {e}")
    else:
        print(f"Wynik dzielenia: {wynik:.2f}")
    finally:
        print("Koniec operacji")

# Uruchomienie
dziel_liczby()</code></pre>



<p class="wp-block-paragraph"><strong>Ulepszona wersja z pętlą:</strong></p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def dziel_liczby_petla():
    """Wersja z ponawianiem przy błędach."""
    while True:
        try:
            a = float(input("\nPodaj pierwszą liczbę (lub 'q' aby wyjść): "))
            b = float(input("Podaj drugą liczbę: "))
            
            if b == 0:
                raise ZeroDivisionError("Dzielenie przez zero!")
            
            wynik = a / b
            print(f"Wynik: {a} / {b} = {wynik:.2f}")
            break
            
        except ValueError:
            odpowiedz = input("Nieprawidłowy format! Spróbować ponownie? (t/n): ")
            if odpowiedz.lower() != 't':
                break
        except ZeroDivisionError as e:
            print(f"Błąd: {e}")
            odpowiedz = input("Spróbować ponownie? (t/n): ")
            if odpowiedz.lower() != 't':
                break

dziel_liczby_petla()</code></pre>



<h2 class="wp-block-heading">Tworzenie własnych klas wyjątków</h2>



<p class="wp-block-paragraph">Możesz tworzyć <strong>własne typy wyjątków</strong> dziedzicząc po <code class="prettyprint lang-sql" style="font-size: 0.85em;">Exception</code>.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">class BledWalidacji(Exception):
    """Własny wyjątek dla błędów walidacji."""
    pass

class UjemnaWartoscError(BledWalidacji):
    """Wyjątek dla ujemnych wartości."""
    pass

def oblicz_pierwiastek(liczba):
    """Oblicza pierwiastek z walidacją."""
    if liczba &lt; 0:
        raise UjemnaWartoscError("Nie można obliczyć pierwiastka z liczby ujemnej!")
    
    return liczba ** 0.5

# Użycie
try:
    wynik = oblicz_pierwiastek(-5)
except UjemnaWartoscError as e:
    print(f"Błąd: {e}")</code></pre>



<h2 class="wp-block-heading">Assertion &#8211; assert</h2>



<p class="wp-block-paragraph"><code class="prettyprint lang-sql" style="font-size: 0.85em;">assert</code> służy do sprawdzania <strong>założeń</strong> w kodzie podczas developmentu.</p>



<pre class="wp-block-code prettyprint lang-sql has-small-font-size" style="font-size: 0.85em;"><code class="prettyprint lang-sql" style="font-size: 0.85em;">def podziel(a, b):
    """Dzieli a przez b."""
    assert b != 0, "Dzielnik nie może być zerem!"
    return a / b

# Użycie
wynik = podziel(10, 2)  # OK
wynik = podziel(10, 0)  # AssertionError: Dzielnik nie może być zerem!</code></pre>



<p class="wp-block-paragraph"><strong>Uwaga:</strong> <code class="prettyprint lang-sql" style="font-size: 0.85em;">assert</code> jest wyłączany w trybie produkcyjnym (<code class="prettyprint lang-sql" style="font-size: 0.85em;">python -O</code>). Do walidacji w produkcji używaj <code class="prettyprint lang-sql" style="font-size: 0.85em;">if</code> + <code class="prettyprint lang-sql" style="font-size: 0.85em;">raise</code>.</p>



<h2 class="wp-block-heading">Dobre praktyki</h2>



<ul class="wp-block-list">
<li>Łap konkretne błędy</li>



<li>Nie ukrywaj błędów</li>



<li>Obsługuj tylko to co potrafisz</li>



<li>Używaj finally do sprzątania</li>



<li>Informacyjne komunikaty błędów</li>
</ul>



<h2 class="wp-block-heading">Ćwiczenia &#8211; Obsługa błędów i wyjątków</h2>



<h3 class="wp-block-heading">Podstawy try-except</h3>



<ol class="wp-block-list">
<li>Napisz program który próbuje otworzyć plik &#8222;dane.txt&#8221;. Obsłuż błąd gdy plik nie istnieje.</li>



<li>Pobierz od użytkownika liczbę. Obsłuż błąd gdy wpisze tekst zamiast liczby.</li>



<li>Stwórz listę 3 elementów. Spróbuj pobrać element o indeksie 5 i obsłuż błąd.</li>



<li>Stwórz słownik z 3 kluczami. Spróbuj pobrać nieistniejący klucz i obsłuż błąd.</li>



<li>Napisz program dzielący dwie liczby. Obsłuż dzielenie przez zero.</li>



<li>Spróbuj dodać string do liczby i obsłuż błąd TypeError.</li>



<li>Napisz program który próbuje skonwertować &#8222;abc&#8221; na int. Obsłuż błąd.</li>



<li>Pobierz od użytkownika indeks listy. Obsłuż błąd gdy podadzielny typ lub poza zakresem.</li>



<li>Otwórz plik do zapisu w katalogu bez uprawnień. Obsłuż PermissionError.</li>



<li>Napisz program który łapie KeyboardInterrupt (Ctrl+C) i wyświetla komunikat.</li>
</ol>



<h3 class="wp-block-heading">Wiele except</h3>



<ol class="wp-block-list">
<li>Napisz kalkulator obsługujący ValueError i ZeroDivisionError.</li>



<li>Napisz funkcję otwierającą plik obsługującą FileNotFoundError i PermissionError.</li>



<li>Pobierz od użytkownika wiek. Obsłuż ValueError i sprawdź czy nie jest ujemny (ValueError).</li>



<li>Napisz program dostępu do słownika obsługujący KeyError i TypeError.</li>



<li>Napisz funkcję konwertującą string na liczbę obsługującą ValueError i TypeError.</li>
</ol>



<h3 class="wp-block-heading">Przypisanie błędu do zmiennej</h3>



<ol class="wp-block-list">
<li>Złap KeyError i wyświetl komunikat zawierający nazwę brakującego klucza.</li>



<li>Złap ValueError i wyświetl dokładny komunikat błędu.</li>



<li>Złap FileNotFoundError i wyświetl nazwę brakującego pliku.</li>



<li>Złap wszystkie wyjątki jako zmienną i wyświetl ich typ.</li>



<li>Złap IndexError i wyświetl komunikat z podanym indeksem.</li>
</ol>



<h3 class="wp-block-heading">Blok else</h3>



<ol class="wp-block-list">
<li>Napisz program który próbuje otworzyć plik. W bloku else wyświetl jego zawartość.</li>



<li>Pobierz liczbę od użytkownika. W else oblicz jej kwadrat.</li>



<li>Otwórz plik do zapisu. W else zapisz dane. Obsłuż błędy.</li>



<li>Pobierz dwie liczby i podziel. W else wyświetl wynik.</li>



<li>Wczytaj dane ze słownika. W else przetwórz dane.</li>
</ol>



<h3 class="wp-block-heading">Blok finally</h3>



<ol class="wp-block-list">
<li>Otwórz plik i zagwarantuj jego zamknięcie w finally.</li>



<li>Napisz funkcję która zawsze wyświetla &#8222;Koniec&#8221; w finally.</li>



<li>Zaimplementuj licznik prób w finally.</li>



<li>Zapisz log operacji w finally (czy była udana czy nie).</li>



<li>Zmierz czas operacji w finally.</li>
</ol>



<h3 class="wp-block-heading">raise &#8211; wywoływanie błędów</h3>



<ol class="wp-block-list">
<li>Napisz funkcję sprawdzającą wiek. Wywołaj ValueError gdy wiek > 150.</li>



<li>Napisz funkcję obliczającą pierwiastek. Wywołaj ValueError dla liczb ujemnych.</li>



<li>Napisz funkcję dzielącą. Wywołaj ZeroDivisionError dla dzielnika = 0.</li>



<li>Napisz funkcję walidującą email. Wywołaj ValueError gdy brak @ .</li>



<li>Napisz funkcję sprawdzającą hasło (min 8 znaków). Wywołaj ValueError gdy za krótkie.</li>



<li>Napisz funkcję która wywołuje TypeError gdy argument nie jest typu int.</li>



<li>Napisz funkcję walidującą PESEL (11 cyfr). Wywołaj ValueError gdy niepoprawny.</li>



<li>Napisz funkcję sprawdzającą czy liczba jest w zakresie 1-100. Wywołaj ValueError gdy nie.</li>



<li>Napisz funkcję która wywołuje FileNotFoundError gdy podano pustą nazwę pliku.</li>



<li>Napisz funkcję walidującą numer telefonu (9 cyfr). Wywołaj ValueError gdy błędny.</li>
</ol>



<h3 class="wp-block-heading">Walidacja danych użytkownika</h3>



<ol class="wp-block-list">
<li>Napisz funkcję pobierającą dodatnią liczbę całkowitą. Powtarzaj dopóki nie będzie poprawna.</li>



<li>Napisz funkcję pobierającą liczbę z zakresu 1-10. Waliduj i powtarzaj.</li>



<li>Napisz funkcję pobierającą tak/nie. Akceptuj tylko te wartości.</li>



<li>Napisz funkcję pobierającą datę w formacie DD-MM-YYYY. Waliduj format.</li>



<li>Napisz funkcję pobierającą ocenę 1-6. Waliduj zakres.</li>
</ol>



<h3 class="wp-block-heading">Funkcje z obsługą błędów</h3>



<ol class="wp-block-list">
<li>Napisz funkcję bezpiecznego dzielenia zwracającą None przy błędzie.</li>



<li>Napisz funkcję bezpiecznego dostępu do listy zwracającą wartość domyślną.</li>



<li>Napisz funkcję bezpiecznego dostępu do słownika z wartością domyślną.</li>



<li>Napisz funkcję bezpiecznie konwertującą na int (zwraca 0 przy błędzie).</li>



<li>Napisz funkcję bezpiecznie otwierającą plik (zwraca None przy błędzie).</li>
</ol>



<h3 class="wp-block-heading">Praca z plikami</h3>



<ol class="wp-block-list">
<li>Napisz program który tworzy plik jeśli nie istnieje, otwiera jeśli istnieje.</li>



<li>Napisz funkcję kopiującą plik z obsługą wszystkich błędów.</li>



<li>Napisz program który próbuje wczytać JSON. Obsłuż błąd parsowania.</li>



<li>Napisz funkcję dopisującą do logu z obsługą błędów.</li>



<li>Napisz funkcję usuwającą plik z obsługą błędów.</li>
</ol>



<h3 class="wp-block-heading">Praca ze słownikami i listami</h3>



<ol class="wp-block-list">
<li>Napisz funkcję bezpiecznie pobierającą wartość zagnieżdżoną ze słownika.</li>



<li>Napisz funkcję aktualizującą słownik z obsługą błędów.</li>



<li>Napisz funkcję usuwającą element z listy po wartości (obsłuż ValueError).</li>



<li>Napisz funkcję sortującą listę mieszanych typów (obsłuż TypeError).</li>



<li>Napisz funkcję łączącą dwa słowniki z obsługą błędów.</li>
</ol>



<h3 class="wp-block-heading">Konwersje i parsowanie</h3>



<ol class="wp-block-list">
<li>Napisz funkcję konwertującą string na float z obsługą błędów.</li>



<li>Napisz funkcję parsującą datę z różnych formatów.</li>



<li>Napisz funkcję konwertującą string na bool (tak/nie, true/false, 1/0).</li>



<li>Napisz funkcję parsującą listę liczb z stringa &#8222;1,2,3,4,5&#8221;.</li>



<li>Napisz funkcję konwertującą temperaturę z obsługą błędnych jednostek.</li>
</ol>



<h3 class="wp-block-heading">Matematyka</h3>



<ol class="wp-block-list">
<li>Napisz funkcję obliczającą silnię. Wywołaj ValueError dla n &lt; 0.</li>



<li>Napisz funkcję obliczającą pierwiastek z walidacją.</li>



<li>Napisz funkcję obliczającą potęgę. Obsłuż OverflowError.</li>



<li>Napisz funkcję obliczającą logarytm. Waliduj argument > 0.</li>



<li>Napisz funkcję obliczającą procent. Waliduj zakres 0-100.</li>
</ol>



<h3 class="wp-block-heading">Kalkulator rozszerzony</h3>



<ol class="wp-block-list">
<li>Napisz kalkulator z menu i pełną obsługą błędów.</li>



<li>Dodaj historię operacji zapisywaną do pliku (obsłuż błędy).</li>



<li>Dodaj tryb zaawansowany z funkcjami matematycznymi (obsłuż błędy dziedziny).</li>



<li>Dodaj obsługę nawiasów w wyrażeniach.</li>



<li>Dodaj możliwość zapisywania i wczytywania sesji.</li>
</ol>



<h3 class="wp-block-heading">Gry i aplikacje</h3>



<ol class="wp-block-list">
<li>Napisz grę w zgadywanie liczby z pełną walidacją inputu.</li>



<li>Napisz quiz z obsługą błędnych odpowiedzi.</li>



<li>Napisz kółko i krzyżyk z walidacją ruchów.</li>



<li>Napisz prostą grę tekstową z zapisem stanu (obsłuż błędy plików).</li>



<li>Napisz symulator bankomatu z walidacją PIN i kwot.</li>
</ol>



<h3 class="wp-block-heading">Własne wyjątki</h3>



<ol class="wp-block-list">
<li>Stwórz własny wyjątek <code class="prettyprint lang-sql" style="font-size: 0.85em;">NiepoprawnyWiekError</code>.</li>



<li>Stwórz własny wyjątek <code class="prettyprint lang-sql" style="font-size: 0.85em;">BledWalidacjiEmail</code>.</li>



<li>Stwórz hierarchię wyjątków dla aplikacji bankowej.</li>



<li>Stwórz własny wyjątek <code class="prettyprint lang-sql" style="font-size: 0.85em;">BledKonfiguracji</code> z dodatkowymi atrybutami.</li>



<li>Stwórz własny wyjątek <code class="prettyprint lang-sql" style="font-size: 0.85em;">PrzekroczonoLimit</code> z informacją o limicie.</li>
</ol>



<h3 class="wp-block-heading">Assert</h3>



<ol class="wp-block-list">
<li>Użyj assert do sprawdzenia czy lista nie jest pusta przed operacją.</li>



<li>Użyj assert do sprawdzenia typu argumentu funkcji.</li>



<li>Użyj assert do sprawdzenia czy liczba jest w zakresie.</li>



<li>Użyj assert do walidacji długości stringa.</li>



<li>Użyj assert do sprawdzenia niezmiennika klasy.</li>
</ol>



<h3 class="wp-block-heading">Zadania kompleksowe</h3>



<ol class="wp-block-list">
<li>Napisz system logowania użytkownika z pełną walidacją (login, hasło, próby).</li>



<li>Napisz program zarządzający kontami bankowymi z walidacją operacji.</li>



<li>Napisz parser plików konfiguracyjnych z obsługą wszystkich błędów.</li>



<li>Napisz system rezerwacji z walidacją dat, dostępności, konfliktów.</li>



<li>Napisz aplikację TODO z zapisem do pliku i pełną obsługą błędów.</li>



<li>Napisz kalkulator kredytu z walidacją wszystkich parametrów.</li>



<li>Napisz system ocen uczniów z walidacją ocen, obliczaniem średnich, zapisem.</li>



<li>Napisz konwerter walut z obsługą błędów API, walidacją kwot.</li>



<li>Napisz aplikację inwentaryzacji z walidacją stanów, cen, operacji.</li>



<li>Napisz prosty interpreter poleceń z obsługą błędów składni i wykonania.</li>
</ol>



<h3 class="wp-block-heading">Debugging</h3>



<ol class="wp-block-list">
<li>Napisz funkcję która loguje wszystkie wyjątki do pliku z datą, typem, traceback.</li>



<li>Napisz dekorator który łapie i loguje wszystkie wyjątki funkcji.</li>



<li>Napisz kontekst menedżer do obsługi zasobów z automatycznym sprzątaniem.</li>



<li>Napisz funkcję która wyświetla czytelny komunikat błędu dla użytkownika końcowego.</li>



<li>Napisz system retry (ponawiania operacji) z wykładniczym cofaniem.</li>
</ol>



<h3 class="wp-block-heading">Zaawansowane</h3>



<ol class="wp-block-list">
<li>Napisz funkcję która łapie wiele typów wyjątków i reaguje inaczej na każdy.</li>



<li>Napisz funkcję używającą re-raise do propagacji błędu z dodatkowym kontekstem.</li>



<li>Napisz chain wyjątków (raise &#8230; from &#8230;).</li>



<li>Napisz własny context manager używając try-finally.</li>



<li>Napisz wrapper funkcji który zamienia wyjątki na kody błędów.</li>
</ol>
<p>Artykuł <a href="https://kamakaczmarek.net/15-python-obsluga-bledow-i-wyjatkow/">15. Python &#8211; obsługa błędów i wyjątków</a> pochodzi z serwisu <a href="https://kamakaczmarek.net">Kama Kaczmarek</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
