🔩 Nowy Rekrut
0 / 66 umiejętności

PODSTAWY PYTHONA

dla Twórców Gier

Naucz się Pythona od zera — przez pisanie, nie czytanie. Każda sekcja to przykład, zadania z oczekiwanym wynikiem i projekt końcowy. 7 modułów, które dają solidne podstawy przed kursem Pygame.

Python 3 1176 ćwiczeń 7 projektów ~45 h praktyki 0 instalacji Język polski
M00

Witaj — co zbudujesz i jak działa kurs

Witaj w Podstawach Pythona. Tu nauczysz się programować od zera — bez żadnej wcześniejszej wiedzy. Nie przepiszesz cudzego kodu z internetu: każdą linijkę napiszesz sam i zrozumiesz, co robi i dlaczego. To ten sam Python, którym pisze się aplikacje, analizuje dane i automatyzuje powtarzalną robotę — uczymy go na grach, bo najszybciej widać efekt.
🎯 Co zbudujesz — 7 prawdziwych programów
> python baza_graczy.py
=== RANKING GRACZY ===
🥇 Anna  — 1500 pkt
🥈 Marek — 1200 pkt
🥉 Kasia  — 980 pkt
Dodać gracza? (t/n): _
Każdy moduł kończysz działającym programem, który uruchomisz w terminalu i pokażesz:
  • 🃏 M01 → Karta Gracza  ·  ⚖️ M02 → Kalkulator BMI
  • 🏆 M03 → Top 3 Graczy  ·  🎲 M04 → Gra „Zgadnij Liczbę"
  • ⚔️ M05 → Kalkulator RPG  ·  📝 M06 → Analizator tekstu
  • 🗃️ M07 → Baza danych graczy
