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.
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
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() 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:
"..." lub pojedynczego '...' — oba działają tak samo.
42 to liczba, a nie tekst. Ta drobna różnica — tekst w cudzysłowie albo goła liczba — jeszcze nieraz da o sobie znać, bo Python obchodzi się z nimi zupełnie inaczej. Liczby potrafi dodawać i mnożyć, tekst umie tylko sklejać. Na razie zapamiętaj jedną prostą rzecz: słowa biorę w cudzysłów, liczby zostawiam bez:
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:
print() ułożonych jeden pod drugim składa się na coś, co naprawdę wygląda jak początek gry:
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 w sekcji o typach. 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.
Witaj to nazwa zmiennej — poszukał jej w pamięci, 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'.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.
print() z tekstem i liczbąprint() przez przecinekprint() bez argumentówprint().wynik i zmienia liczbę w środku.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ę.str (od angielskiego string, czyli sznurek liter, bo tekst to ciąg znaków ustawionych jeden za drugim, jak koraliki na sznurku):
int (od angielskiego integer = liczba całkowita). Liczby całkowite nie mają cudzysłowu:
float (od angielskiego floating point = liczba zmiennoprzecinkowa). Używa się kropki, nie przecinka:
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.True — str, int czy bool?bool — to jeden z 4 typów Pythona. True i False to jego jedyne wartości.= w jednej kolumnie; Python tego nie wymaga, ale robimy tak dlatego, że od razu widać, gdzie kończą się nazwy, a zaczynają wartości:
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:
moje_imie = "Bruno".= 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.=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.
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.type() pozwala to wykryć w sekundę, zamiast w nieskończoność zgadywać i tracić czas. Wypróbujmy ją na zmiennych gracza Bruna z poprzedniej lekcji:
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.
type("5") — int czy str?<class 'str'> — cyfra w cudzysłowie to tekst. Cudzysłów zawsze oznacza str.<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.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:
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.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.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.
type() do sprawdzania typu zmiennej"5" (str — tekst) od 5 (int — liczba)type() wkładamy do print().type() różnych wartości: 3, "3", 3.0, False.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.# (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.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:
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.
# 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:
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.# 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.
## na początku#) — nawet jeśli wynik wygląda tak samo.#) i zobaczyć, co zniknie z wyniku.* (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ń:
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:
// 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.25 // 7?10 - 7 = 3.
**, 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:
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.+, -, *, / — 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.// 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.
+, -, *, /, //, %, **/ (wynik float) a // (wynik całkowity)// 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.
//, % i ** na różnych liczbach.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.2 + 3 dałoby 5, razy 4 — dwadzieścia. Sprawdź, co naprawdę wychodzi:
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.2 ** 3 ** 2? Podpowiedź: to NIE jest (2 ** 3) ** 2.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.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.
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.
"Gracz Bruno ma 1250 punktów" jedną linią kodu, bez ręcznego sklejania.
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.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:
imie = "Ana" i wynik = 99 jako jedno zdanie?f"{imie} ma wynik {wynik}" — litera f i wartości w klamrach {}. Python podmienia klamry na wartości zmiennych.(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.
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:
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.
str) z liczbą (int). Użyj f-stringa: f"Punkty: {punkty}" — klamry robią konwersję za Ciebie.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.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.
f"..." i wstawiać zmienne w {}:.1f lub :.2fZłóż 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.
imie, zyczenie, podpis,= — u góry i u dołu,"500" + 1 wywołuje błąd, a int("500") + 1 daje 501.
f przed cudzysłowem.{}."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.int() (integer = liczba całkowita) — zamienia na liczbę całkowitąfloat() (floating-point = zmiennoprzecinkowa) — zamienia na liczbę z ułamkiemstr() (string = sznurek) — zamienia na tekst"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:str — to tekst. Nawet jeśli wygląda jak liczba, cudzysłów sprawia, że Python traktuje to jako ciąg znaków. Teraz zamieniamy:+ 100 działa i daje 600. Bez konwersji Python rzuciłby błąd, bo tekstu nie można dodać do liczby.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.int() z liczbą bez ułamka:int(2.0) daje 2, to rozumiemy. A co, gdy float ma część dziesiętną?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.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).int. int("trzy") — słowo, błąd. int("3.14") — ma kropkę, też błąd dla int().float("3.14"), potem ewentualnie int().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.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.
int(), float()str()int() ucina część dziesiętną (nie zaokrągla)ValueErrorrandom), zamiast pisać wszystko od zera.
int() ucina, nie zaokrągla.int(), float(), str() na różnych wartościach.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.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!
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:randint(1, 10) losuje nową liczbę przy każdym uruchomieniu. Wynik jest inny za każdym razem.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.
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.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 brandint dla pozycji i rozmiaru — piksele i rozmiar muszą być liczbami całkowitymiuniform dla prędkości — prędkość może być 3.2, 2.7, 4.1 (potrzebujemy ułamka)import random na górze pliku?random, dopóki go nie zaimportujesz. Bez import random na górze pliku — każde użycie random.cokolwiek da ten błąd.import random musi być przed pierwszym użyciem.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.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.
import nazwarandom.randint(a, b) do losowania liczby całkowitejrandom.uniform(a, b) do losowania liczby zmiennoprzecinkowejif — program, który potrafi wybrać, co zrobić.
random.randint i random.uniform z różnymi granicami (pamiętaj o import random na górze).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.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}!")
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.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.input(), gdy zamiast imienia wpiszesz liczbę? Sprawdźmy typ:wiek = input("Ile masz lat? ")
print(type(wiek))
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)
"14" do liczby 10 — to różne typy. input() zawsze zwraca str, więc samo wpisanie liczby nie wystarczy.input() w int() (albo float()): wiek = int(input("Ile masz lat? "))int() z sekcji 1.8):wiek = int(input("Ile masz lat? "))
print(f"Za 10 lat bedziesz miec {wiek + 10} 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.input()input() zawsze zwraca str (tekst)int(input(...)) / float(input(...))TypeError z dodawania tekstu do liczby i go naprawićif, True/False). Właśnie dlatego input() poznajesz teraz — od tej chwili będzie wracać w prawie każdym zadaniu.
input() i sam sprawdzisz wynik — my podstawimy dane. Bez praktyki przycisk „dalej" pozostaje zablokowany.input() czyta wpisaną wartość? Użyj pola „📥 Spróbuj sam" pod kodem — wpisz dane i zobacz, co wypisze Twój program.input(), potem int(input()) i policz coś na wczytanej liczbie.print()type()#int(), float(), str()import random i używać random.randint()// i %), formatować f-stringami, konwertować typy i losować liczby przez random. To fundament na którym stoi każdy program na świecie.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.
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ć.if (jeśli) i else (w przeciwnym razie). Dzięki temu ten sam program potrafi zachować się inaczej dla każdego, kto go uruchomi.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
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.swiatlo = True, potem swiatlo = False — a żarówka od razu pokazuje jej skutek:bool (boolean = logiczny), o dokładnie dwóch wartościach — True (prawda) i False (fałsz).type():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.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:true — nie wartości logicznej. Wartości logiczne piszemy zawsze z wielkiej litery: True i False.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.True lub False. Sprawdźmy to na liczbach, które bez trudu policzysz w głowie: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.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: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.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.print(False == False)?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!)True i False piszemy z wielkiej litery==, !=, <, >, <=, >= — i dowiesz się, który najczęściej prowadzi do błędu.
True albo False.3 > 2, "kot" == "pies", 10 != 10.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ź:> 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: Falsehp > 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.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.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.print(7 => 5) zgłasza błąd składni:>= (większy lub równy) · ✅ <= (mniejszy lub równy)=> · ❌ =<True lub False. Cztery z nich — >, <, >=, <= — porównują wielkość, a dwa pozostałe — == i != — pytają o równość i różnicę.==, 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.print(10 < 5 < 20)?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.a <= x < bbool= 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.
>= i <= (najpierw kierunek, potem =).0 < 7 < 10, 5 <= 5 <= 5.= 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ć.= 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.if, które są miejscem zadawania pytań, zawsze potrzebujesz podwójnego ==: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".= zamiast dwóch. To słynna pułapka „if x = 5". Co zrobi Python?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.= to przypisanie, dwa znaki == to porównanie.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.== 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."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.= 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.print("5" == 5)?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.= (przypisanie) z == (porównanie)=== w warunku= 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.
= ZAPISUJE wartość, a == PYTA o równość.print(7 == 7) i porównaj z x = 7 (przypisanie nic nie wypisuje).if to pierwsza i najważniejsza decyzja w programowaniu: sprawdza warunek i wykonuje blok kodu tylko gdy warunek jest prawdziwy.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: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.{}, 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.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: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.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).: i wcięcie zawsze chodzą razem, zobaczmy też, co się stanie, gdy zapomnisz właśnie dwukropka: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.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.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.temperatura = 20? Ile linii?Ten kod wykonuje sie zawsze. — blok if temperatura > 30 zostaje pominięty, ale ostatni print jest poza wcięciem.if z prawidłowym wcięciem (4 spacje)if może się nie wykonać wcaleif — 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.
if — pamiętaj o dwukropku : na końcu warunku i o wcięciu 4 spacje w następnej linii (klawisz Tab też zadziała). Na rozbieg trzy krótkie szczeble (napraw → uzupełnij → ułóż); wszystkie ćwiczenia poza ostatnim odblokowują następną lekcję (Wyzwanie jest dla chętnych). Zadania 6 i 7 to celowo zepsuty kod — napraw błąd wcięcia i brakujący dwukropek.if/else daje programowi tę samą gwarancję — zawsze wykona się dokładnie jedna gałąź, nigdy obie i nigdy żadna.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: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.if mógłby milczeć, a if/else milczeć nie potrafi.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.%, 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: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.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.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.liczba = 8?8 jest parzysta. — 8 % 2 = 0, warunek True, wykonuje się gałąź if.if/elseif/else daje gwarancję, której sam if nie dajeif 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.
if ORAZ po else i o wcięciu obu bloków.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.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.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?".else — siatki bezpieczeństwa na wszystko, czego nie przewidziałeś.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:elif ustawi kilka OSOBNYCH if — wtedy Python sprawdza każdy z nich niezależnie:if zamiast elif — subtelny błąd logiczny: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.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.ocena = 1?Ocena 1: Niedostateczny — żaden warunek od ==6 do ==2 nie pasuje, wykonuje się else.if/elif/elseif a elifif, 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.
elif (np. kategorie wieku) i sprawdź różne wartości.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.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".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: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.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 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.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".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.not pozwala zapisać myśl tak, jak ją formułujesz w głowie, i to często czyni kod czytelniejszym.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)if, tym mniej musisz zagnieżdżać i tym łatwiej ktoś inny zrozumie Twój kod.wiek = 16 i prawo_jazdy = True?wiek >= 18 to False (16 < 18), więc and daje False niezależnie od prawo_jazdy.and, or, notand wymaga obu True, or wymaga jednegoand, a kiedy or przy łączeniu warunkówand 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.
and, or, not.True and False, True or False, not True.if działa tak samo: wewnętrzny warunek jest sprawdzany tylko wtedy gdy zewnętrzny jest spełniony.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ą.and? O tym za chwilę.)if A and B: robi to samo co if A: if B: — ale jest znacznie czytelniejsze.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ść".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ą:
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.wiek = 15 i ma_bilet = True (wersja zagnieżdżona z porównania wyżej)?Tylko dla doroslych. — zewnętrzny if wiek >= 18 jest False, bilet nie jest sprawdzany w ogóle.if w if z max 2–3 poziomamiand zamiast zagnieżdżeniaif, 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.
if wcinasz głębiej (8 spacji) — to wcięcie wyznacza, co jest „w środku" czego.= (przypisanie) z == (porównanie)if z prawidłowym wcięciemif/else dla dwóch ścieżekif/elif/else dla wielu opcjiand, or, notif i wiedzieć kiedy użyć and zamiastTrue 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.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ę.
Bron: miecz.Trafienie krytyczne!; w przeciwnym razie obrażenia są bazowe i wypisz Zwykly cios.Tarcza zablokowala slaby cios!HP goblina: z tą wartością.Goblin pokonany!; jest poniżej 10 → Goblin ledwo zyje; w przeciwnym razie → Goblin walczy dalej.Goblin czuje sie pewnie.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.
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.append() w środku. Różnią się jedną rzeczą, za to zasadniczą: filtr decyduje, KTÓRE elementy przejdą, a transformacja zmienia KAŻDY z nich. Zapamiętaj to zdanie — mylenie tych dwóch to najczęstszy błąd przy wzorcach pętlowych.append() wyłącznie dla elementów spełniających warunek — w efekcie powstaje nowa lista samych zwycięstw, podczas gdy oryginał zostaje nietknięty. To ważne, bo bardzo często chcesz mieć pod ręką i komplet danych, i ich przefiltrowaną wersję obok siebie, żeby móc je porównać albo wrócić do pełnej listy.append() stoi na tym samym poziomie wcięcia co if zamiast w jego środku, do nowej listy wpadają WSZYSTKIE elementy — warunek nie blokuje niczego, bo dokładanie dzieje się niezależnie od niego.append() musi być wcięty pod if. W transformacji jest odwrotnie: przelicza się każdy element, więc append() stoi poza warunkiem albo w obu gałęziach if / else.append() — a robią co innego. Filtr skraca: nowa lista bywa krótsza od oryginału, czasem nawet zupełnie pusta. Transformacja zachowuje długość: ile elementów weszło, tyle wychodzi, tylko w zmienionej postaci. Dlatego przy takim kodzie wystarczy jedno pytanie kontrolne: czy ktoś ma wypaść, czy każdy ma się zmienić? Odpowiedź od razu mówi, gdzie postawić append().[1, -2, 3] przechodzi przez pętlę, w której ujemne zamieniasz na 0, a resztę przepisujesz bez zmian. Ile elementów ma nowa lista?[1, 0, 3]. To transformacja, więc nikt nie wypada; gdyby to był filtr odsiewający ujemne, zostałyby dwa.append w środku ifappend(przeliczony element)