To nie ćwiczenia w próżni — piszesz prawdziwy Python, od pierwszej linijki do działających aplikacji konsolowych.
Kurs to siedem modułów (M01–M07), a każdy zbudowany jest tak samo: krótka teoria z życiowym przykładem, praktyka — kod, który piszesz i uruchamiasz wprost tu, w przeglądarce (klikasz „Sprawdź", a my od razu mówimy, czy się zgadza), quiz sprawdzający zrozumienie i projekt końcowy. Kurs jest dla każdego, kto zaczyna zupełnie od zera — nie musisz nic umieć z programowania ani niczego instalować, żeby zacząć.
🎉 Dobra wiadomość: w tym kursie nie musisz nic instalować. Kod piszesz i uruchamiasz wprost na stronie, w każdej lekcji — wystarczy przeglądarka. Możesz od razu przejść do Modułu 1 i zacząć pisać.
Dlaczego tak? Bo dla osoby, która dopiero zaczyna, instalowanie Pythona i edytora bywa największą przeszkodą — łatwo się zniechęcić, zanim w ogóle napisze się pierwszą linijkę. Dlatego u nas piszesz kod od razu w przeglądarce, a o instalacji w ogóle nie musisz myśleć.
🛠 Chcesz później programować też poza przeglądarką? (opcjonalne — rozwiń)
Do tego kursu nie jest to potrzebne — ale jeśli zechcesz budować własne, większe projekty i gry (Pygame) na swoim komputerze, możesz w dowolnej chwili zainstalować Pythona i edytor VS Code. Mamy gotową instrukcję krok po kroku, ze zrzutami ekranu:
M01

Twój Pierwszy Program

Napiszesz swój pierwszy program i nauczysz się fundamentów: wypisywania tekstu, zmiennych, obliczeń i rozmowy z użytkownikiem. Każdy program na świecie używa tych właśnie elementów.
Wyobraź sobie przepis kulinarny — lista kroków dla kucharza. Program to lista kroków dla komputera. Python wykonuje je linia po linii, od góry do dołu.
Program to po prostu lista instrukcji — trochę jak przepis kulinarny, tyle że kucharzem jest komputer: czyta go linijka po linijce i wykonuje po kolei. Każda linia kodu = jedna instrukcja dla Pythona, a wynik (to, co program wypisze) zobaczysz od razu pod kodem.
🐍 Jak działa nauka w tym kursie
Nic nie instalujesz, nie tworzysz żadnych plików — wszystko dzieje się tutaj, w przeglądarce:
1
Każda sekcja ma zakładki: 📖 Teoria + ćwiczenia (czytasz i robisz krótkie „szybkie strzały") oraz 🐍 Praktyka (piszesz prawdziwy kod).
2
Wpisujesz kod w okienko i klikasz „Sprawdź" — Python uruchamia go od razu i mówi, czy wynik się zgadza (pierwsze uruchomienie chwilę trwa).
3
Zalicz ćwiczenia z praktyki, żeby odblokować przycisk „dalej" — uczysz się pisząc, nie tylko czytając.
👾 W grze Asteroidy użyjesz tego tak:
zycia = 3           # ile żyć ma gracz
punkty = 0          # wynik w HUD
statek_x = 400      # pozycja x statku (środek ekranu 800px)
predkosc = 5        # pikseli na klatkę
SZEROKOSC = 800     # stała — szerokość okna gry
Każda zmienna w grze to element z tego modułu!
1.1

print() — wyświetlanie tekstu

Wyobraź sobie, że budujesz grę i chcesz, żeby gracz zobaczył wynik, komunikat o wygranej albo wskazówkę, co robić dalej. Jak komputer ma „powiedzieć" coś graczowi? Właśnie przez print(). To polecenie, które każe Pythonowi wypisać tekst w oknie terminala. Bez print() Twój program działa w kompletnej ciszy — liczy, kombinuje, ale nigdy nie pokaże wyniku. Tak jakbyś rozwiązywał coś w głowie i nigdy nie powiedział odpowiedzi na głos.
print() to Twoje pierwsze narzędzie do komunikacji z użytkownikiem. Python ma wbudowanych wiele gotowych poleceń z nazwami — nazywamy je funkcjami. Funkcja to mały, gotowy mechanizm, który coś robi. Żeby zadziałał, musisz go „wywołać": piszesz jego nazwę, a tuż za nią dajesz okrągłe nawiasy (), do których wkładasz to, na czym ma popracować. print działa dokładnie tak — podajesz mu w nawiasach tekst albo liczbę, a on wypisuje to na ekranie. Zobacz:

print("Cześć, Bruno!") > python plik.py Cześć, Bruno!
Dlaczego od print() zaczynamy całą naukę programowania? Bo to najprostszy sposób, żeby zobaczyć, że Twój kod naprawdę działa — że komputer Cię „usłyszał". Każdy większy program, od gry po kalkulator, w którymś momencie musi coś pokazać człowiekowi, a print() jest właśnie tym głosem programu. Bez niego kod liczy w ciszy i nigdy nie zdradza wyniku. Zacznijmy od najprostszego możliwego przykładu:
Ten kod mówi Pythonowi: „wypisz ten tekst". Zwróć uwagę na cudzysłów wokół słów — to obowiązkowe. Cudzysłów mówi Pythonowi: „to jest tekst do wypisania, nie polecenie". Dlaczego to ważne? Bo bez cudzysłowu Python nie wie, że to tekst: bierze słowo za coś, co powinien znać, nie znajduje go i zgłasza błąd. Zobaczysz to za chwilę. Możesz użyć podwójnego "..." lub pojedynczego '...' — oba działają tak samo.
Czas wypisać liczbę. Reguła jest ta sama: cudzysłów oznacza tekst, a 42 to liczba, więc zapisujesz ją bez cudzysłowu. Ten drobiazg robi dużą różnicę: 42 to liczba, którą Python umie dodać i pomnożyć, ale "42" w cudzysłowie to już napis: dwa znaki, które umie tylko skleić z tekstem. Ta różnica jeszcze nieraz da o sobie znać. Zobacz, jak Python wypisuje liczbę:
Czasem warto zostawić pustą linię między dwiema porcjami informacji — tak jak odstęp między akapitami. Wystarczy wywołać print() z pustym środkiem. Weźmy wyniki dwóch graczy: to dwie osobne sekcje, a pusta linia ładnie je rozdziela — od razu widać, gdzie kończy się jeden, a zaczyna drugi. I wbrew pozorom to nie jest tylko ozdoba. Kiedy program wypisuje dużo naraz, to właśnie odstępy decydują o tym, czy gracz w ogóle połapie się w tym, co widzi. Dobry programista myśli o osobie, która będzie czytać wynik, równie troskliwie jak o samym kodzie:
Wróćmy do Bruna i dodajmy mu więcej informacji — poziom, życia, wiadomość na start. To będzie Twój pierwszy ekran startowy: zestaw linii, które gracz widzi, zanim zacznie grać. Zobaczysz, jak kilka zwykłych print() ułożonych jeden pod drugim składa się na coś, co naprawdę wygląda jak początek gry:
W tym kodzie pojawiła się jedna nowość: przecinek w print("Zycia:", 3) — dzięki niemu wypiszesz kilka rzeczy naraz, tutaj tekst i liczbę obok siebie, a Python sam wstawi między nie spację. Wygodne, prawda? Nie musisz ręcznie łączyć tekstu z liczbą — zresztą samo + by tu nie zadziałało, ale do tego wrócimy przy konwersji typów w sekcji 1.8. Puste print() już znasz — tu pracuje dokładnie tak samo jak przed chwilą u Bruna i Marka: oddziela ekran startowy od wiadomości dla gracza.
Na koniec rzecz najważniejsza w tej lekcji — wróćmy na chwilę do cudzysłowu. Mówiliśmy, że jest obowiązkowy; teraz zobaczysz na własne oczy, dlaczego. Zobacz, co się stanie z tym samym tekstem bez cudzysłowu:
NameError: name 'Witaj' is not defined
Bez cudzysłowu Python wziął Witaj za nazwę czegoś, co powinien znać — poszukał, nie znalazł i zgłosił błąd. Dokładnie przed tym chroni cudzysłów: mówi Pythonowi „nie szukaj, po prostu to wypisz". Dlatego tekst zapisujesz ZAWSZE w cudzysłowie: "Witaj" lub 'Witaj'.
Zbierzmy to w całość. print() wypisuje na ekranie wszystko, co włożysz w nawiasy — tekst zawsze w cudzysłowie, liczby bez. Przecinek łączy kilka wartości w jednej linii, a puste print() robi odstęp. Tych kilka prostych chwytów wystarczy, żeby program wreszcie „przemówił" do gracza — a używać ich będziesz dosłownie w każdej kolejnej lekcji, więc warto już teraz poćwiczyć je do skutku.

✔️ Po tej sekcji powinieneś umieć:
  • wywoływać print() z tekstem i liczbą
  • wypisywać kilka wartości w jednym print() przez przecinek
  • tworzyć pustą linię przez print() bez argumentów
🧠 Sprawdź wiedzę — 1.1
Wiesz już jak wypisać tekst i liczby na ekran. Ale za każdym razem przepisujesz wartości ręcznie — co, jeśli imię gracza pojawia się w dziesięciu miejscach? W sekcji 1.2 poznasz zmienne — pudełka na wartości, które Python pamięta przez całe działanie programu.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.2

Zmienne i typy danych — pudełka na dane

Wyobraź sobie, że grasz w grę i masz wynik, imię gracza i liczbę żyć. Gdzie program ma te dane przechowywać? W zmiennych — to takie podpisane pudełka w pamięci komputera. Każde pudełko ma naklejkę (nazwę) i zawartość (wartość). Kiedy wynik rośnie, Python otwiera pudełko wynik i zmienia liczbę w środku.
Zmienną tworzymy, wpisując nazwa = wartość. Znak = to przypisanie — mówi Pythonowi: „weź wartość z prawej strony i włóż ją do pudełka o nazwie z lewej". To nie jest znak równości z matematyki, choć wygląda identycznie. W matematyce x = 5 stwierdza fakt: x jest równe pięć. W Pythonie to polecenie do wykonania: utwórz pudełko o nazwie x i schowaj w nim piątkę.

punkty = 100 punkty 100 nazwa = etykieta na pudełku = wkłada wartość do środka
Dlaczego ta różnica jest ważna? Bo polecenie można wydać ponownie — i właśnie to czyni zmienne „zmiennymi": ich zawartość może się zmieniać w trakcie gry, na przykład gdy wynik gracza rośnie po pokonaniu wroga. Zobacz, co się dzieje w pudełku, gdy Bruno zdobywa punkty:

punkty = 100 punkty = 250 punkty 100 250 nowe nadpisuje — stara znika bez śladu
Zacznijmy od najprostszego przypadku — zmiennej przechowującej tekst. Tekst w Pythonie nazywamy str (od angielskiego string, czyli sznurek liter, bo tekst to ciąg znaków ustawionych jeden za drugim, jak koraliki na sznurku):
Teraz zmienna przechowująca liczbę całkowitą — w Pythonie to typ int (od angielskiego integer = liczba całkowita). Liczby całkowite nie mają cudzysłowu:
Czasem potrzebujemy liczby z częścią dziesiętną — np. pozycja gracza, prędkość, procent. To typ float (od angielskiego floating point = liczba zmiennoprzecinkowa). Używa się kropki, nie przecinka:
Na koniec typ wyjątkowy — bool (od angielskiego boolean, na cześć matematyka George'a Boole'a). Przechowuje tylko dwie możliwe wartości: True (prawda) albo False (fałsz) — i nic poza tym. Sięgasz po niego zawsze, gdy coś jest albo włączone, albo nie: czy gracz żyje, czy gra jest spauzowana, czy poziom został ukończony. Te dwie wartości piszemy wielką literą i bez cudzysłowu, bo to nie tekst, tylko dwa specjalne słowa wbudowane w Pythona.

Bool wróci ze zdwojoną siłą w module o warunkach — to na jego podstawie program będzie podejmował decyzje:
🤔 Spróbuj zgadnąć (nie szkodzi, jeśli jeszcze nie wiesz): Jakiego typu jest wartość True — str, int czy bool?
Odpowiedź
bool — to jeden z 4 typów Pythona. True i False to jego jedyne wartości.
Teraz połącz wszystkie cztery typy w jednym programie — tak mogłyby wyglądać dane gracza tuż po wczytaniu gry. Zwróć uwagę, że wyrównaliśmy znaki = w jednej kolumnie; Python tego nie wymaga, ale robimy tak dlatego, że od razu widać, gdzie kończą się nazwy, a zaczynają wartości:
Jedna ważna zasada: nazwy zmiennych piszemy małymi literami, a słowa łączymy podkreśleniem. To konwencja zwana snake_case — po angielsku snake to wąż, a podkreślenia spinające słowa wyglądają jak wąż pełznący między wyrazami: moje_imie = moje→_→imie. Dlaczego się jej trzymamy? Bo Python rozróżnia wielkie i małe litery — Imie i imie to dla niego dwie różne zmienne. Jedna zasada dla wszystkich = mniej pomyłek:
Co się stanie, jeśli zapomnisz tej zasady? Python sprawdza poprawność kodu zanim go uruchomi — jeśli nazwa zmiennej zaczyna się cyfrą lub ma spację, zatrzymuje się i zgłasza błąd SyntaxError (po angielsku syntax = składnia, czyli zasady języka). Spróbuj:
SyntaxError — Python nie może uruchomić programu bo nazwa zmiennej jest nieprawidłowa. Nazwy zmiennych: zaczynają się literą, nie mają spacji, słowa łączymy podkreśleniem. Poprawnie: moje_imie = "Bruno".
Zbierzmy to w całość. Zmienna to nazwane pudełko w pamięci, do którego operatorem = wkładasz wartość, żeby móc jej użyć później wielokrotnie, bez przepisywania za każdym razem. Python rozpoznaje cztery podstawowe rodzaje tej wartości: tekst (str), liczbę całkowitą (int), liczbę z ułamkiem (float) oraz prawdę albo fałsz (bool). Każdy z nich zachowuje się trochę inaczej, dlatego od początku warto wiedzieć, który typ trzymasz w danym pudełku.

Nazwy zapisujesz małymi literami w stylu snake_case, bo Python rozróżnia wielkość liter, a jedna spójna zasada chroni Cię przed literówkami i pomyłkami. Tych czterech typów i tego sposobu nazywania będziesz używać w każdej kolejnej sekcji — od arytmetyki po pętle — więc to fundament, na którym stanie cała reszta kursu. Im pewniej opanujesz je teraz, tym łatwiej pójdzie wszystko, co dalej.

✔️ Po tej sekcji powinieneś umieć:
  • tworzyć zmienne i przypisywać im wartości operatorem =
  • znać 4 podstawowe typy: str (tekst), int (liczba całkowita), float (ułamek), bool (prawda/fałsz)
  • stosować konwencję snake_case w nazwach zmiennych
🧠 Sprawdź wiedzę — 1.2
Masz już zmienne czterech typów i umiesz nadpisywać ich wartości. Ale czasem trzeba sprawdzić, czym tak naprawdę jest dana wartość — bo 5 i "5" wyglądają podobnie, a zachowują się zupełnie inaczej. W sekcji 1.3 poznasz funkcję type(), którą w każdej chwili zapytasz Pythona, jakiego typu jest dana zmienna.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.3

Funkcja type() — sprawdzanie typów

Wyobraź sobie ekwipunek w grze — masz 5 mieczy i napis „5" na tarczy. Oba wyglądają tak samo, ale są zupełnie inne: liczbę możesz dodać do innych liczb, a tekst możesz tylko złączyć z innym tekstem. Python doskonale wie, co jest czym — to właśnie typ danych. Funkcja type() pozwala ci w każdej chwili zapytać Pythona: hej, co tak naprawdę przechowuje ta zmienna?
type() to kolejna funkcja wbudowana w Pythona — podobnie jak print(), masz ją gotową od razu, bez żadnego importu czy instalacji. Podajesz jej zmienną w nawiasach, a ona w odpowiedzi mówi, jakiego ta zmienna jest typu. Sama w sobie nic nie wyświetla, dlatego zwykle wkładamy ją do środka print() — najpierw type() ustala typ, a dopiero potem print() pokazuje go na ekranie.

Po co w ogóle sprawdzać typ? Bo gdy program zachowuje się dziwnie, zaskakująco często winny jest właśnie typ — wartość, którą bierzesz za liczbę, okazuje się tekstem i działania przestają wychodzić tak, jak chcesz. type() pozwala to wykryć w sekundę, zamiast w nieskończoność zgadywać i tracić czas. Wypróbujmy ją na zmiennych gracza Bruna z poprzedniej lekcji:
Cztery zmienne, cztery różne odpowiedzi. Zobacz, jak Python na nie wpadł — przykłada lupę do każdej wartości po kolei:
"Bruno" 3 2.5 True str int float bool type() patrzy na wartość, nie na nazwę
Lupa nie patrzy na nazwę zmiennej, tylko na to, co siedzi w środku. Tekst w cudzysłowie to zawsze str, liczba całkowita — int, liczba z kropką — float, a True albo False — bool. Python ustala to w chwili tworzenia zmiennej, dlatego nie musisz nigdzie ogłaszać, że zycia będzie liczbą — wpisujesz 3 bez cudzysłowu i wniosek wyciąga się sam. W niektórych innych językach trzeba typ podawać ręcznie przy każdej zmiennej; Python bierze tę robotę na siebie.
🧠 Teraz już to wiesz — sprawdź się: Jaki typ zwróci type("5") — int czy str?
Odpowiedź
<class 'str'> — cyfra w cudzysłowie to tekst. Cudzysłów zawsze oznacza str.
Python wypisuje pełną nazwę typu w nawiasach ostrokątnych — <class 'str'>, <class 'int'> i tak dalej. Słowo class znaczy po angielsku „klasa", ale na razie spokojnie czytaj je jako „typ" — pełniejsze znaczenie poznasz dużo później. Najważniejsze jest to, co stoi w środku — 'str' albo 'int' — bo właśnie ten napis mówi Ci, z czym dokładnie masz do czynienia.

Teraz uwaga na pułapkę, która łapie niemal każdego początkującego: cyfra w cudzysłowie to NIE liczba. To tekst, który tylko wygląda jak liczba, ponieważ Python patrzy na cudzysłów, a nie na to, co jest w jego środku:
Widzisz? miecze i napis wypisują na ekranie identyczne 5, ale ich typy są zupełnie różne — jeden to int, drugi to str. Samo patrzenie na wynik niczego tu nie zdradza, ponieważ wygląda tak samo; dopiero type() pokazuje prawdę. To właśnie dlatego ta pułapka jest tak podstępna. A teraz sam to wypróbuj — uruchom poniższy kod i zobacz, co się stanie:
TypeError: can only concatenate str (not "int") to str
I o to chodziło 🙂 — Python nie może dodać tekstu (str) do liczby (int). To jak próba dodania jabłka do kilometra — nie ma sensu. napis wygląda jak liczba, ale cudzysłów robi z niego str, więc + 10 się wykłada. Zawsze sprawdzaj, czy Twoja liczba ma cudzysłów: "5" to tekst, 5 to liczba.

👉 Nie naprawiaj tego kodu — błąd był celowy, chodziło tylko o to, żebyś go zobaczył i zrozumiał. Jak zamienić tekst na liczbę (żeby liczył poprawnie), poznasz w sekcji 1.8 — Konwersja typów.
Zbierzmy to w całość. type() to Twój podręczny wykrywacz typów — wkładasz w nawiasy dowolną zmienną, a Python odpowiada, czym ona naprawdę jest pod spodem. Sięgasz po niego zawsze wtedy, gdy program liczy inaczej, niż się spodziewasz, bo bardzo często powodem okazuje się liczba, która w rzeczywistości jest tekstem zamkniętym w cudzysłowie.

Zapamiętaj jedną zasadę, a oszczędzisz sobie wielu godzin szukania błędów: cudzysłów zawsze oznacza str, nawet wtedy, gdy otacza same cyfry. Ma to ogromne znaczenie, ponieważ dane przychodzące z zewnątrz — z pliku albo od gracza — niemal zawsze są tekstem, więc trzeba je świadomie zamienić, zanim zaczniesz na nich liczyć. Jak dokładnie wykonać taką zamianę, pokaże Ci sekcja o konwersji typów. Na razie wystarczy, że umiesz w każdej chwili zapytać Pythona o typ i spokojnie odczytać jego odpowiedź — to drobne narzędzie zaoszczędzi Ci mnóstwa zgadywania i nerwów przy każdym następnym programie, który napiszesz.

✔️ Po tej sekcji powinieneś umieć:
  • używać type() do sprawdzania typu zmiennej
  • rozróżniać "5" (str — tekst) od 5 (int — liczba)
  • wiedzieć, że TypeError pojawia się, gdy mieszasz typy, których nie można łączyć
🧠 Sprawdź wiedzę — 1.3
Umiesz już sprawdzić, jakiego typu jest dowolna wartość. Ale gdy wrócisz do swojego kodu po tygodniu, sama liczba czy nazwa zmiennej często nie powie Ci, skąd się wzięła ani po co. W sekcji 1.4 poznasz komentarze — krótkie notatki w kodzie, które to wyjaśniają, a których Python nie wykonuje.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.4

Komentarze — notatki w kodzie

Wyobraź sobie, że piszesz grę i po tygodniu wracasz do kodu. Widzisz linię predkosc = 120 — ale 120 czego? Kilometrów na godzinę? Mil? Punktów na sekundę? Nie wiesz. Komentarz wyjaśniłby to od razu: predkosc = 120 # km na godzine. To notatka dla samego siebie z przyszłości — i dla każdego, kto będzie czytał Twój kod. Python jej nie wykonuje, ale Ty za tydzień będziesz za nią wdzięczny.
Komentarz zaczyna się od znaku # (po angielsku hash, czyli kratka). Wszystko, co napiszesz po # w tej samej linii, Python całkowicie pomija — czyta linię, widzi kratkę i od razu przeskakuje do następnej, jakby reszty w ogóle nie było. Możesz tam wpisać dosłownie cokolwiek: po polsku, po angielsku, z literówkami, ze znakami zapytania — Pythona to zupełnie nie obchodzi, bo komentarz nie jest poleceniem dla komputera, tylko notatką dla człowieka.

Po co w ogóle pisać coś, czego komputer nie wykonuje? Bo kod czytają ludzie znacznie częściej, niż się początkującym wydaje — a tym czytelnikiem najczęściej jesteś Ty sam, kilka dni czy tygodni później. Wracasz do swojej gry, widzisz jakąś liczbę i nie masz pojęcia, skąd się wzięła ani czemu akurat taka. Komentarz działa wtedy jak karteczka przyklejona do tej linii — natychmiast przypomina, o co chodziło, bo zapisuje to, czego z samego kodu nie widać. Zacznijmy od najprostszego przykładu:
Trzy linie kodu, a na ekranie tylko jedna. Prześwietlmy, którędy Python przeszedł:
# To jest komentarz print("Ten kod sie wykona") # print("Ten sie NIE wykona") ▸ Wynik: Ten kod sie wykona dla Pythona linia z # nie istnieje
Ta trzecia, pominięta linia to bardzo praktyczna sztuczka, którą programiści wykorzystują codziennie: kratką możesz tymczasowo „wyłączyć" dowolną linię kodu, nie usuwając jej na stałe. Kiedy szukasz błędu, wyłączasz podejrzany fragment, uruchamiasz program i sprawdzasz, czy problem zniknął. Jeśli tak — wiesz, gdzie szukać; jeśli nie — zdejmujesz kratkę i linia znów działa, a Ty nie straciłeś ani kawałka kodu.
Teraz najważniejsza zasada tej sekcji: dobry komentarz mówi DLACZEGO, a nie CO. Po co to rozróżnienie? Bo CO robi dana linia, widać już z samego kodu — zycia = 3 wyraźnie ustawia trzy życia i nie trzeba tego powtarzać słowami. Czego z kodu nie widać, to powód decyzji: dlaczego akurat trzy, a nie pięć czy jedno. Właśnie ten powód warto zapisać, bo to on ulatuje z pamięci najszybciej:
Spójrz, co dają te dwa komentarze. Bez nich linia predkosc = 120 byłaby zagadką — 120 czego? Kilometrów, mil, pikseli na sekundę? Notatka km na godzine — predkosc startowa gracza odpowiada na to w pół sekundy. Podobnie zycia = 3: sama liczba nic nie tłumaczy, ale dopisek o balansie trudności mówi, że trzy życia to świadoma decyzja, a nie przypadkowa wartość. A wynik na ekranie to dalej tylko 120 i 3 — komentarze niczego nie zmieniły w działaniu, bo Python je zignorował. I o to chodzi: komentarz nigdy nie wpływa na to, co program robi, więc możesz pisać ich tyle, ile trzeba.
A co się stanie, jeśli zapomnisz # i spróbujesz dopisać notatkę wprost po wartości — bez żadnego znaku przed nią? Wygląda niewinnie, przecież „to tylko tekst" — ale dla Pythona to poważny kłopot, bo on nie odróżnia notatki od polecenia, dopóki nie zobaczy kratki. Zanim przeczytasz wyjaśnienie, zobacz to na własne oczy:
SyntaxError — Python widzi predkosc = 120 i myśli, że instrukcja jest skończona. Potem natrafia na km na godzine i nie wie, co to znaczy — próbuje wykonać to jako kod. Notatka ZAWSZE musi mieć # na początku: predkosc = 120 # km na godzine.
Komentarz zaczynasz znakiem # i Python go ignoruje, więc pisz notatki tam, gdzie naprawdę coś wyjaśniają — przy nietypowej liczbie czy decyzji projektowej — a nie przy każdej oczywistej linii, bo wtedy stają się tylko szumem.

✔️ Po tej sekcji powinieneś umieć:
  • pisać komentarze znakiem #
  • wiedzieć, że Python komentarze całkowicie ignoruje
  • „wyłączać" linię kodu przez dodanie # na początku
  • pisać komentarze, które mówią DLACZEGO, nie CO
🧠 Sprawdź wiedzę — 1.4
Umiesz już opisywać kod komentarzami. Ale Python potrafi liczyć na kilka sposobów — i nie wszystkie dają wyniki, jakich się spodziewasz. W sekcji 1.5 odkryjesz operatory, które nie istnieją na zwykłym kalkulatorze — w tym taki, który odcina resztę, i taki, który zaokrągla w dół.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.5

Arytmetyka — Python jako kalkulator

Wyobraź sobie, że Twoja gra oblicza wynik — każdy pokonany wróg to 100 punktów, bonus za prędkość to mnożnik, a wróg zabrał ci jedno życie. Żeby to wszystko policzyć, program musi wykonywać działania matematyczne. Python potrafi to zrobić natychmiast i nigdy się nie myli. Do tego służą operatory arytmetyczne — znaki, które mówią Pythonowi co obliczyć.
Zacznijmy od czterech działań, które znasz z matematyki, i które w Pythonie wyglądają niemal tak samo. Dodawanie zapisujemy plusem, odejmowanie minusem, mnożenie gwiazdką * (nie literą „x", bo tę Python wziąłby za nazwę zmiennej), a dzielenie ukośnikiem /. Python liczy je natychmiast i nigdy się nie myli, dzięki czemu możesz mu spokojnie powierzyć każde obliczenie potrzebne w grze — od sumowania punktów po przeliczanie obrażeń:
Zwróć uwagę na ostatnią linię: 20 / 10 dało 2.0, a nie 2. To nie pomyłka. Operator / zawsze zwraca wynik z przecinkiem, czyli typ float, nawet gdy dzielenie wychodzi idealnie równo. Dzieje się tak dlatego, że Python zakłada, iż przy dzieleniu możesz spodziewać się ułamka, więc na wszelki wypadek od razu daje Ci float. Dla porównania zobaczmy wynik okrągły i nieokrągły obok siebie:
Teraz poznasz dwa nowe operatory, których nie znajdziesz na zwykłym kalkulatorze, a które w grach przydają się bez przerwy. Nie trzeba ich nawet tłumaczyć słowami — wystarczy popatrzeć. Masz 7 złotych monet i pakujesz je do sakiewek, po 2 do każdej:
Zapakuj 7 monet do sakiewek po 2 luzem 7 // 2 = 3 — pełne sakiewki 7 % 2 = 1 — moneta luzem // bierze całość · % bierze resztę
Monety wskakują parami: pierwsza sakiewka pełna, druga, trzecia… i stop — siódma moneta nie ma pary, zostaje luzem. Właśnie zobaczyłeś oba nowe operatory naraz. Dzielenie całkowite // pyta: ile PEŁNYCH sakiewek się zapakowało? 7 // 2 daje 3. Reszta z dzielenia % (po angielsku modulo) pyta: ile monet zostało luzem? 7 % 2 daje 1. Dlatego chodzą parą — jeden patrzy na sakiewki, drugi na to, co leży obok.

W grze ten duet pracuje na okrągło: punkty na poziomy, sekundy na minuty, monety na sakiewki. Bruno uzbierał 37 punktów, a awans wypada co 10 — ile pełnych poziomów już ma? To to samo pytanie o pełne sakiewki, tylko w innym przebraniu:
🤔 Spróbuj zgadnąć (nie szkodzi, jeśli jeszcze nie wiesz): ile wynosi 25 // 7?
Odpowiedź
3 — dzielenie całkowite odcina resztę. 3 * 7 + 4 to 25, więc mieszczą się 3 pełne siódemki.
A ile punktów Bruno uzbierał już ponad ten trzeci, pełny poziom? To pytanie o resztę:
Trzy pełne poziomy i 7 punktów ponad ostatni z nich. A gdy zechcesz policzyć odwrotnie — ile punktów brakuje do następnego awansu — odejmij resztę od dziesiątki: 10 - 7 = 3.
Jest jeszcze trzeci operator spoza zwykłego kalkulatora: **, czyli potęgowanie. Mnoży liczbę przez samą siebie tyle razy, ile wynosi wykładnik po prawej stronie — zapis 2 ** 10 znaczy „dwójka pomnożona przez siebie dziesięć razy". Liczby z potęgowania rosną zaskakująco szybko, dlatego operator ten przydaje się tam, gdzie coś ma rosnąć lawinowo, na przykład koszt ulepszenia, który podwaja się z każdym poziomem. Sprawdźmy, ile wyjdzie z dwójki podniesionej do dziesiątej potęgi:
Wynik to 1024 — dwójka pomnożona przez siebie dziesięć razy. Dobrze widać, jak gwałtownie rosną potęgi: jeszcze 2 ** 4 to skromne 16, ale kilka kroków dalej liczba przeskakuje tysiąc. Z tego powodu potęgowania używamy wszędzie tam, gdzie wartość ma rosnąć lawinowo — koszty w sklepie, zadawane obrażenia czy liczba przeciwników na kolejnych falach ataku.

A co się stanie, jeśli spróbujesz podzielić przez zero? W matematyce to działanie zakazane i Python traktuje je dokładnie tak samo. Zanim przeczytasz wyjaśnienie, zobacz to na własne oczy:
ZeroDivisionError — dzielenie przez zero jest niemożliwe (tak samo jak w matematyce). Python zgłasza ten błąd zanim obliczy cokolwiek. Zawsze sprawdzaj, czy dzielnik może być zerem — np. gdy użytkownik wpisuje liczbę graczy.
Zbierzmy to w całość. Python liczy jak kalkulator, który nigdy się nie myli, i daje Ci do ręki siedem operatorów. Cztery z nich — +, -, *, / — znasz ze szkoły, przy czym warto pamiętać, że / zawsze zwraca float. Trzy pozostałe to specjalność programisty: // mówi, ile pełnych części się mieści, % podaje resztę, a ** podnosi liczbę do potęgi.

Najczęściej w grach przydaje się duet // i % — przeliczanie punktów na poziomy, sekund na minuty, monet na paczki po dziesięć. Pamiętaj tylko o jednym wyjątku: nigdy nie dziel przez zero, ponieważ Python natychmiast przerwie program błędem. Gdy dzielnik pochodzi od gracza, zawsze warto najpierw sprawdzić, czy przypadkiem nie jest zerem, żeby program nie wywrócił się w najmniej spodziewanym momencie. Sam operator % jeszcze nieraz Ci się przyda — w module o warunkach posłuży choćby do sprawdzania, czy liczba jest parzysta, bo każda parzysta dzieli się przez dwa bez reszty. To prosty trik, a używa się go w grach zaskakująco często.

✔️ Po tej sekcji powinieneś umieć:
  • używać 7 operatorów: +, -, *, /, //, %, **
  • wyjaśnić różnicę między / (wynik float) a // (wynik całkowity)
  • wiedzieć kiedy pojawia się ZeroDivisionError
🧠 Sprawdź wiedzę — 1.5
Masz już // i % — operatory, których nie znajdziesz na zwykłym kalkulatorze. Ale co, jeśli w jednym wyrażeniu jest i dodawanie, i mnożenie? Python ma swoje reguły kolejności — i czasem zaskakują. W sekcji 1.6 zobaczysz, dlaczego 2 + 3 * 4 nie równa się 20.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.6

Kolejność operatorów

Bruno oblicza premię za poziom i pisze bonus = 10 + 5 * 2. Spodziewa się 30 — a Python zwraca 20! Bruno niczego nie zepsuł. Po prostu jedna cicha reguła przestawiła kolejność obliczeń — ta sama, którą znasz z lekcji matematyki. Za chwilę zobaczysz ją w akcji, a pod koniec sekcji naprawisz premię Bruna.
Python nie liczy po prostu od lewej do prawej. Gdyby tak robił, 2 + 3 dałoby 5, razy 4 — dwadzieścia. Sprawdź, co naprawdę wychodzi:
Czternaście, nie dwadzieścia. Zobacz, w jakiej kolejności Python to rozłożył:
2 + 3 * 4 najpierw mnożenie: 3 * 4 = 12 2 + 12 potem dodawanie: 2 + 12 = 14 14 Python liczy jak matematyk, nie od lewej
Mnożenie wyprzedziło dodawanie — jak na matematyce. Pełna hierarchia, od najważniejszego: nawiasy → potęga (**) → mnożenie i dzielenie (* / // %) → dodawanie i odejmowanie (+ -). Po co hierarchia, zamiast zwykłego czytania po kolei? Bo dzięki niej zapis 2 + 3 * 4 ma jedno, ustalone znaczenie na całym świecie — każdy matematyk i każdy program policzą go tak samo. Gdyby kolejność zależała od humoru, ten sam wzór dawałby różne wyniki w różnych miejscach, a to byłaby katastrofa.

A co, jeśli naprawdę chcesz, żeby dodawanie wykonało się pierwsze? Wtedy z pomocą przychodzą nawiasy. Wszystko, co zamkniesz w nawiasie, Python policzy w pierwszej kolejności, zanim ruszy resztę — bo nawiasy stoją na samym szczycie hierarchii:
🤔 Niespodzianka (nie szkodzi, jeśli nie zgadniesz — mało kto za pierwszym razem): ile da 2 ** 3 ** 2? Podpowiedź: to NIE jest (2 ** 3) ** 2.
Odpowiedź
512, nie 64! Potęgowanie liczy się wyjątkowo od PRAWEJ: najpierw 3 ** 2 = 9, potem 2 ** 9 = 512. Prawie wszystko inne idzie od lewej — potęga to wyjątek.
Warto też wiedzieć, gdzie w tej kolejności siedzi potęgowanie — a siedzi wysoko, zaraz pod nawiasami. W wyrażeniu 10 - 2 ** 3 Python najpierw policzy 2 ** 3 = 8, a dopiero potem odejmie: 10 - 8 = 2. Gdybyś chciał najpierw odjąć, znów ratują nawiasy — (10 - 2) ** 3 to już 8 ** 3, czyli całe 512. Jedna para nawiasów potrafi więc zmienić wynik z 2 na 512, bo przesuwa to, co policzy się jako pierwsze. Z potęgowaniem warto być szczególnie uważnym, bo skacze w hierarchii bardzo wysoko i łatwo o nim zapomnieć, gdy patrzy się tylko na plusy i minusy w wyrażeniu.

Teraz wróćmy do Bruna i jego premii za poziom. Chciał najpierw zsumować bazowe punkty z bonusem, a dopiero potem podwoić całość. Zobacz, jak bardzo zmienia się wynik w zależności od tego, czy postawisz nawiasy we właściwym miejscu — te same liczby, ten sam mnożnik, a rezultat zupełnie inny:
Spójrz na te dwie linie. bonus_zly = 10 + 5 * 2 dało 20, bo Python — wierny swojej hierarchii — najpierw pomnożył 5 * 2, a potem doliczył 10. Tymczasem bonus_ok = (10 + 5) * 2 dało 30, bo nawias zmusił go, by najpierw zsumował 10 i 5, a wynik dopiero podwoił. Różnica to całe dziesięć punktów premii — a w prawdziwej grze taki drobiazg potrafi zepsuć balans albo zirytować gracza, który czuje, że coś się nie zgadza. Dlatego twórcy gier sprawdzają takie wzory wyjątkowo skrupulatnie, często wypisując sobie wynik pośredni, żeby na własne oczy zobaczyć, co Python naprawdę policzył w środku.
⚠️ To był błąd logiczny — Python nie zgłosi tu żadnego błędu, ale wynik będzie inny, niż zamierzałeś. To najtrudniejszy rodzaj pomyłki: program działa, tylko liczy źle. Stąd prosta zasada — gdy masz wątpliwości co do kolejności, dodaj nawiasy. Nic nie kosztują, a kod robi się czytelniejszy.
Zbierzmy to w całość. Python liczy według ustalonej hierarchii: najpierw nawiasy, potem potęgi, dalej mnożenie i dzielenie, a na końcu dodawanie i odejmowanie. W praktyce wystarczy jedna rada — gdy masz najmniejszą wątpliwość, postaw nawiasy. Twój zamiar staje się wtedy czytelny i dla Pythona, i dla człowieka, który kiedyś przeczyta ten kod.

✔️ Po tej sekcji powinieneś umieć:
  • przewidzieć wynik złożonego wyrażenia bez nawiasów
  • używać nawiasów, żeby wymusić właściwą kolejność
  • rozpoznać błąd logiczny — program działa ale liczy źle
🧠 Sprawdź wiedzę — 1.6
Wiesz już, że Python szanuje kolejność działań — tak jak w matematyce. Teraz pora połączyć tekst z liczbami w jeden komunikat. W sekcji 1.7 poznasz f-stringi — sposób, żeby wypisać "Gracz Bruno ma 1250 punktów" jedną linią kodu, bez ręcznego sklejania.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.7

f-stringi — łączenie tekstu ze zmiennymi

Bruno chce wypisać wynik gry: imię gracza, liczbę punktów i poziom. Mógłby użyć kilku osobnych print(), ale wtedy każda wartość wylądowałaby w osobnej linii. A co, jeśli chce zmieścić to w jednym zdaniu: „Bruno zdobył 1250 punktów na poziomie 3"? Do tego służy f-string — szablon zdania z miejscami na zmienne. Litera f pochodzi od angielskiego formatted (sformatowany). Python widzi f"..." i wie, że ma zajrzeć do klamer {} i wstawić tam wartości zmiennych.
Do tego właśnie służy f-string — szablon zdania z okienkami na wartości. Zobacz, jak Python go skleja:
imie = "Bruno" punkty = 1250 f"{imie} ma {punkty} pkt" Bruno ma 1250 pkt f włącza szablon · {…} to okienko na wartość
Dwie rzeczy włączają ten mechanizm: litera f tuż przed cudzysłowem — bez niej Python zostawi klamry jako zwykły tekst — i klamry {}, w które wpisujesz nazwę zmiennej. Dlaczego to wygodniejsze niż sklejanie tekstu plusem? Bo od razu widać, jak będzie wyglądać całe zdanie — czytasz szablon niemal jak zwykłe zdanie po polsku. Nie musisz też ręcznie zamieniać liczb na tekst — f-string robi tę konwersję automatycznie, dzięki czemu omijasz całą klasę błędów. Zacznijmy od najprostszego przykładu:
🤔 Spróbuj zgadnąć (nie szkodzi, jeśli jeszcze nie wiesz): Jak zapisać imie = "Ana" i wynik = 99 jako jedno zdanie?
Odpowiedź
f"{imie} ma wynik {wynik}" — litera f i wartości w klamrach {}. Python podmienia klamry na wartości zmiennych.
Siła f-stringów polega na tym, że w jednym zdaniu możesz połączyć dowolnie wiele zmiennych i poustawiać je dokładnie tam, gdzie chcesz. Co więcej, w klamrach nie musi stać sama nazwa zmiennej — możesz wpisać tam całe wyrażenie matematyczne, a Python najpierw je obliczy, a dopiero potem wstawi gotowy wynik w zdanie. To bardzo praktyczne, bo nie musisz tworzyć osobnej zmiennej tylko po to, żeby coś raz wyświetlić:
Spójrz na drugą linię. W klamrach siedzi całe działanie (poziom + 1) * 100 - punkty, a mimo to w wyniku widać po prostu liczbę 150. Python policzył to wyrażenie w locie i wstawił sam rezultat — nie musiałeś nigdzie zapisywać go do osobnej zmiennej, bo klamry przyjmują nie tylko nazwy, ale i obliczenia.
Czasem wynik mnożenia ma mnóstwo cyfr po przecinku i wygląda paskudnie — coś w stylu 62.65100000000001. F-string pozwala to ujarzmić. Wewnątrz klamer, po dwukropku, możesz dopisać przepis na formatowanie: zapis {zmienna:.1f} znaczy „pokaż tę liczbę z jednym miejscem po przecinku". Literka f na końcu pochodzi od float, a cyfra przed nią mówi, ile miejsc chcesz zobaczyć — :.2f da dwa, :.0f żadnego. Po co to robić? Bo w grze chcesz pokazać graczowi czytelne „62.7", a nie kilkanaście cyfr, które tylko zaśmiecają ekran. Sprawdźmy ten sam wynik bez formatowania i z formatowaniem:
Widzisz różnicę? Bez formatowania Python wyrzucił surowe 62.651, a z dopiskiem :.1f zaokrąglił liczbę ładnie do 62.7. Co ważne, to zaokrąglenie dotyczy wyłącznie wyświetlania — sama wartość w pamięci się nie zmienia, więc dalsze obliczenia wciąż liczą na pełnej dokładności.
A co się stanie, jeśli zapomnisz o f-stringu i spróbujesz połączyć tekst z liczbą zwykłym plusem?
TypeError — Python nie łączy automatycznie tekstu (str) z liczbą (int). Użyj f-stringa: f"Punkty: {punkty}" — klamry robią konwersję za Ciebie.
Zbierzmy to w całość. F-string to szablon zdania, który zaczynasz literą f, a w klamry {} wstawiasz zmienne albo całe obliczenia — Python sam podmienia je na wartości i sam zamienia liczby na tekst. Dzięki temu jedną linią złożysz czytelny komunikat dla gracza, zamiast mozolnie sklejać kawałki plusem.

To narzędzie, po które będziesz sięgać już do końca kursu, bo prawie każdy program coś komunikuje: wynik, stan gry, informację o błędzie. Zapamiętaj dwie pułapki, a oszczędzisz sobie kłopotów. Bez litery f klamry zostaną wypisane dosłownie, jako zwykły tekst. A sklejanie tekstu z liczbą plusem bez konwersji zawsze kończy się błędem. F-string omija oba te problemy naraz, dlatego tak szybko staje się ulubionym sposobem wypisywania.

✔️ Po tej sekcji powinieneś umieć:
  • pisać f-stringi z f"..." i wstawiać zmienne w {}
  • obliczać wyrażenia bezpośrednio w klamrach f-stringa
  • formatować liczby przez :.1f lub :.2f
🧠 Sprawdź wiedzę — 1.7
🎁 Mini-projekt — „Kartka z życzeniami"

Złóż własną kartkę okolicznościową — program, który wypisze życzenie w ozdobnej ramce. Wykorzystasz dokładnie to, czego uczyłeś się w tej sekcji: zmienne i f-stringi.

Wymagania:
  • zapisz w zmiennych: imie, zyczenie, podpis,
  • użyj f-stringów, żeby wstawić zmienne do tekstu,
  • otocz kartkę ramką ze znaków = — u góry i u dołu,
  • kartka ma mieć co najmniej trzy linie treści.
💡 Chcesz wersję, która sama składa kartkę z dowolnym życzeniem i emoji? Zobacz nasz generator → devostro.pl/kartka — to ten sam pomysł z tej lekcji, tylko rozbudowany: wybierasz okazję, a kod sam składa gotową kartkę do wysłania.
F-stringi sprawiają, że Twoje programy mówią po ludzku — imię, wynik, wszystko w jednym zdaniu. Ale co, jeśli musisz zamienić tekst na liczbę? W sekcji 1.8 odkryjesz konwersję typów — i dowiesz się, dlaczego "500" + 1 wywołuje błąd, a int("500") + 1 daje 501.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.8

Konwersja typów

Bruno zapisał rekord gry w pliku tekstowym — liczba wygląda jak "500", ale jest tekstem, nie liczbą. Python nie może automatycznie dodać tekstu do liczby — tak jak nie możesz pomnożyć karteczki z napisem „500" przez 2. Konwersja to przetłumaczenie: bierzesz tekst "500" i zamieniasz go w prawdziwą liczbę. Potem możesz liczyć, porównywać, dodawać — wszystko, co robisz z liczbami.
Czasem masz wartość jednego typu, a potrzebujesz jej w zupełnie innym — liczbę zapisaną jako tekst, którą chcesz dodać, albo liczbę, którą chcesz skleić z napisem. Wtedy trzeba ją przekonwertować, czyli przetłumaczyć z jednego typu na drugi. Do konwersji typów służą trzy funkcje:
  • int() (integer = liczba całkowita) — zamienia na liczbę całkowitą
  • float() (floating-point = zmiennoprzecinkowa) — zamienia na liczbę z ułamkiem
  • str() (string = sznurek) — zamienia na tekst
Python nigdy nie robi tego automatycznie — musisz wywołać funkcję sam, bo tylko Ty wiesz, czy "500" ma służyć do liczenia, czy do wyświetlenia; Python nie zgaduje za Ciebie, żeby przypadkiem nie popsuć danych. Sprawdźmy to na przykładzie Bruno: mamy rekord gry zapisany jako tekst "500", sprawdzimy jego typ, zamienimy na liczbę i dodamy bonus:
Python mówi: str — to tekst. Nawet jeśli wygląda jak liczba, cudzysłów sprawia, że Python traktuje to jako ciąg znaków. Teraz zamieniamy:
Prześwietl tę zamianę:
"500" (str — tekst) int() int("500") 500 (int — liczba) konwersja = tłumaczenie: tekst → liczba
Prawdziwa liczba — więc + 100 działa i daje 600. Bez konwersji Python rzuciłby błąd, bo tekstu nie można dodać do liczby.
W drugą stronę: str() zamienia liczbę na tekst. Potrzebujesz tego, gdy chcesz skleić (+) liczbę z tekstem. Próba sklejenia bez str() daje błąd TypeError — Python nie miesza typów automatycznie.
str(42) zamienił liczbę 42 na tekst "42". Dopiero wtedy można go skleić z "Wynik: " używając +. Bez str() Python widziałby tekst + liczbę i zgłosiłby błąd.
Teraz coś zaskakującego. Zacznijmy od oczywistego — co robi int() z liczbą bez ułamka:
Okej — int(2.0) daje 2, to rozumiemy. A co, gdy float ma część dziesiętną?
Python ucina część dziesiętną — nie zaokrągla. int(2.1) to 2, nie 3. int(3.9) to 3, nie 4 — mimo że 3.9 jest bliżej 4. Działa jak nożyczki: odcina wszystko po kropce, bez patrzenia, jak duża jest reszta.

A ujemne? Tu jest mała pułapka. int(-2.8) to -2, a nie -3. Wyobraź sobie oś liczbową: startujesz z -2.8 i idziesz w stronę zera — pierwsza pełna liczba po drodze to -2. Ucinanie zawsze prowadzi w stronę zera: dla dodatnich „w dół" (2.8→2), dla ujemnych „w górę" (-2.8→-2).

W grze ma to całkiem praktyczne znaczenie. Jeśli z ułamkowych obrażeń liczysz całe punkty życia, ucinanie sprawia, że wynik zawsze idzie w tę samą, przewidywalną stronę, a nie raz w górę, raz w dół. Dzięki temu łatwiej przewidzieć zachowanie gry i prościej ją przetestować, bo nie musisz pamiętać żadnych dodatkowych reguł zaokrąglania.
A co się stanie, gdy spróbujesz zamienić słowo na liczbę?
ValueError: invalid literal for int()
Python zgłasza ten błąd, gdy próbujesz zamienić tekst, który nie jest liczbą, na int. int("trzy") — słowo, błąd. int("3.14") — ma kropkę, też błąd dla int().

✅ Poprawka: dla liczby z ułamkiem użyj float("3.14"), potem ewentualnie int().
Zbierzmy to w całość. Konwersja to świadome przetłumaczenie wartości z jednego typu na inny: int() i float() robią z tekstu liczbę, a str() z liczby tekst. Python nie zrobi tego sam, ponieważ tylko Ty wiesz, czy dana "500" ma posłużyć do liczenia, czy do wyświetlenia.

Zapamiętaj dwie rzeczy, które najczęściej zaskakują. Po pierwsze, int() nie zaokrągla, tylko ucina część po przecinku w stronę zera. Po drugie, zamiana zadziała wyłącznie wtedy, gdy tekst naprawdę wygląda jak liczba, bo słowo „trzy" zatrzyma program błędem. Ta wiedza przyda Ci się już w następnej sekcji, gdzie dane po raz pierwszy będą przychodzić wprost od użytkownika.

✔️ Po tej sekcji powinieneś umieć:
  • konwertować tekst na liczbę: int(), float()
  • konwertować liczbę na tekst: str()
  • wiedzieć, że int() ucina część dziesiętną (nie zaokrągla)
  • wiedzieć kiedy Python zgłosi ValueError
🧠 Sprawdź wiedzę — 1.8
Umiesz już zamieniać typy i sprawdzać, co Python widzi w każdej zmiennej. Ostatnia sekcja modułu pokaże moduły i import — jak sięgnąć po gotowe narzędzia Pythona (np. losowanie z random), zamiast pisać wszystko od zera.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.9

Moduły i import — gotowe narzędzia

Wyobraź sobie, że Bruno buduje grę i chce, żeby asteroidy pojawiały się w losowych miejscach ekranu. Mógłby sam napisać algorytm losowania — ale po co, skoro ktoś już to zrobił za niego? Python ma gotowe zestawy funkcji zwane modułami — wystarczy napisać import random i masz do dyspozycji cały zestaw narzędzi do losowania. To jak wypożyczenie gotowego narzędzia zamiast budowania go od zera.
Moduł (po angielsku module = zestaw) to gotowy plik pełen funkcji napisanych wcześniej przez innych programistów. Zamiast wymyślać koło na nowo, po prostu z niego korzystasz — a Python ma dziesiątki takich zestawów: do losowania, do matematyki, do dat i wielu innych zadań.

Żeby użyć modułu, musisz go najpierw wczytać poleceniem import, i to jedną linią umieszczoną na samej górze pliku, przed resztą kodu. Dlaczego akurat na górze? Ponieważ Python czyta plik od góry do dołu — jeśli spróbujesz użyć funkcji z modułu, zanim go zaimportujesz, program zatrzyma się błędem, bo w tym momencie nie zna jeszcze takiej nazwy.
import random   # ta linia musi byc na gorze pliku!
▸ Wynik:
(brak wyniku — ta linia tylko ładuje moduł do pamięci)
Po tej jednej linii moduł random jest załadowany do pamięci i gotowy do użycia. Od teraz możesz wywoływać jego funkcje, używając zapisu z kropką — random.nazwa_funkcji(). Kropkę czytaj jako polecenie „z modułu random weź funkcję o tej nazwie"; to ten sam sposób, w jaki będziesz sięgać po narzędzia z każdego innego modułu w przyszłości. Sam random zawiera wiele różnych narzędzi do losowania, a każde nadaje się do trochę innego celu. Sprawdźmy pierwsze z nich:
🤔 Spróbuj zgadnąć — nie szkodzi, jeśli nie jesteś pewien: czy każde uruchomienie programu wypisze liczbę 7?
Sprawdź, gdy zgadniesz
Nie — randint(1, 10) losuje nową liczbę przy każdym uruchomieniu. Wynik jest inny za każdym razem.
Siódemka. Zajrzyj, skąd się wzięła:
import random random randint choice shuffle random.randint(1, 10) 7 1 10 4 za każdym uruchomieniem inna liczba od 1 do 10 — granice włącznie import otwiera skrzynkę z narzędziami
Dwa argumenty — 1 i 10 — to granice losowania, obie włącznie: wypaść może każda liczba całkowita od 1 do 10. I w tym cała siła: skoro każde uruchomienie wyciąga inną liczbę, program przestaje być przewidywalny — a gra przestaje być nudna.
💡 Uwaga — czy komputer naprawdę „losuje"? ...no właśnie — czy na pewno „nieprzewidywalny"? Tak naprawdę random nie losuje z powietrza: bierze ziarno (po angielsku seed), najczęściej z zegara systemowego, i z niego wylicza kolejne liczby. To pseudolosowość — gdybyś znał ziarno, mógłbyś przewidzieć każdy wynik. Dla gry (asteroidy, jabłko węża) to w zupełności wystarcza: wygląda losowo i o to chodzi. Ale do rzeczy, które muszą być naprawdę nieprzewidywalne (hasła, kody, kryptografia), Python ma osobny moduł — secrets — czerpiący z „szumu" całego systemu.
Moduł random ma dwie funkcje, których Bruno użyje w grze:
  • randint(a, b) — losuje liczbę całkowitą od a do b (obie granice włączone)
  • uniform(a, b) — losuje liczbę zmiennoprzecinkową między a i b
Sprawdźmy obie na przykładzie asteroidy z gry Bruna:
Każda zmienna dostała inną funkcję, bo potrzebują różnych typów liczb:
  • randint dla pozycji i rozmiaru — piksele i rozmiar muszą być liczbami całkowitymi
  • uniform dla prędkości — prędkość może być 3.2, 2.7, 4.1 (potrzebujemy ułamka)
Każde uruchomienie tworzy inną asteroidę — inne miejsce, inny rozmiar, inna prędkość. To dokładnie ten efekt, którego oczekujesz w grze, bo gdyby asteroidy spadały zawsze tak samo, gracz nauczyłby się ich na pamięć już po jednej rundzie i zrobiłoby się nudno.
Co się stanie, gdy zapomnisz napisać import random na górze pliku?
NameError: name 'random' is not defined
Python nie zna słowa random, dopóki go nie zaimportujesz. Bez import random na górze pliku — każde użycie random.cokolwiek da ten błąd.

✅ Zawsze na górze: import random musi być przed pierwszym użyciem.
⚠️ Ważne — importy zawsze na samej górze pliku, przed resztą kodu. To konwencja całego świata programistów Pythona.
Zbierzmy to w całość. Moduł to gotowy zestaw funkcji, który wczytujesz poleceniem import na samej górze pliku, a potem sięgasz po jego narzędzia przez kropkę. Dzięki temu nie musisz pisać wszystkiego od zera — korzystasz z kodu, który ktoś już napisał, sprawdził i dopracował. To jedna z największych zalet Pythona. Oszczędza mnóstwo pracy i czasu. Im więcej modułów poznasz, tym mniej kodu będziesz musiał pisać samodzielnie od zera.

Z modułu random zapamiętaj dwie funkcje. randint(a, b) losuje liczbę całkowitą i nadaje się do pozycji czy rozmiaru, a uniform(a, b) losuje liczbę z ułamkiem i pasuje tam, gdzie potrzeba płynności, na przykład do prędkości. To właśnie losowość sprawia, że gra za każdym razem wygląda inaczej, i dlatego random będzie wracać w kolejnych projektach raz za razem — od prostych zgadywanek po pełnoprawne gry zręcznościowe.

✔️ Po tej sekcji powinieneś umieć:
  • importować moduł przez import nazwa
  • używać random.randint(a, b) do losowania liczby całkowitej
  • używać random.uniform(a, b) do losowania liczby zmiennoprzecinkowej
  • wiedzieć, że importy są zawsze na górze pliku
🧠 Sprawdź wiedzę — 1.9
Masz już print, zmienne, typy, działania, f-stringi, konwersję typów i import modułów — cały fundament Pythona. Do tej pory program robił dokładnie to, co mu kazałeś. W module 2 nauczysz go podejmować decyzje: True i False, warunki, if — program, który potrafi wybrać, co zrobić.
Tu napiszesz kod i sam sprawdzisz wynik. Bez praktyki przycisk „dalej" pozostaje zablokowany.
1.10

Wczytywanie danych — input()

Do tej pory Twoje programy znały wszystkie dane z góry — wpisywałeś je wprost w kod (imie = "Bruno"). Teraz poznasz coś, co zamienia program w rozmowę: input(). Program zadaje pytanie, gracz wpisuje odpowiedź, a przy każdym uruchomieniu może być inna.
Wyobraź sobie, że gra wita każdego gracza tak samo: „Witaj, Bruno!" — bez sensu, bo każdy nazywa się inaczej. Trzeba najpierw zapytać gracza, jak ma na imię, a dopiero potem go powitać. Dokładnie do tego służy input(): program pyta, gracz wpisuje, program zapamiętuje odpowiedź i używa jej dalej.
input() (po angielsku input = wejście) sprawia, że program przestaje być monologiem, a staje się rozmową. Robi trzy rzeczy po kolei: najpierw wyświetla pytanie, które wpiszesz w nawiasach; potem zatrzymuje cały program i czeka, aż użytkownik coś wpisze i naciśnie Enter; na końcu zwraca to, co zostało wpisane, żebyś mógł zapisać odpowiedź do zmiennej i użyć jej dalej.
imie = input("Jak masz na imie? ")
print(f"Czesc, {imie}!")
▸ Gdy gracz wpisze „Bruno":
Czesc, Bruno!
Program zamarł na pytaniu i czekał — dopiero po wpisaniu „Bruno" i naciśnięciu Enter Python zapisał ten tekst do zmiennej imie i ruszył dalej. Dlatego wynik zależy od tego, co wpiszesz: uruchom z innym imieniem, dostaniesz inne powitanie. To pierwszy raz, gdy Twój program zachowuje się inaczej przy każdym uruchomieniu.
💡 Jak sprawdzamy input tutaj? Wcześniej input() był na samym końcu kursu, „do zrobienia u siebie" — bo potrzebuje kogoś, kto wpisze odpowiedź. Teraz sprawdzarka robi to za Ciebie: podstawia przygotowane odpowiedzi i patrzy, co Twój program wypisze. Piszesz kod z input() normalnie, klikasz „Sprawdź", a my karmimy go danymi i sprawdzamy wynik. Gdy potem zbudujesz własną grę na komputerze, ten sam input() zatrzyma program i poczeka, aż wpiszesz coś w terminalu.
Ciekawe — a co zwróci input(), gdy zamiast imienia wpiszesz liczbę? Sprawdźmy typ:
wiek = input("Ile masz lat? ")
print(type(wiek))
▸ Gdy wpiszesz „14":
<class 'str'>
Wpisałeś 14 — wygląda jak liczba, a Python uparcie mówi str. To nie pomyłka: input() z zasady oddaje wszystko jako tekst, bo nie wie, czy chciałeś podać wiek do liczenia, czy numer pokoju, którego nigdy nie będziesz dodawać. Skoro w zmiennej siedzi tekst, zobacz, co się stanie, gdy spróbujesz dodać do niego liczbę 10:
wiek = input("Ile masz lat? ")
print(wiek + 10)
▸ Gdy wpiszesz „14":
TypeError: can only concatenate str (not "int") to str
TypeError: can only concatenate str (not "int") to str
Python nie doda tekstu "14" do liczby 10 — to różne typy. input() zawsze zwraca str, więc samo wpisanie liczby nie wystarczy.

✅ Rozwiązanie: owiń input() w int() (albo float()): wiek = int(input("Ile masz lat? "))
Oto poprawne podejście — konwersję robimy od razu przy wczytywaniu, zanim wartość trafi do zmiennej (przydaje się int() z sekcji 1.8):
wiek = int(input("Ile masz lat? "))
print(f"Za 10 lat bedziesz miec {wiek + 10} lat.")
▸ Gdy wpiszesz „14":
Za 10 lat bedziesz miec 24 lat.
int(input(...)) działa od środka na zewnątrz, jak matrioszka. Najpierw uruchamia się input() i wczytuje tekst "14". Potem ten tekst trafia do int(), które zamienia go na prawdziwą liczbę 14. Dopiero ta liczba ląduje w zmiennej, więc + 10 działa bez problemu. Zasada raz a dobrze: jeśli wczytaną wartość zamierzasz dodawać, mnożyć albo porównywać jak liczbę — owiń input() w int() lub float() już w chwili wczytywania.

✔️ Po tej sekcji powinieneś umieć:
  • pobierać dane od gracza przez input()
  • wiedzieć, że input() zawsze zwraca str (tekst)
  • wczytywać liczby przez int(input(...)) / float(input(...))
  • rozpoznać TypeError z dodawania tekstu do liczby i go naprawić
Twoje programy potrafią już rozmawiać z graczem — to ostatni element fundamentu. W module 2 program nauczy się podejmować decyzje: wczytasz coś od gracza i na tej podstawie wybierzesz, co zrobić (if, True/False). Właśnie dlatego input() poznajesz teraz — od tej chwili będzie wracać w prawie każdym zadaniu.
Tu napiszesz kod z input() i sam sprawdzisz wynik — my podstawimy dane. Bez praktyki przycisk „dalej" pozostaje zablokowany.
M01

Twój Pierwszy Program — Podsumowanie

✔️ Co umiesz po tym module:
  • wypisywać tekst i liczby przez print()
  • tworzyć zmienne wszystkich 4 typów (str, int, float, bool)
  • sprawdzać typ przez type()
  • pisać komentarze znakiem #
  • wykonywać obliczenia wszystkimi 7 operatorami arytmetycznymi
  • rozumieć kolejność działań i używać nawiasów
  • łączyć tekst ze zmiennymi przez f-stringi
  • konwertować typy przez int(), float(), str()
  • importować moduły przez import random i używać random.randint()
🎯 Brawo! Przeszedłeś przez cały Moduł 01 — to nie jest mała rzecz. Nauczyłeś się wypisywać tekst, tworzyć zmienne, liczyć (też // i %), formatować f-stringami, konwertować typy i losować liczby przez random. To fundament na którym stoi każdy program na świecie.

Ale teoria bez praktyki to tylko słowa. Czas złożyć WSZYSTKO w jedną całość — napisz projekt w okienku poniżej, uruchom go i porównaj wynik z przykładem. To prawdziwy sprawdzian: kilka kroków liczenia, nie jedno działanie.
🏗️ Projekt końcowy — „Karta Bohatera"

Zbudujesz generator karty bohatera — takie narzędzie naprawdę bywa w grach RPG: gracz podaje kilka rzeczy o swojej postaci, a program sam wylicza z nich statystyki i składa gotową kartę. To Twój pierwszy program, który nie tylko wypisuje to, co dostał, ale naprawdę liczy — i łączy w jedną całość wszystko z tego modułu: zmienne i typy, arytmetykę (w tym dzielenie całkowite i resztę), formatowanie liczb oraz losowanie. Przeczytaj spokojnie każdy krok — nie spiesz się, bo to siedem małych zadań, które razem dają coś, z czego będziesz dumny.

  1. Przygotuj losowanie. Dwie wartości na karcie będą losowe. Zadbaj o to, żeby potrzebny moduł był gotowy, zanim go użyjesz.
  2. Zapisz dane bohatera w zmiennych. Będą trzy: imię (Aria), wiek (14) i liczba pokonanych wrogów (37). Zwróć uwagę, które z nich są tekstem, a które liczbami — bo na tych drugich będziesz liczyć.
  3. Policz punkty doświadczenia. Każdy przeżyty rok daje 10 punktów, każdy pokonany wróg — 25. Zapisz to jednym wyrażeniem, bez zmiennych pomocniczych. Zanim uruchomisz program, policz wynik na kartce.
  4. Wyznacz poziom i drogę do awansu. Bohater awansuje co każde 100 punktów. Wylicz jego aktualny poziom, a potem — ile punktów brakuje mu do następnego. Oba działania da się zapisać krótko, jeśli sięgniesz po odpowiednie operatory dzielenia.
  5. Wylosuj celność. Celność to liczba z ułamkiem od 50 do 100. Surowa wartość ma mnóstwo cyfr po przecinku, więc na karcie pokaż ją zaokrągloną do jednego miejsca i ze znakiem procentu.
  6. Wylosuj szczęśliwą liczbę. Bohaterowi przyda się też szczęśliwa liczba całkowita od 1 do 100.
  7. Złóż kartę. Wypisz wszystko jako czytelną kartę: nagłówek, a pod nim każdą statystykę w osobnej linii. Dbaj o to, żeby karta ładnie się czytała — to ją zobaczy gracz.
Po skończeniu sprawdź, czy Twój program:
  • korzysta z danych bohatera zapisanych w zmiennych,
  • liczy punkty z wieku i liczby pokonanych wrogów,
  • wyznacza poziom przez dzielenie całkowite, a „do awansu" przez resztę z dzielenia,
  • losuje celność i pokazuje ją zaokrągloną do jednego miejsca po przecinku, ze znakiem procentu,
  • losuje szczęśliwą liczbę, a całą kartę składa f-stringami.
⏳ Python uruchomi się przy pierwszym „Uruchom" (pierwszy raz chwilę trwa).
M01

Test końcowy — Twój Pierwszy Program

Zdaj test końcowy, żeby odblokować Moduł 02. Próg: 80%. Każde podejście to NOWY zestaw 15 pytań z całego modułu. Prób bez limitu.
📝 Test końcowy — Moduł 01
Sprawdź całą wiedzę z modułu. Odpowiedz na wszystkie pytania, potem sprawdź wynik.
M02

Decyzje — Warunki i if/else

Nauczysz się tworzyć programy, które podejmują decyzje — reagują inaczej na różne dane. To serce każdego algorytmu.
Wyobraź sobie skrzyżowanie z sygnalizacją: zielone → jedź, czerwone → stój. Program też może reagować inaczej na różne sytuacje — wybierać jedną z wielu ścieżek.
W Pythonie decyzje realizujesz słowem if (jeśli) i else (w przeciwnym razie). Dzięki temu ten sam program potrafi zachować się inaczej dla każdego, kto go uruchomi.
👾 W grze Asteroidy użyjesz tego tak:
if zycia <= 0:
    stan_gry = "game_over"   # koniec gry!

if laser_trafil_wroga:
    punkty += 20             # wróg trudniejszy = więcej pkt
elif laser_trafil_asteroide:
    punkty += 10             # asteroida łatwiejsza = mniej pkt

if trafiony and not nietykalny:
    zycia -= 1               # traci życie tylko gdy nie jest nietykalny
Każda decyzja w grze to if/elif/else z tego modułu!
2.1

Wartości True i False

Wyobraź sobie, że grasz w quiz: pytanie pada, a Ty odpowiadasz TAK lub NIE — nie możesz powiedzieć "może". Python działa identycznie: każde porównanie daje odpowiedź TAK (True) albo NIE (False), nigdy coś pomiędzy. Te dwie wartości mają swoją nazwę — typ bool, od angielskiego boolean (logiczny). Na True i False opiera się każda decyzja w każdym programie.
Zacznij od patrzenia, nie od definicji. Na scenie poniżej linijka kodu mryga i się podmienia — swiatlo = True, potem swiatlo = False — a żarówka od razu pokazuje jej skutek:
swiatlo = True swiatlo = False True = świeci, False = zgaszona
Ta żarówka wisi na zwykłym pstryczku, bez ściemniacza — więc zna dokładnie dwa stany: świeci albo nie. Wartości, które kod jej przypisywał, tworzą w Pythonie osobny typ: bool (boolean = logiczny), o dokładnie dwóch wartościach — True (prawda) i False (fałsz).

Dlaczego akurat od tego zaczynamy cały moduł o warunkach? Bo komputer nie umie się wahać. Gdy Bruno strzela do przeciwnika, gra musi rozstrzygnąć jedno: trafił czy nie trafił. Gdy kończy poziom — zdobył dość punktów czy nie. Każda taka decyzja sprowadza się do jednej z dwóch wartości logicznych i to one napędzają całą logikę gry.

Przenieś żarówkę wprost do kodu: wartość logiczną przypisujesz do zmiennej jak liczbę czy tekst, a jej typ sprawdzisz znanym Ci z modułu pierwszego poleceniem type():
Python potwierdził to czarno na białym: typ zmiennej swiatlo to <class 'bool'>, czyli dokładnie ten logiczny typ, o którym mówimy. Zwróć przy okazji uwagę na drobiazg, który później oszczędzi Ci sporo nerwów — True i False piszemy zawsze z wielkiej litery.

To nie kaprys ani ozdoba. Python rozróżnia wielkość liter, więc true pisane z małej to dla niego coś zupełnie innego niż True — szuka wtedy zmiennej o takiej nazwie, nie znajduje jej i przerywa program. Zobaczmy ten błąd na własne oczy, bo zobaczyć go raz to zapamiętać na zawsze:
NameError: name 'true' is not defined
Python szuka zmiennej o nazwie true — nie wartości logicznej. Wartości logiczne piszemy zawsze z wielkiej litery: True i False.
Wiesz już, czym jest bool — czas zobaczyć, skąd te wartości biorą się w praktyce. Prawda jest taka, że True rzadko wpisujemy ręcznie; znacznie częściej Python wytwarza je sam, gdy o coś go zapytamy. A pytamy go przez porównanie dwóch wartości, i odpowiedź na takie pytanie to zawsze jedna z dwóch wartości logicznych.

To dlatego porównaniom poświęcimy całą następną sekcję — są głównym źródłem wartości logicznych w każdym programie. Na razie wystarczy, żebyś zobaczył sam efekt: zadajemy Pythonowi proste pytanie o liczby, a on odpowiada nam True lub False. Sprawdźmy to na liczbach, które bez trudu policzysz w głowie:
Każde takie wyrażenie to pytanie zadane Pythonowi, na które odpowiada krótkim „tak" lub „nie". 5 > 3 znaczy „czy 5 jest większe od 3?" — odpowiedź True; 5 != 5 pyta „czy 5 jest różne od 5?" — False, bo obie liczby są równe. Odpowiedź jest zawsze ostra, bez niczego pomiędzy. Właśnie dlatego wartości logiczne świetnie nadają się na pamięć stanu gry: Bruno albo żyje, albo nie, a tarcza jest włączona lub wyłączona — trzymasz to w zmiennej bool i jednym if sprawdzasz jej stan.
Jest przy tym jedna rzecz, o której warto wiedzieć od razu, bo wygląda na ciekawostkę, a potem oszczędzi Ci zdziwienia: bool ma własną nazwę i dwie wartości, ale Python liczy True jako 1, a False jako 0. To nie są więc osobne światy — wartość logiczna jest dla Pythona szczególnym rodzajem liczby. Zobacz sam:
Nie chodzi o to, żeby tak pisać na co dzień — if zywy: czyta się o niebo lepiej niż if zywy == 1:. Chodzi o to, żeby Cię nie zaskoczyło, gdy Python doda dwie prawdy i wyjdzie mu 2. W module o listach wykorzystamy to do czegoś konkretnego: zbierzesz serię trafień i jednym poleceniem policzysz, ile ich było.

Najczęściej nie wpisujesz True i False ręcznie, lecz dostajesz je jako wynik porównania, któremu przyjrzymy się dokładnie w następnej sekcji — to one są fundamentem każdego if i każdej decyzji programu.
🤔 Zgadnij albo odpowiedz: Jaki wynik zwróci print(False == False)?
Odpowiedź
True — porównanie pyta „czy są równe?". Obie strony to False, więc są równe → True. (Brzmi przewrotnie, ale „fałsz równa się fałsz" to prawda!)

✔️ Po tej sekcji powinieneś umieć:
  • wiedzieć, że bool to True lub False — tylko dwie wartości
  • rozumieć, że każde porównanie zwraca bool
  • wyjaśnić, dlaczego True i False piszemy z wielkiej litery
🧠 Sprawdź wiedzę — 2.1
Python zwraca True lub False — teraz wiesz, jak to sprawdzić. Ale jeden operator to za mało — jest ich sześć i każdy pyta inne pytanie. W sekcji 2.2 zobaczysz je wszystkie razem: ==, !=, <, >, <=, >= — i dowiesz się, który najczęściej prowadzi do błędu.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
2.2

Operatory porównania — pełna lista

Wyobraź sobie, że Bruno sprawdza wyniki meczu: czy zdobył więcej punktów niż rekord? Czy jego życia nie spadły do zera? Czy wprowadzone hasło się zgadza? Do każdego z tych pytań Python odpowiada True lub False — i do ich zadawania służą operatory porównania. Python ma 6 takich operatorów — każdy pyta o coś innego: większy, mniejszy, równy, różny i ich kombinacje z "lub równy".
Zacznij od zobaczenia jednego z nich w akcji. Na scenie poniżej program pyta print(5 > 3) — „czy 5 jest cięższe od 3?" — a waga kładzie obie liczby na szalkach, przechyla się w stronę cięższej i oddaje odpowiedź:
print(5 > 3) print(3 > 5) czy 5 jest cięższe od 3? czy 3 jest cięższe od 5? 5 3 3 5 True False porównanie zawsze daje True albo False
Właśnie obejrzałeś całe porównywanie w akcji. Operator > położył dwie wartości na szalkach i sprawdził, która cięższa — a odpowiedź oddał krótkim True albo False. Za drugim razem pytanie brzmiało „czy 3 jest cięższe od 5?" — waga przechyliła się w stronę piątki, więc odpowiedź mogła być tylko jedna: False
Czytamy wyniki linia po linii: hp > 50 — 75 jest większe od 50, więc True. hp < 0 — 75 nie jest ujemne, więc False. hp == 75 — dokładnie 75, więc True. Ostatnia linia 0 < hp <= 100 to łańcuch dwóch porównań naraz — Python sprawdza, czy 0 < 75 I czy 75 <= 100. Oba są prawdziwe, wynik to True.

Wynik każdego porównania to zawsze bool — True lub False — i to otwiera przed Tobą trzy różne sposoby wykorzystania tego samego wyrażenia. Możesz zapisać wynik do zmiennej (wynik = hp > 50), żeby użyć go później; możesz go od razu wypisać (print(hp > 50)), żeby sprawdzić, co wyjdzie; albo wstawić wprost do warunku if, do czego dojdziemy już w sekcji 2.4.

Wróćmy jeszcze na chwilę do łańcucha 0 < hp <= 100, bo to wygodny chwyt, który łatwo zapamiętać. Python rozbija go na dwa osobne porównania — sprawdza, czy 0 < hp oraz czy hp <= 100 — i zwraca True tylko wtedy, gdy oba są prawdziwe. W grze Bruna taki zapis świetnie pilnuje, żeby punkty życia mieściły się w dozwolonym przedziale, zamiast spaść poniżej zera albo wystrzelić ponad maksimum.
SyntaxError: invalid syntax
Operatory lub-równy zapisujemy zawsze tak samo: najpierw symbol kierunku, potem znak równości. Odwrotna kolejność nie istnieje w Pythonie i od razu zatrzymuje program — np. print(7 => 5) zgłasza błąd składni:
✅ >= (większy lub równy)  ·  ✅ <= (mniejszy lub równy)
❌ =>  ·  ❌ =<
Przećwiczmy wszystkie sześć operatorów na liczbach, które możesz sprawdzić w głowie:
Zbierzmy to w całość. Masz sześć operatorów porównania, a każdy z nich zadaje Pythonowi jedno proste pytanie o relację między dwiema wartościami i odpowiada na nie wartością True lub False. Cztery z nich — >, <, >=, <= — porównują wielkość, a dwa pozostałe — == i != — pytają o równość i różnicę.

Warto już teraz wbić sobie do głowy najczęstszą pułapkę całego modułu: operator równości to podwójny znak ==, a nie pojedyncze =. Pojedynczy znak ma w Pythonie zupełnie inne zadanie i pomylenie tych dwóch to klasyczny błąd początkującego. Dlatego właśnie poświęcimy mu w całości następną sekcję — zobaczysz dokładnie, skąd się bierze i jak rozpoznać go od razu.
🤔 Zgadnij albo odpowiedz: Co zwróci print(10 < 5 < 20)?
Odpowiedź
False — łańcuch sprawdza OBA porównania: 10 < 5 (fałsz!) ORAZ 5 < 20. Skoro pierwsze jest fałszywe, całość to False — choć drugie by pasowało.

✔️ Po tej sekcji powinieneś umieć:
  • używać wszystkich 6 operatorów: >, <, >=, <=, ==, !=
  • łączyć porównania w łańcuch: a <= x < b
  • wyjaśnić, dlaczego wynik każdego porównania to zawsze typ bool
🧠 Sprawdź wiedzę — 2.2
Masz już pełen zestaw operatorów porównania. Jest jeden problem — Python używa znaku = do dwóch zupełnie różnych rzeczy, a jeden znak różnicy wywołuje błąd, który trudno zauważyć. W sekcji 2.3 zobaczysz skąd bierze się jeden z najczęstszych błędów Pythona i jak go rozpoznać od razu.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
2.3

Pułapka: = vs ==

Wyobraź sobie dwie różne czynności: wkładasz klucze do szuflady — to przypisanie, robisz coś z kluczami. Potem pytasz "czy klucze są w szufladzie?" — to porównanie, sprawdzasz stan. W Pythonie = to wkładanie (przypisujesz wartość do zmiennej), a == to pytanie (sprawdzasz, czy wartości są równe). Wyglądają prawie tak samo — jeden znak różnicy — ale robią zupełnie co innego i nie można ich zamieniać.
Pojedynczy znak = oznacza w Pythonie przypisanie — bierze wartość z prawej strony i wkłada ją do zmiennej po lewej. Niczego nie sprawdza i niczego nie wypisuje na ekran; po prostu coś ustawia. Podwójny znak == to zupełnie inna operacja, czyli porównanie — zadaje pytanie „czy te dwie wartości są równe?" i odpowiada wartością True albo False.

Oba zapisy różnią się tylko jednym znakiem, a robią coś przeciwnego — jeden ustawia wartość, drugi o nią pyta — i właśnie dlatego ich pomylenie to jeden z najczęstszych błędów na starcie nauki. W warunkach if, które są miejscem zadawania pytań, zawsze potrzebujesz podwójnego ==:
Zobacz teraz, co Python robił w środku przy dwóch pierwszych liniach — najpierw wkładanie, potem pytanie:
x = 5 x == 5 ? x 5 = WKŁADA do pudełka 5 == sprawdza → True = wkłada, == pyta
Dokładnie to widać na animacji: kulka z 5 wpada do pudełka bez żadnego napisu na ekranie, a pytanie x == 5 wraca z odpowiedzią True. W kodzie zostały jeszcze dwie linie. Kolejne x == 10 pyta „czy x jest równe 10?" i daje False. Na końcu if x == 5: sprawdza warunek — jest prawdziwy, więc wcięty blok się wykonuje i na ekranie pojawia się „x wynosi 5".
Teraz najciekawsze. Wyobraź sobie, że chciałeś sprawdzić warunek, ale w pośpiechu wpisałeś tylko jeden znak = zamiast dwóch. To słynna pułapka „if x = 5". Co zrobi Python?
SyntaxError: invalid syntax
if imie = "Anna": — Python natychmiast zgłasza błąd. Dobra wiadomość: Python chroni Cię przed tym błędem — nie pozwoli uruchomić kodu z = w warunku.
Zapamiętaj: jeden znak = to przypisanie, dwa znaki == to porównanie.
Masz tu zresztą szczęście, którego nie mają programiści w wielu innych językach. W części z nich if x = 5 nie jest błędem — kod się uruchamia, po cichu nadpisuje zmienną i prowadzi do podstępnej awarii, której szuka się godzinami. Python świadomie na to nie pozwala: pojedyncze = w warunku zatrzymuje program od razu, zanim cokolwiek pójdzie nie tak. Ten błąd, choć irytujący, jest więc Twoim sprzymierzeńcem.

Operator == działa przy tym ze wszystkimi typami danych — liczbami (5 == 5), tekstem ("Anna" == "Anna") i wartościami logicznymi (True == True). Pamiętaj jednak, że porównanie tekstu jest wrażliwe na wielkość liter: "anna" == "Anna" to False, bo Python widzi dwa różne ciągi znaków. Gdy sprawdzasz hasło albo imię wpisane przez gracza, każda litera musi się zgadzać co do jednej.

Z początku może to wyglądać na przesadę, ale ma sens. Gdyby hasło "Bruno" przechodziło tak samo jak "bruno" i "BRUNO", byłoby łatwiejsze do zgadnięcia. Python traktuje więc wielką i małą literę jako dwa różne znaki — i tak samo zrobi z każdą spacją czy literówką. To dobry moment, żeby zapamiętać, że dla komputera „prawie takie samo" znaczy po prostu „różne", bez żadnej taryfy ulgowej.

Zbierzmy to w całość. Jeden znak = coś robi — przypisuje wartość zmiennej. Dwa znaki == o coś pytają — sprawdzają równość i zwracają bool. W warunkach zawsze chodzi o pytanie, więc zawsze używasz ==, a Python dodatkowo pilnuje Cię, przerywając program, gdybyś się pomylił. Gdy następnym razem zobaczysz przy if komunikat o błędzie składni, sprawdź najpierw, czy nie wpisałeś tam przypadkiem pojedynczego znaku równości — to naprawdę jedna z najczęstszych przyczyn takiego komunikatu u początkujących.
🤔 Zgadnij albo odpowiedz: Co wypisze print("5" == 5)?
Odpowiedź
False — tekst "5" to NIE liczba 5. Python nie uznaje ich za równe, bo to różne typy. Klasyczna pułapka po wczytaniu danych.

✔️ Po tej sekcji powinieneś umieć:
  • nigdy nie mylić = (przypisanie) z == (porównanie)
  • wiedzieć, że w warunkach zawsze używamy ==
  • wyjaśnić, dlaczego Python zgłasza błąd, gdy użyjesz = w warunku
🧠 Sprawdź wiedzę — 2.3
Wiesz już, że = przypisuje, a == porównuje — to kluczowe rozróżnienie. Teraz pora użyć warunków do czegoś prawdziwego. W sekcji 2.4 Python po raz pierwszy sam zdecyduje czy wykonać kod — zobaczysz if bez else: działanie, które albo się wykona, albo nie.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
2.4

if — prosta decyzja

Wyobraź sobie bramkę w grze: JEŚLI gracz ma bilet — wchodzi na arenę, JEŚLI nie ma — omija wejście i gra idzie dalej. W obu przypadkach program kontynuuje działanie — różnica jest tylko w tym czy konkretny fragment kodu się wykona. if to pierwsza i najważniejsza decyzja w programowaniu: sprawdza warunek i wykonuje blok kodu tylko gdy warunek jest prawdziwy.
Obejrzyj dwa przebiegi tego samego programu. Najpierw ramka podświetla kod — przeczytaj go spokojnie. Pod kodem jest scena: romb to bramka (sprawdza warunek), a prostokąty to stacje — linie kodu, które zapalają się, gdy program je wykonuje. Kulka niesie wartość: przy 35 przechodzi przez bramkę w prawo i wcięte linie zapalają się razem ze swoimi stacjami; przy 20 bramka nie przepuszcza i kulka jedzie prosto w dół. Dolna stacja — linia bez wcięcia — zapala się w obu przebiegach:
temperatura = 35 temperatura = 20 if temperatura > 30: print("Goraco! Pij duzo wody.") print("Unikaj slonca.") print("Ten kod wykonuje sie zawsze.") if 35 > 30 ? 20 > 30 ? Tak → w prawo (wcięcie) Nie ↓ "Goraco!..." "Unikaj slonca." "...wykonuje sie zawsze." kreska w kodzie = odejście w prawo
Właśnie zobaczyłeś pierwszą decyzję programu. Do tej pory Python wykonywał wszystkie linie po kolei, zawsze tak samo — a tu kulka z 20 minęła bramkę i część kodu po prostu się nie wykonała. Za tę decyzję odpowiada if (po angielsku „jeśli"), a po nim warunek — pytanie zwracające True lub False, dokładnie takie, jakie ważyłeś w sekcji 2.2.

Wcięcie, które na animacji świeciło jako niebieska kreska, to w kodzie 4 spacje lub klawisz Tab — i jest obowiązkowe. Właśnie po nim Python poznaje, które linie należą do bramki: kod z wcięciem wykonuje się tylko przy prawdziwym warunku, kod bez wcięcia — zawsze. Dlatego dolna stacja świeciła w obu przebiegach.

Jeśli zaglądałeś kiedyś do innego języka programowania, to dla porównania: tam blok wyznaczają zwykle nawiasy klamrowe {}, a w Pythonie tę samą rolę pełni samo wcięcie. To dlatego Python uchodzi za język czytelny — kod jest poukładany w schludne kolumny, bo musi być, a nie tylko dlatego, że ktoś był staranny.

Zwróć też uwagę na dwukropek na końcu linii z if. To nie ozdoba — dwukropek mówi Pythonowi „za chwilę zaczyna się blok zależny od tego warunku". Razem z wcięciem tworzą parę, którą zobaczysz przy każdym warunku w tym module: najpierw dwukropek zapowiada blok, a potem wcięcie pokazuje jego granice. Oto ten program w całości:
Wynik znasz już z animacji: przy 35 bramka przepuszcza i wykonują się oba wcięte print(), przy 20 cały wcięty blok zostaje pominięty — a ostatnia linia drukuje się tak czy inaczej.

Zatrzymaj się na chwilę przy tej ostatniej linii, bo dobrze pokazuje istotę wcięcia. Należy ona do głównego ciągu programu, a nie do warunku, więc jej los nie zależy od temperatury. To bardzo częsty układ: kawałek kodu zależny od warunku, a tuż pod nim kod, który ma się wykonać tak czy inaczej. Całą tę różnicę wyznacza jedynie to, czy linia jest wcięta, czy nie — innego znaku Python tu nie potrzebuje, więc to na wcięciu spoczywa cała odpowiedzialność za sens programu.
Skoro wcięcie jest tak ważne, zobaczmy, co się stanie, gdy zwyczajnie zapomnisz je dodać:
IndentationError: expected an indented block
Python oczekuje, że po if warunek: będzie wcięty blok kodu. Brak wcięcia (lub za mało spacji) powoduje ten błąd. Używaj dokładnie 4 spacje albo klawisza Tab — konsekwentnie przez cały plik (nie mieszaj spacji z Tab).
Druga połowa tej samej pary to dwukropek. Skoro : i wcięcie zawsze chodzą razem, zobaczmy też, co się stanie, gdy zapomnisz właśnie dwukropka:
SyntaxError: expected ':'
Po warunku if ZAWSZE stawiamy dwukropek — to on zapowiada blok zależny od warunku. Bez niego Python nie wie, że za chwilę zacznie się kod do wykonania pod warunkiem, i przerywa od razu. Na szczęście podpowiada wprost, czego mu brakuje: expected ':'. Zapamiętaj parę nierozłączną: if warunek:, a w następnej linii — wcięcie.
Samotny if — bez żadnej drugiej ścieżki — to świadomy wybór, który znaczy: „wykonaj to, gdy warunek jest spełniony, a jeśli nie — po prostu pomiń i idź dalej". Program nie zatrzymuje się i nie zgłasza błędu, gdy warunek jest False; po cichu przeskakuje wcięty blok i kontynuuje od następnej linii bez wcięcia. To zachowanie bywa właśnie tym, czego potrzebujesz.

Dlaczego? Bo wiele rzeczy w grze ma się zdarzyć tylko czasem, a poza tym nie dziać się nic. „Tylko jeśli HP Bruna spadło do zera — wypisz Game Over." „Tylko jeśli zebrał bonus — dorzuć mu punkty." W żadnym z tych przypadków nie ma drugiej ścieżki: albo coś się dzieje, albo program leci dalej, jakby nigdy nic.

Zbierzmy to w całość. if sprawdza warunek i wykonuje wcięty blok tylko wtedy, gdy ten warunek jest prawdziwy. Wcięcie decyduje, co należy do bloku, a co jest poza nim, dlatego jego brak kończy się błędem. Sam if daje jedną opcjonalną ścieżkę — w następnej sekcji poznasz else, czyli drugą drogę: program zyska wtedy gwarancję, że zawsze wybierze jedną z dwóch.
🤔 Zgadnij albo odpowiedz: Co wypisze program, gdy temperatura = 20? Ile linii?
Odpowiedź
Jedna linia: Ten kod wykonuje sie zawsze. — blok if temperatura > 30 zostaje pominięty, ale ostatni print jest poza wcięciem.

✔️ Po tej sekcji powinieneś umieć:
  • pisać if z prawidłowym wcięciem (4 spacje)
  • rozumieć, że blok if może się nie wykonać wcale
  • rozróżniać kod wewnątrz bloku od kodu poza nim
🧠 Sprawdź wiedzę — 2.4
Znasz już if — Python wykonuje blok albo pomija. Ale co, jeśli chcesz, żeby program zawsze coś powiedział — w jednym przypadku jedno, w innym drugie? W sekcji 2.5 dodasz else: gwarancję, że dokładnie jedna gałąź zawsze się wykona — zero wyjątków.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
2.5

if / else — dwie ścieżki

Wyobraź sobie automat z napojami: wrzucasz monetę — JEŚLI masz wystarczająco dużo — dostaniesz napój, W PRZECIWNYM RAZIE — moneta wraca. Zawsze jeden z tych wyników, nigdy oba naraz i nigdy żaden. if/else daje programowi tę samą gwarancję — zawsze wykona się dokładnie jedna gałąź, nigdy obie i nigdy żadna.
Obejrzyj dwa przebiegi. Najpierw ramka podświetla kod — przeczytaj go spokojnie. Potem kulka z 8 staje na bramce, warunek mryga, zapala się „Tak" i kulka skręca do górnej stacji. W drugim przebiegu kulka z 4 dostaje „Nie" i jedzie prosto w else. Zawsze zapala się dokładnie jedna stacja:
wynik = 8 wynik = 4 if wynik > 6: print("Zdales! Brawo.") else: print("Nie zdales.") if 8 > 6 ? 4 > 6 ? Tak → Nie ↓ "Zdales! Brawo." else "Nie zdales." else = druga wcięta droga zawsze zapala się dokładnie jedna
Na animacji rozwidlenie zagrało dwa razy: kulka z 8 przeszła próg i zapaliła gałąź „Zdales! Brawo.", a kulka z 4 odbiła w else — „Nie zdales.". Za każdym razem zaświeciła się dokładnie jedna stacja. Słowo else znaczy „w przeciwnym razie" i wykonuje się dokładnie wtedy, gdy warunek w if okazał się False. Razem if i else tworzą dwie ścieżki, a program zawsze wybiera jedną z nich — nigdy obie, nigdy żadną. To właśnie ta pewność odróżnia if/else od samotnego if z poprzedniej sekcji.
if/else daje gwarancję, której sam if nie daje: zawsze wykona się dokładnie jedna gałąź — obie naraz się nie zapalą i żadna nie zostanie pominięta, co widziałeś na obu przebiegach animacji.

Dlaczego ta gwarancja jest tak cenna? Bo wiele sytuacji w programie wymaga, żeby użytkownik zawsze dostał jakąś odpowiedź. Gdy gracz wpisuje hasło, musi usłyszeć „dostęp przyznany" albo „błędne hasło" — nie wolno zostawić go w ciszy, bez żadnej informacji. Samotny if mógłby milczeć, a if/else milczeć nie potrafi.
SyntaxError: invalid syntax
Brak dwukropka po else to jeden z najczęstszych błędów w if/else. Zobacz przykład:
if wynik > 6:
    print("Zdales!")
else          # ← brak ":"
    print("Nie zdales.")
Python widzi else i czeka na dwukropek. Bez niego nie wie, gdzie zaczyna się blok. Każdy blok (if, else, elif) musi kończyć się dwukropkiem.
Jeszcze jeden przykład — rozpoznaj, czy liczba jest parzysta. Przyda się operator %, czyli reszta z dzielenia z modułu pierwszego. Przypomnijmy: 7 % 2 daje 1, bo siódemka podzielona przez dwa to trzy całe i jeden w reszcie, a 8 % 2 daje 0, bo ósemka dzieli się równo. Każda liczba parzysta dzieli się przez dwa bez reszty — wystarczy więc sprawdzić, czy liczba % 2 == 0:
Prześledźmy: w zmiennej była 7, Python obliczył 7 % 2, czyli 1 — warunek liczba % 2 == 0 jest więc False i program przeszedł do else. Budowa tego warunku to typowy wzorzec: najpierw coś obliczamy (tutaj resztę z dzielenia), a dopiero wynik porównujemy operatorem ==. Najpierw oblicz, potem porównaj, na końcu zdecyduj — ten porządek wraca w niezliczonych programach, więc dobrze mieć go z tyłu głowy od początku.

Zwróć uwagę, że oba przykłady mają tę samą budowę, choć dotyczą zupełnie innych spraw. Zawsze jest warunek po if, wcięty blok dla przypadku prawdziwego i drugi wcięty blok po else dla wszystkich pozostałych. To stały szkielet, który będziesz powtarzać w setkach programów — zmienia się tylko warunek i treść komunikatów. A parzystość i rytmy (tura % 3 == 0 wyłapie co trzecią turę) będziesz jeszcze drążyć w zadaniach tej sekcji.

Zbierzmy to w całość. if/else dzieli program na dwie ścieżki i gwarantuje, że zawsze wybierze dokładnie jedną. Pamiętaj tylko, że każdy z bloków — i if, i else — musi kończyć się dwukropkiem, bo bez niego Python nie wie, gdzie zaczyna się wcięty kod. Te dwa drobiazgi, dwukropek i wcięcie, to najczęstsze źródła błędów na początku, więc warto sprawdzać je odruchowo.
🤔 Zgadnij albo odpowiedz: Co wypisze program, gdy liczba = 8?
Odpowiedź
8 jest parzysta. — 8 % 2 = 0, warunek True, wykonuje się gałąź if.

✔️ Po tej sekcji powinieneś umieć:
  • pisać if/else
  • rozumieć, że dokładnie jedna gałąź się zawsze wykona
  • wyjaśnić, dlaczego if/else daje gwarancję, której sam if nie daje
🧠 Sprawdź wiedzę — 2.5
if i else dają dwie opcje. Ale co z ocenami 1, 2, 3, 4, 5, 6 — to sześć przypadków, nie dwa. W sekcji 2.6 poznasz elif: sposób na łańcuch warunków bez zagnieżdżania if w if. I zobaczysz, dlaczego kolejność elifów ma znaczenie.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
2.6

elif — wiele opcji

Wyobraź sobie bramkarza z checklistą: czy masz zaproszenie VIP? Nie. Czy masz bilet premium? Nie. Czy masz bilet normalny? Tak! — i bramkarz przestaje sprawdzać dalej, wpuszcza Cię. elif działa identycznie: Python sprawdza warunki po kolei i gdy znajdzie pasujący — wykonuje ten blok i całkowicie pomija resztę. Nie chodzi o to, że kolejne są fałszywe — Python ich w ogóle nie sprawdza.
Obejrzyj trzy przebiegi tej samej drabiny. Ocena 6 odbija w prawo przy pierwszej bramce — i nic niżej już nie jest sprawdzane. 5 mija pierwszą, wpada w drugą. 1 nie pasuje nigdzie i spada na sam dół, do else.
ocena = 6 ocena = 5 ocena = 1 if ocena == 6 ? "Celujacy!" Nie ↓ elif ocena == 5 ? "Bardzo dobry" Nie ↓ else "Niedostateczny" różne dane = różna droga pierwszy pasujący wygrywa
Do tej pory umiałeś rozdzielić program na dwie ścieżki przez if/else. Ale ocen w szkole jest sześć, pór dnia kilka, kategorii temperatury wiele — na to jest elif, skrót od angielskiego else if: „a jeśli nie to, może to?".

Właśnie to widziałeś na scenie: Python schodzi po drabinie od góry i wykonuje pierwszy pasujący blok — a resztę całkowicie pomija, ona przestaje istnieć. Dlatego zawsze wykonuje się dokładnie jedna gałąź. Ocena, której nie złapała żadna bramka, spada do else — siatki bezpieczeństwa na wszystko, czego nie przewidziałeś.

Gałęzi elif możesz dopisać dowolnie wiele, a końcowe else jest opcjonalne — choć prawie zawsze warto je mieć. Na scenie widziałeś skrót; tak wygląda pełna drabina ocen w kodzie:
Uruchomiliśmy kod z oceną 5 — to dokładnie środkowy przebieg ze sceny: pierwsza bramka przepuszcza, druga łapie, reszta drabiny przestaje istnieć. I właśnie ta „reszta przestaje istnieć" bywa pułapką, gdy ktoś zamiast elif ustawi kilka OSOBNYCH if — wtedy Python sprawdza każdy z nich niezależnie:
Wiele if zamiast elif — subtelny błąd logiczny:
Przy 85 punktach oba pierwsze if są prawdziwe — wypisuje i "Zdany" i "Dobry". Z elif Python zatrzymałby się na "Zdany" i nie sprawdzał dalej. Gdy warunki mogą być jednocześnie prawdziwe — zawsze używaj elif.
Kolejność warunków w elif ma znaczenie, gdy zakresy się nakładają. Warunek wąski (trudniejszy do spełnienia) musi iść wyżej, warunek szeroki — niżej. Np. sprawdzając progi punktowe: najpierw >= 90 (celujący), potem >= 75, potem >= 50. Gdybyś dał >= 50 na górze, ktoś z 95 punktami dostałby "Zdany" i Python nie sprawdziłby już wyższych progów. W przykładzie z ocenami każdy warunek to równość (== 6, == 5…) — zakresy się nie nakładają, więc kolejność nie ma znaczenia. Ale w zadaniach poniżej używasz właśnie zakresów (np. 6–11, 12–17) — tam pamiętaj: węższy/wyższy próg na górze.
🤔 Zgadnij albo odpowiedz: Co wypisze kod, gdy ocena = 1?
Odpowiedź
Ocena 1: Niedostateczny — żaden warunek od ==6 do ==2 nie pasuje, wykonuje się else.

✔️ Po tej sekcji powinieneś umieć:
  • pisać łańcuch if/elif/else
  • rozumieć, że wykonuje się tylko pierwszy pasujący blok
  • wiedzieć różnicę między wieloma if a elif
🧠 Sprawdź wiedzę — 2.6
Masz już if, else i elif — obsłużysz dowolną liczbę przypadków. Ale każdy warunek sprawdza tylko jedną rzecz. W sekcji 2.7 połączysz dwa warunki w jeden: and, or, not — i napiszesz program, który sprawdza wiek i prawo jazdy jednocześnie.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
2.7

Operatory logiczne: and, or, not

Wyobraź sobie trzy różne sytuacje: żeby prowadzić samochód potrzebujesz wieku 18+ I prawa jazdy — oba warunki naraz (and). Żeby zapłacić wystarczy mieć gotówkę LUB kartę — jedno z dwóch (or). Możesz wyjść bez parasola, jeśli NIE pada — odwrócenie warunku (not). Te trzy słowa działają w Pythonie dokładnie jak "i", "lub", "nie" w języku polskim.
Do tej pory każdy if sprawdzał jedną rzecz naraz. Często jednak decyzja zależy od kilku rzeczy jednocześnie — wstęp na kurs wymaga wieku i wiedzy, płatność przejdzie gotówką lub kartą, parasol bierzesz tylko gdy nie pada. Do łączenia warunków służą trzy operatory logiczne: and, or i not — a działają dokładnie tak, jak ich polskie odpowiedniki „i", „lub", „nie".
Obejrzyj scenę: kulka staje przed szlabanem z dwoma światłami. Światła sprawdzają się po kolei — razem z podkreśleniem części warunku w kodzie. Szlaban idzie w górę dopiero, gdy oba są zielone.
wiek = 20 prawo_jazdy = True if wiek > 18 and prawo_jazdy: print("Mozesz prowadzic!") wiek > 18 prawo_jazdy "Mozesz prowadzic!" and — szlaban otwiera się tylko przy OBU zielonych
To jest and, czyli „i" — operator wymagający. Całe wyrażenie jest True tylko wtedy, gdy oba połączone warunki są True; jedno czerwone światło i wynik od razu spada do False. W kodzie wygląda to tak:
Oba warunki prawdziwe — and daje True i print się wykonuje. Gdyby wiek wynosił 16, pierwsze światło byłoby czerwone i całość od razu spadłaby do False — bloku by nie było. and żąda spełnienia wszystkiego.

Drugi operator to or, czyli „lub". Ten sam szlaban, inna zasada — obejrzyj: pierwsze światło robi się czerwone (gotówki brak) i… nic się nie psuje. Drugie jest zielone, a przy or jedno wystarczy — szlaban w górę.
ma_gotowke = False ma_karte = True if ma_gotowke or ma_karte: print("Masz czym zaplacic.") ma_gotowke ma_karte "Masz czym zaplacic." or — JEDNO zielone wystarczy, szlaban i tak w górę
ma_gotowke to False, ale ma_karte to True — jeden prawdziwy warunek w zupełności wystarczy, or zwraca True. Blok zostałby pominięty tylko wtedy, gdyby oba światła były czerwone.

Trzeci operator to not, czyli „nie". Działa inaczej niż dwa poprzednie — nie łączy dwóch warunków, tylko odwraca jeden. To, co było True, staje się False, a to, co było False, staje się True. Przydaje się, gdy wygodniej zapytać „czy coś NIE zachodzi" niż „czy zachodzi" — na przykład „wyjdź bez parasola, jeśli nie pada".
Zmienna deszcz ma wartość False, więc not deszcz daje True i blok się wykonuje. Gdyby padało, czyli deszcz byłoby True, wtedy not deszcz dałoby False i print zostałby pominięty.

Po co w ogóle odwracać warunek, skoro można by go zapisać wprost? Bo czasem pytanie brzmi naturalniej „od tyłu". Wygodniej powiedzieć „jeśli gra NIE jest skończona, graj dalej" niż wymyślać warunek na sztywno opisujący trwającą grę. not pozwala zapisać myśl tak, jak ją formułujesz w głowie, i to często czyni kod czytelniejszym.
SyntaxError: invalid syntax
Polskie słowa i, lub, nie nie działają w Pythonie:
if wiek >= 18 i prawo_jazdy:   # ← błąd!
    print("Mozesz prowadzic!")
Python nie zna słowa i — szuka operatora logicznego, nie znajduje, zgłasza błąd. Operatory logiczne piszemy po angielsku:
and (i)  ·  or (lub)  ·  not (nie)
Dlaczego warto je opanować już teraz? Bo prawdziwe programy prawie nigdy nie sprawdzają jednej rzeczy. Dostęp do konta to poprawny login i poprawne hasło i aktywne konto. Promocja należy się, gdy ktoś jest nowym klientem lub ma kod rabatowy. Im więcej takich warunków potrafisz złożyć w jednym czytelnym if, tym mniej musisz zagnieżdżać i tym łatwiej ktoś inny zrozumie Twój kod.
🤔 Zgadnij albo odpowiedz: Co wypisze kod, gdy wiek = 16 i prawo_jazdy = True?
Odpowiedź
Nic — wiek >= 18 to False (16 < 18), więc and daje False niezależnie od prawo_jazdy.

✔️ Po tej sekcji powinieneś umieć:
  • łączyć warunki przez and, or, not
  • znać tabelę prawdy: and wymaga obu True, or wymaga jednego
  • wiedzieć kiedy użyć and, a kiedy or przy łączeniu warunków
🧠 Sprawdź wiedzę — 2.7
Łączysz już warunki z and i or — jeden if sprawdza kilka rzeczy naraz. Ale czasem logika jest warstwowa: najpierw sprawdź wiek, a potem wewnątrz sprawdź bilet. W sekcji 2.8 zobaczysz zagnieżdżone if — i dowiesz się kiedy wybrać and a kiedy nested if.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
2.8

Zagnieżdżone if

Wyobraź sobie system biletów w kinie: najpierw sprawdzają wiek (czy masz 18 lat?) — JEŚLI tak, sprawdzają bilet (czy masz bilet?) — JEŚLI tak, wchodzisz. Bez pierwszego sprawdzenia drugie nie ma sensu — nie ma co sprawdzać biletu u osoby, która i tak nie wejdzie. Zagnieżdżone if działa tak samo: wewnętrzny warunek jest sprawdzany tylko wtedy gdy zewnętrzny jest spełniony.
Czasem jedna decyzja zależy od drugiej — i to w określonej kolejności. Najpierw sprawdzasz wiek, a dopiero gdy się zgadza, ma sens pytanie o bilet. Takich warstwowych sytuacji nie opiszesz jednym warunkiem; potrzebujesz if umieszczonego wewnątrz innego if — to właśnie zagnieżdżanie. Warstwy wyznacza wcięcie: linia wcięta głębiej należy do warunku stojącego nad nią.

Zacznijmy od najmniejszej możliwej wersji — samo szczęśliwe przejście, jeszcze bez odmów. (A czemu nie zwykłe and? O tym za chwilę.)
Prześwietlmy ten kod. Patrz na dwie kreski wcięcia w kodzie i dwa odejścia w prawo na scenie — to to samo, zapalają się razem, krok po kroku.
wiek = 20 ma_bilet = True if wiek > 18: if ma_bilet: print("Wejdz, prosze.") if 20 > 18 ? Tak → if ma_bilet ? Tak → "Wejdz, prosze." głębiej w prawo = głębiej w if
Na rentgenie widać sedno: kulka przechodzi bramę wieku i skręca w prawo — to pierwsze wcięcie. Staje przed bramą biletu i skręca głębiej — to drugie. Dopiero podwójnie wcięta linia się wykonuje. Gdyby wiek wynosił 15, kulka odbiłaby w dół już przy pierwszej bramie — i do biletu w ogóle by nie doszło. Dokładnie jak bileter, który nie pyta piętnastolatka o bilet: sprawdzanie nie miałoby sensu, więc Python nawet tam nie zagląda.
Zbyt głębokie zagnieżdżenie tworzy trudny do czytania kod.
Przy 4+ poziomach kod staje się piramidą wcięć — ciężki do zrozumienia i debugowania. Jeśli oba warunki muszą być spełnione naraz: if A and B: robi to samo co if A: if B: — ale jest znacznie czytelniejsze.
Kiedy wybrać zagnieżdżony if, a kiedy and? Prosta reguła: jeśli chcesz dać inny komunikat dla każdego powodu odmowy — użyj zagnieżdżenia (wiesz, który warunek zawiódł). Jeśli chcesz tylko sprawdzić, czy oba warunki są spełnione — użyj and. W przykładzie z kinem: zagnieżdżenie pozwala powiedzieć "kup bilet przy kasie" lub "za młody" — and powiedziałoby tylko "nie możesz wejść".

Najlepiej zobaczyć obie wersje obok siebie. Zagnieżdżony if i połączenie przez and potrafią wpuścić gracza w dokładnie tej samej sytuacji — różnią się tym, ile potrafią powiedzieć, gdy go nie wpuszczają:
Tym samym domykasz cały moduł o warunkach. Masz już komplet narzędzi do podejmowania decyzji: wartości True i False, operatory porównania, if, else i elif, operatory logiczne and, or, not oraz zagnieżdżanie. Od teraz Twój program nie tylko liczy i wypisuje, ale też samodzielnie wybiera, co zrobić — a to jest sedno programowania. W kolejnych modułach te decyzje połączysz z pętlami i listami, i dopiero wtedy poczujesz, jak wiele potrafi prosty if.
🤔 Zgadnij albo odpowiedz: Co wypisze kod, gdy wiek = 15 i ma_bilet = True (wersja zagnieżdżona z porównania wyżej)?
Odpowiedź
Tylko dla doroslych. — zewnętrzny if wiek >= 18 jest False, bilet nie jest sprawdzany w ogóle.

✔️ Po tej sekcji powinieneś umieć:
  • pisać if w if z max 2–3 poziomami
  • wiedzieć kiedy użyć and zamiast zagnieżdżenia
  • wyjaśnić, dlaczego wewnętrzny warunek sprawdza się tylko gdy zewnętrzny jest spełniony
🧠 Sprawdź wiedzę — 2.8
Znasz już warunki w pełni: if, else, elif, and, or, not i zagnieżdżone if — wszystkie narzędzia do podejmowania decyzji w Pythonie. W podsumowaniu sprawdzisz całą wiedzę testem końcowym, a potem M03 nauczy Pythona zapamiętywać listy wartości.
Tu napiszesz kod i sprawdzisz go od razu. Bez praktyki przycisk „dalej" pozostaje zablokowany.
M02

Decyzje — Podsumowanie

✔️ Co umiesz po tym module:
  • rozumieć typ bool i wartości True/False
  • używać wszystkich 6 operatorów porównania
  • nigdy nie mylić = (przypisanie) z == (porównanie)
  • pisać if z prawidłowym wcięciem
  • pisać if/else dla dwóch ścieżek
  • pisać łańcuch if/elif/else dla wielu opcji
  • łączyć warunki przez and, or, not
  • pisać zagnieżdżone if i wiedzieć kiedy użyć and zamiast
🎯 Brawo! Właśnie nauczyłeś się czegoś kluczowego — Twoje programy mogą teraz podejmować decyzje. Wiesz, jak używać True i False, wszystkich 6 operatorów porównania, if, if/else, if/elif/else, operatorów and, or, not, i zagnieżdżonych warunków. Ale teoria bez praktyki to tylko słowa.

Teraz kolej na Ciebie — napisz System walki samodzielnie, bez zaglądania do rozwiązania. Przeczytaj wymagania, zastanów się jak to zbudować, i zacznij pisać linijka po linijce. Poprawiaj błędy, które się pojawią — to normalna część programowania. "Pokaż rozwiązanie" to ostateczność, gdy naprawdę utkniesz — nie pierwszy krok.
⚔️ Projekt końcowy — „System walki"

Bruno staje do walki z goblinem. Twój program policzy obrażenia (z szansą na trafienie krytyczne), sprawdzi tarczę goblina i oceni, czy przeciwnik jeszcze walczy — łącząc wszystko z tego modułu: porównania, if/elif/else, and i zagnieżdżony if. Dane walki masz gotowe w zmiennych na górze — Ty dopisujesz samą logikę.

  1. Broń. Jeśli bronią jest miecz, wypisz Bron: miecz.
  2. Trafienie krytyczne. Jeśli siła bohatera osiągnęła próg krytyka — obrażenia się podwajają i wypisz Trafienie krytyczne!; w przeciwnym razie obrażenia są bazowe i wypisz Zwykly cios.
  3. Tarcza (warunek w warunku). Jeśli goblin ma tarczę, a cios jest słaby (obrażenia poniżej 30) — obrażenia spadają do zera i wypisz Tarcza zablokowala slaby cios!
  4. Zdrowie. Policz, ile zdrowia zostało goblinowi po ciosie, i wypisz f-stringiem HP goblina: z tą wartością.
  5. Stan goblina (kilka progów). Zdrowie padło do zera lub niżej → Goblin pokonany!; jest poniżej 10 → Goblin ledwo zyje; w przeciwnym razie → Goblin walczy dalej.
  6. Pewność siebie (dwa warunki naraz). Jeśli goblin ma tarczę i wciąż ma sporo zdrowia (powyżej 20) — wypisz Goblin czuje sie pewnie.
Po skończeniu sprawdź, czy Twój program:
  • sprawdza broń i nalicza trafienie krytyczne po progu siły,
  • liczy obrażenia rozgałęzieniem, a tarczę warunkiem w warunku,
  • ocenia stan goblina kilkoma progami (pokonany / ledwo żyje / walczy dalej),
  • sprawdza pewność siebie dwoma warunkami naraz i liczy zdrowie po ciosie.
⏳ Python uruchomi się przy pierwszym „Uruchom" (pierwszy raz chwilę trwa).
🧮 Bonus dla dorosłych — „Kalkulator BMI" (nieobowiązkowe, poza bramą)

Bonus dla starszych uczniów: policz BMI i przypisz kategorię z poradą — ten sam zestaw narzędzi (if/elif/else i porównania) co w całym module, ale na realnym, dorosłym przykładzie. Jest poza bramą — możesz go pominąć albo zrobić dla wprawy.

  1. BMI. Policz BMI ze wzoru — waga podzielona przez wzrost podniesiony do kwadratu — i wypisz je z jednym miejscem po przecinku.
  2. Kategoria. Łańcuchem if/elif/else przypisz kategorię wg progów: niedowaga poniżej 18.5, waga prawidłowa do 25, nadwaga do 30, otyłość powyżej.
  3. Porada. Dopisz krótką poradę do każdej kategorii i wypisz kategorię oraz poradę.
⏳ Python uruchomi się przy pierwszym „Uruchom" (pierwszy raz chwilę trwa).
M02

Test końcowy — Decyzje i Warunki

Zdaj test końcowy, żeby odblokować Moduł 03. Próg: 80%. Każde podejście to NOWY zestaw 15 pytań z całego modułu. Prób bez limitu.
📝 Test końcowy — Moduł 02
Sprawdź całą wiedzę z modułu o warunkach. Odpowiedz na wszystkie pytania, potem sprawdź wynik.
🏆

Kurs ukończony — Co dalej?

🎉 Brawo! Przeszedłeś przez 7 modułów Pythona od zera.
Zmienne, warunki, pętle, funkcje, listy, stringi, słowniki — masz to wszystko.
✔️ Co umiesz po tym kursie:
  • Pisać programy, które działają — od pustego pliku do gotowego projektu
  • Używać zmiennych, typów danych i konwersji typów
  • Pisać warunki if/elif/else i zagnieżdżać logikę
  • Budować pętle for i while, sterować nimi przez break i continue
  • Tworzyć własne funkcje i rozumieć zakres zmiennych
  • Pracować z listami, słownikami i metodami stringów
  • Czytać komunikaty błędów i naprawiać kod
Następny krok: Snake XTRA

Python bez Pygame to silnik bez samochodu. W Snake XTRA budujesz grę od zera: okno, ruch węża, jedzenie, punkty na planszy, ekran końcowy i tempo, które rośnie z każdym jabłkiem. Piszesz w przeglądarce, tak samo jak tutaj, i po każdym kroku masz kod, który da się uruchomić. Żadna wiedza z tego kursu nie idzie w kosz — każda linijka gry opiera się na tym co już umiesz.
🐍 Przejdź do Snake XTRA →
25 lekcji · od okna do pełnej gry · w pakiecie z Podstawami 158 PLN