Wstęp jest tą częścią , którą przeskakujesz, aby dostać się do dobrych rzeczy, prawda? Jasne, możesz go pominąć, jeśli chcesz , ale kto wie, co możesz przegapić
. To nie jest zbyt długie, więc może na wszelki wypadek powinieneś to sprawdzić.
Co to jest programowanie?
Po prostu programowanie oznacza nakazanie komputerowi zrobienia czegoś. Komputery to głupie maszyny. Nie wiedzą jak coś zrobić. Musisz im wszystko powiedzieć, a wszystkie szczegóły muszą być poprawne. Ale jeśli podasz im odpowiednie instrukcje, mogą zrobić wiele wspaniałych i niesamowitych rzeczy.
Instrukcja jest podstawową komendą, którą przekazujesz komputerowi, zazwyczaj w celu wykonania pojedynczej, bardzo specyficznej rzeczy.
Program komputerowy składa się z wielu instrukcji. Komputery robią wszystko, co robią dzisiaj, ponieważ wielu inteligentnych programistów napisało programy lub oprogramowanie, aby powiedzieć im, jak. Oprogramowanie oznacza po prostu program lub kolekcję programów uruchamianych na komputerze lub czasami na innym komputerze, z którym jest połączony, na przykład na serwerze internetowym.
Komputery "myślą" za pomocą wielu, wielu i wielu obwodów elektrycznych. Na najbardziej podstawowym poziomie obwody te są przełącznikami, które są WŁĄCZONE lub WYŁĄCZONE. Inżynierowie i informatycy używają 1 i 0, aby oznaczyć ON i OFF. Wszystkie te 1 i 0 to rodzaj kodu zwanego binarnym. Binarny tak naprawdę oznacza "dwa stany". Oba stany to WŁĄCZONE i WYŁĄCZONE lub 1 i 0. Czy wiesz: cyfra binarna = bit.
Python - język dla nas i komputera
Wszystkie komputery używają plików binarnych. Ale większość ludzi nie mówi dobrze binarnie. Potrzebujemy łatwiejszego sposobu, aby powiedzieć komputerowi, co chcemy zrobić. Więc ludzie wymyślili języki programowania. Komputerowy język programowania pozwala nam pisać rzeczy w zrozumiały dla nas sposób, a następnie tłumaczy je na binarne, aby komputer mógł z nich korzystać. Istnieje wiele różnych języków programowania. Tu nauczysz się, jak używać jednego z tych języków - jednego o nazwie Python - aby powiedzieć komputerowi, co ma robić.
Dlaczego warto uczyć się programowania?
Nawet jeśli nie zostaniesz profesjonalnym programistą (większość ludzi tego nie robi), jest wiele powodów, aby uczyć się programowania:
• Najważniejsze jest to, że chcesz! Programowanie może być bardzo interesujące i satysfakcjonujące, jako hobby lub zawód.
• Jeśli interesujesz się komputerami i chcesz wiedzieć więcej o tym, jak działają i jak możesz zmusić ich do robienia tego, co chcesz, to dobry powód, aby dowiedzieć się o programowaniu.
• Może chcesz tworzyć własne gry, a może nie możesz znaleźć programu, który robi dokładnie to, co chcesz lub potrzebujesz, abyś mógł napisać własne.
v Komputery są obecnie wszędzie, więc jest duża szansa, że będziesz korzystać z komputerów w pracy, w szkole lub w domu - prawdopodobnie wszystkie trzy. Poznanie programowania pomoże Ci lepiej zrozumieć komputery.
Dlaczego Python?
Mając do wyboru wszystkie języki programowania (a jest ich wiele!), Dlaczego wybraliśmy Pythona na książkę programistyczną dla dzieci? Oto kilka powodów:
• Python został stworzony od początku, aby był łatwy do nauczenia. Programy Pythona dotyczą tego jak najłatwiej czytać, pisać i rozumieć dowolny język komputerowy.
• Python jest bezpłatny. Możesz pobrać Pythona - i wiele, wiele zabawnych i przydatnych programów napisanych w Pythonie - za darmo.
• Python to oprogramowanie open source. Częścią tego, co oznacza open source, jest to, że każdy użytkownik może rozszerzyć Pythona (stwórz rzeczy, które pozwolą ci zrobić więcej z Pythonem lub łatwiej zrobić to samo). Wielu ludzi to zrobiło, a istnieje duża kolekcja darmowych rzeczy w Pythonie, które można pobrać.
• Python nie jest zabawką. Chociaż jest to bardzo dobre narzędzie do nauki programowania, jest używane codziennie przez tysiące profesjonalistów na całym świecie, w tym programistów w instytucjach takich jak NASA i Google. Kiedy więc nauczysz się Pythona, nie musisz przełączać się na "prawdziwy" język, aby tworzyć "prawdziwe" programy. Możesz wiele zrobić z Pythonem.
• Python działa na różnych komputerach. Python jest dostępny dla komputerów z systemem Windows, komputerów Mac i komputerów z systemem Linux. W większości przypadków ten sam program Python, który działa na komputerze z systemem Windows w domu, będzie działał na komputerze Mac w Twojej szkole. (Pamiętaj, że jeśli komputer, którego chcesz użyć, nie ma Pythona, możesz go pobrać za darmo).
• Lubię Pythona. Uwielbiam to i korzystam z niego, i myślę, że również. Myśląc jak programista. Używamy Pythona , ale większość tego, czego dowiesz się o programowaniu tutaj, może być użyta z każdym innym językiem komputerowym. Nauka programowania w Pythonie zapewni Ci świetny start w prawie każdym innym języku, którego chcesz używać w przyszłości.
Tu nauczymy Cię podstaw programowania komputerowego. Kurs jest przeznaczony dla dzieci, ale może go używać każdy, kto chce się nauczyć programować komputer. Nie musisz nic wiedzieć o programowaniu, ale powinieneś znać podstawy korzystania z komputera. Może używasz go do wysyłania e-maili, surfowania w sieci, słuchania muzyki, grania w gry lub pisania raportów do szkoły. Jeśli możesz wykonać podstawowe czynności na swoim komputerze, takie jak uruchomienie programu, otwieranie i zapisywanie plików, nie powinieneś mieć problemów
Czego potrzebujesz?
Nauczysz się programowania za pomocą języka komputerowego o nazwie Python. Python jest darmowy i możesz go pobrać z kilku miejsc w Sieci. Aby nauczyć się programowania u nas, wystarczy:
• Ten tekst (oczywiście!).
• Komputer z systemem Windows, Mac OS X lub Linux. Przykłady są wykonywane w systemie Windows.
• Podstawowa wiedza na temat korzystania z komputera (uruchamianie programów, zapisywanie plików itp.). Jeśli masz z tym problemy, może uda ci się uzyskać pomoc od kogoś.
• Zezwolenie na instalację Pythona na komputerze (od rodzica, nauczyciela lub osoby odpowiedzialnej za komputer).
• Pragnienie uczenia się i próbowania rzeczy, nawet jeśli nie zawsze pracują za pierwszym razem.
Czego nie potrzebujesz?
Aby nauczyć się programowania u nas, nie musisz:
• Kupować oprogramowania. Wszystko, czego potrzebujesz, jest bezpłatne.
• ? Żadnej wiedza na temat programowania komputerowego. Ten tekst jest dla początkujących.
Korzystanie z tekstu
Jeśli zamierzasz korzystać z tego tekstu, aby nauczyć się programowania, oto kilka wskazówek, które pomogą Ci lepiej z niej skorzystać:
• Postępuj zgodnie z przykładami.
• Wpisz programy.
• Wwykonuj pytania quizu.
• Nie martw się, bądź szczęśliwy!
Zawsze staraj się śledzić i pisać programy . (Powiem ci dokładnie, jak to zrobić.) Możesz po prostu usiąść na dużym, wygodnym krześle i przeczytać cały tekst, a prawdopodobnie dowiesz się czegoś o programowaniu. Ale nauczysz się o wiele więcej przez programowanie.
Instalowanie Pythona
Aby korzystać z kursu , musisz zainstalować program Python na swoim komputerze. Nie martw się o popełnianie błędów. W rzeczywistości popełnisz wiele z nich! Myślę, że popełnianie błędów i zastanawianie się, jak je znaleźć i naprawić, jest jednym z najlepszych sposobów nauki. W programowaniu błędy zazwyczaj nie kosztują niczego poza odrobiną czasu. Więc zrób dużo, ucz się od nich i … baw się dobrze.
Pierwszą rzeczą, którą musisz zrobić, jest zainstalowanie Pythona na komputerze, którego zamierzasz używać. Znajdź wersję instalatora zgodną z systemem operacyjnym komputera.
W pierwszych dniach komputerów osobistych ludzie mieli łatwość. Przy wielu pierwszych komputerach wbudowano w komputer język programowania BASIC. Nie musieli niczego instalować. Wszystko, co zrobili, to włączenie komputera, a ekran powiedziałby "GOTOWE" i mogli zacząć pisać programy BASIC. Brzmi świetnie, co? Oczywiście to "GOTOWE" było wszystkim, co masz. Bez programów, bez okien, bez menu. Jeśli chcesz, aby komputer coś zrobił, musisz napisać program! Nie było edytorów tekstu, odtwarzaczy multimedialnych, przeglądarek internetowych ani żadnych innych rzeczy, do których jesteśmy przyzwyczajeni. Nie było nawet sieci do przeglądania. Nie było wyszukanej grafiki ani dźwięku, z wyjątkiem sporadycznego "sygnału", jeśli popełniłeś błąd
Istnieją wersje dla Windows, Mac OS X i Linux. Wszystkie nasze przykłady używają Windowsa, ale użycie Pythona w Mac OS X lub Linux jest bardzo podobne. Postępuj zgodnie z instrukcjami na stronie internetowej, aby uruchomić odpowiedni instalator dla swojego systemu. Wersja Pythona, której używamy, to wersja 2.7.3.
Python 2 vs. Python 3
Kiedy ukazała się nowa wersja Pythona, Python 3, okazało się jednak, że nie jest to naprawdę "uaktualnienie" tyle, co punkt rozwidlający. To znaczy, wielu ludzi nie chce przełączyć się na Python 3, więc zostali z Pythonem 2
Uruchamianie Pythona z IDLE
Istnieje kilka sposobów na rozpoczęcie korzystania z Pythona. Jeden nazywa się IDLE, i na razie będziemy go używać. W menu Start w Pythonie 2.7 zobaczysz IDLE (GUI Pythona). Kliknij tę opcję, a otworzy się okno IDLE. Powinien wyglądać jak okno poniżej.
IDLE to powłoka Pythona. Powłoka jest w zasadzie sposobem na interakcję z programem poprzez wpisanie tekstu, a ta powłoka pozwala na interakcję z Pythonem. (To dlatego widzisz Python Shell na pasku tytułowym okna.) IDLE również jest GUI, dlatego w menu Start pokauzje Python GUI. IDLE ma kilka innych rzeczy oprócz powłoki, ale do tego dojdziemy za minutę.
>>> na rysunku jest znakiem zachęty Pythona. Monit jest tym, co program wyświetla, gdy czeka, aż coś wpiszesz. Polecenie >>> informuje, że Python jest gotowy do rozpoczęcia pisania instrukcji Pythona.
GUI oznacza graficzny interfejs użytkownika. Oznacza to coś z oknami, menu, przyciskami, paskami przewijania itp. Programy, które nie mają GUI, nazywane są programami tekstowymi, programami konsoli lub programami wiersza poleceń.
Instrukcje, proszę
Dajmy Pythonowi naszą pierwszą instrukcję. Najedź kursorem na koniec znaku zachęty >>> wpisz i naciśnij klawisz Enter. (Na niektórych klawiaturach nazywa się to klawiszem Return.) Musisz nacisnąć klawisz Enter po każdym wpisanym wierszu. Po naciśnięciu klawisza Enter otrzymasz tę odpowiedź:
print "Hello World!"
Hello World!
>>>
Poniższy rysunek pokazuje, jak wygląda to w oknie IDLE
Python zrobił to, co powiedziałeś: wyświetla twoją wiadomość. (W programowaniu drukowanie często oznacza wyświetlanie tekstu na ekranie, zamiast drukowania go na kartce papieru za pomocą drukarki.) Ta jedna linia jest instrukcją Pythona. Jesteś na dobrej drodze do programowania! Komputer jest pod twoją komendą! Przy okazji, ucząc się programowania, istnieje tradycja, że pierwszą rzeczą, którą robisz przy nauce programowania, jest wyświetlanie "Hello World!". Podążasz za tą tradycją. Witamy w świecie programowania! Dobre pytanie! IDLE stara się pomóc ci zrozumieć rzeczy nieco lepiej. Pokazuje rzeczy w różnych kolorach, aby pomóc Ci odróżnić różne części kodu od siebie. (Kod to kolejny termin na instrukcje, które dajesz komputerowi w języku takim jak Python).
Jeśli coś nie działa
Jeśli popełnisz błąd, możesz zobaczyć coś takiego:
>>> pront "Hello World!"
SyntaxError: invalid syntax
>>>
Ten komunikat o błędzie oznacza, że wpisałeś coś, czego Python nie rozumiał. W tym przykładzie print jest błędnie zapisane jako pront , a Python nie wie, co z tym zrobić. Jeśli tak się stanie, spróbuj ponownie i upewnij się, że wpisujesz dokładnie tak, jak w przykładzie. To prawda. To dlatego, że print jest słowem kluczowym Pythona, a pront nie.
Słowo kluczowe to specjalne słowo, które jest częścią języka Python (znanego również jako słowo zastrzeżone)
Interakcja z Pythonem
Użyłeś Pythona w trybie interaktywnym. Wpisałeś polecenie (instrukcję), a Python natychmiast ją wykonał.
Wykonywanie polecenia, instrukcji lub programu to po prostu fantazyjny sposób mówienia "uruchom" go lub "wykonaj".
Spróbujmy czegoś innego w trybie interaktywnym. Wpisz to w wierszu polecenia:
>>> print 5 + 3
8
>>>
Więc Python może dodawać! Nie powinno to dziwić, ponieważ komputery są dobre w arytmetyce. Spróbujmy jeszcze raz:
>>> print 5 * 3
15
>>>
W prawie wszystkich programach komputerowych i językach symbol * służy do mnożenia. Ta postać jest nazywana asterisk lub gwiazdką.
Jeśli jesteś przyzwyczajony do pisania "5 razy 3" jako "5 x 3" w klasie matematycznej, będziesz musiał przyzwyczaić się do używania * do mnożenia w Pythonie. (Jest to symbol powyżej liczby 8 na większości klawiatur.)
Dobra, a co powiesz na to:
>>> print 5 * 3
15
>>>
Dobra, a co powiesz na to:
>>> print 1234567898765432123456789 * 9876543212345678987654321
12193263200731596000609652202408166072245112635269
>>>
Zgadza się. Z komputerem możesz robić matematykę na naprawdę, naprawdę dużych liczbach. Oto coś, co możesz zrobić:
>>> print "kot" + "pies"
kotpies
>>>
Lub spróbuj tego:
>>> print "cześć" * 20
cześć cześć cześć cześć cześć cześć cześć cześć cześć cześć
cześć cześć cześć cześć cześć cześć cześć cześć cześć cześć
Poza matematyką, kolejną rzeczą, w której komputery są dobre, jest robienie różnych rzeczy. Tutaj powiedzieliśmy Pythonowi, aby wydrukował "cześć" 20 razy. Później zrobimy więcej w trybie interaktywnym, ale w tej chwili
Czas na programowanie
Do tej pory przyjrzeliśmy się pojedynczym instrukcjom Pythona (w trybie interaktywnym). Chociaż jest to świetne do sprawdzenia niektórych rzeczy, które Python może zrobić, te przykłady nie są tak naprawdę programami. Jak wspomniałem wcześniej, program to zbiór instrukcji zebranych razem. Zróbmy więc nasz pierwszy program Pythona. Po pierwsze, potrzebujesz sposobu na wpisanie programu. Jeśli wpiszesz to w interaktywnym oknie, Python nie "zapamięta". Musisz użyć edytora tekstu (takiego jak Notatnik dla Windows lub TextEdit dla Mac OS X lub vi dla Linuksa), który może zapisać program na dysku twardym. IDLE jest wyposażony w edytor tekstu, który jest znacznie lepszy dla tego, czego potrzebujesz niż Notatnik. Aby go znaleźć, wybierz Plik > Nowe okno z menu IDLE. Zobaczysz okno podobne do tego na następnym rysunku. Pasek tytułu mówi Bez tytułu, ponieważ nie podałem jeszcze nazwy pliku.
Kiedy mówię o opcjach menu, takich jak Plik > Nowy, pierwsza część (w tym przypadku Plik) to menu główne. > Informuje, że następną rzeczą (Nowy w tym przypadku) jest pozycją w menu Plik .
Zobaczysz okno podobne do tego na następnym rysunku. Pasek tytułu mówi Bez tytułu, ponieważ nie podałeś jeszcze nazwy pliku.
Teraz wpisz program w poniższej liście do edytora.
Listing 1.1 Nasz pierwszy prawdziwy program
print "Kocham pizzę!"
print "pizza" * 20
print "mniam" * 40
print "Jestem pełny".
Po zakończeniu zapisz program za pomocą opcji menu Plik > Zapisz lub Plik > Zapisz jako. Wywołaj plik pizza.py. Możesz zapisać go w dowolnym miejscu (o ile pamiętasz, gdzie jest, abyś mógł go później znaleźć). Możesz utworzyć nowy folder do zapisywania programów w Pythonie. Ważna jest część .py na końcu nazwy pliku, ponieważ informuje ona komputer, że jest to program w Pythonie, a nie tylko stary plik tekstowy. Być może zauważyłeś, że edytor używał różnych kolorów w programie. Niektóre słowa są pomarańczowe, a inne zielone. Dzieje się tak, ponieważ edytor IDLE zakładał, że będziesz pisać w programie Python. W programach Python edytor IDLE pokazuje słowa kluczowe Pythona w kolorze pomarańczowym, a wszystko w cudzysłowie na zielono. Ma to ułatwić czytanie kodu Pythona.
Uruchomienie pierwszego programu
Po zapisaniu programu przejdź do menu Run (nadal w edytorze IDLE) i wybierz Run Module (jak pokazano na następnym rysunku). Spowoduje to uruchomienie programu
Okno powłoki Pythona (to, które pojawiło się po uruchomieniu IDLE) staje się ponownie aktywne, a zobaczysz coś takiego:
Część RESTART informuje, że uruchomiłeś program. (Będzie to pomocne, gdy uruchamiasz programy w kółko, aby je przetestować). Następnie program działa. Dobra, więc nie robi zbyt wiele. Ale masz komputer, aby zrobić to, co mu kazałeś. Nasze programy staną się bardziej interesujące w miarę upływu czasu.
Jeśli coś pójdzie nie tak
Co się stanie, jeśli wystąpi błąd w programie i nie działa? Istnieją dwa różne rodzaje błędów, które mogą się zdarzyć. Spójrzmy na oba rodzaje, abyś wiedział, co zrobić, jeśli ci się przytrafi.
Błędy składniowe
IDLE sprawdza niektóre programy, zanim nawet spróbuje je uruchomić. Jeśli IDLE znajdzie błąd, zazwyczaj jest to błąd składniowy. Składnia to reguły pisowni i gramatyki języka programowania, więc błąd składniowy oznacza, że wpisałeś coś, co nie jest właściwym kodem Pythona.
Oto przykład:
print "Witaj i witaj w Pythonie!"
print "Mam nadzieję, że spodoba ci się nauka programowania".
print [brak cudzysłowu] Bye!"
Brakowało nam na razie cudzysłowu między wydrukiem a Bye! "Jeśli próbowałbyś uruchomić ten program, IDLE wyświetli komunikat "W twoim programie jest błąd: nieprawidłowa składnia". Wtedy musiałbyś spojrzeć na swój kod na zobacz, co się stało, edytor IDLE podświetli (na czerwono) miejsce, w którym znalazł błąd dokładnie tam, gdzie jest problem, ale powinien być blisko.
Błędy w czasie wykonywania
Drugi rodzaj błędu, który może się zdarzyć, to taki, którego Python (lub IDLE) nie może wykryć przed uruchomieniem programu. Ten rodzaj błędu występuje tylko wtedy, gdy program działa, dlatego nazywa się to błędem wykonania. Oto przykład błędu wykonania w programie:
print "Cześć, witaj w Pythonie!"
print "Mam nadzieję, że spodoba ci się nauka programowania".
print "Do widzenia na teraz!" + 5
Jeśli to zapiszesz i spróbujesz go uruchomić, program zacznie działać. Pierwsze dwie linie zostaną wydrukowane, ale pojawi się komunikat o błędzie:
>>> ============================ RESTART ============================
>>>
Cześć, witaj w Pythonie!
Mam nadzieję, że spodoba ci się nauka programowania
Traceback (most recent call last): <- początek komunikatu błędu
File "C:/HelloWorld/examples/error1.py", line 3, in
print "Bye for now!" + 5 <- zła linia kodu
TypeError: cannot concatenate 'str' and 'int' object <- co Python uważa za złe
>>>
Linia zaczynająca się od Traceback jest początkiem komunikatu o błędzie. Następny wiersz mówi, gdzie wystąpił błąd - podaje nazwę pliku i numer linii. Następnie wyświetla zły wiersz kodu. Pomaga to znaleźć miejsce, w którym problem występuje w kodzie. Ostatnia część komunikatu o błędzie mówi ci, co Python uważa za złe. Gdy dowiesz się więcej o programowaniu i Pythonie, łatwiej będzie zrozumieć, co oznacza wiadomość. W Pythonie nie można dodawać różnych rodzajów rzeczy, takich jak liczba i tekst. Dlatego print "Cześć na razie!" + 5 dał nam błąd. To tak, jakby powiedzieć: "Jeśli wezmę 5 jabłek i dodam 3 aligatory, ile mam?" Masz 8, ale 8 czego? Dodanie ich razem nie ma sensu. Ale możesz pomnożyć prawie wszystko przez liczbę, aby uzyskać więcej tego rodzaju rzeczy. (Jeśli masz 2 aligatory i pomnożysz przez 5, masz 10 aligatorów!) Dlatego wydrukuj "Cześć na razie!" * 5 działa.
Myśląc jak programista
Nie martw się, jeśli pojawią się komunikaty o błędach. Mają one pomóc Ci zrozumieć, co poszło nie tak, abyś mógł to naprawić. Jeśli coś jest nie tak z twoim programem, chcesz zobaczyć komunikat o błędzie. Rodzaje błędów, które nie dają Ci komunikatu o błędzie, są znacznie trudniejsze do znalezienia!
Nasz drugi program
Pierwszy program niewiele zrobił. Właśnie wyświetlił jakieś rzeczy na ekranie. Spróbujmy czegoś bardziej interesującego. Kod z listingu 1.2 dotyczy prostej gry z odgadywaniem numerów. Uruchom nowy plik w IDLE używający Plik > Nowe okno, tak jak za pierwszym razem. Wpisz kod z listingu 1.2, a następnie zapisz go. Możesz nazwać to, jak chcesz, o ile kończy się na .py. NumGuess.py może być dobrą nazwą. Jest tylko 18 linii instrukcji Pythona i kilka pustych linii, aby ułatwić czytanie. Pisanie nie powinno zająć zbyt wiele czasu. Nie martw się, że nie rozmawialiśmy jeszcze o tym, co ten kod oznacza jeszcze. Dotrzemy do tego bardzo szybko.
Listing 1.2 Gra polegająca na odgadywaniu numerów
import random
secret = random.randint(1, 99) // Wybiera tajną liczbę
guess = 0
tries = 0
print "AHOY! Jestem Dread Pirate Roberts, i mam sekret!"
r
print "Jest to liczba od 1 do 99. Dam ci 6 prób. "
while guess != secret and tries < 6:
guess = input("Czy masz na myśli? ") // Odgadywanie gracza [do sześciu razy]
if guess < secret:
print "Za mała, ty szkarłatna papugo!"
elif guess > secret:
print "Za duża, szczurze lądowy!"
tries = tries + 1 : Wykorzystuje jedną próbę
if guess == secret:
print "Avast! Masz to! Znalazłeś mój sekret, tak!"
else: <- Wyświetlanie wiadomości na końcu gry
print "Nigdy więcej domysłów! Lepiej następnym razem, kolego!"
print "Tajna liczba to", secret
Kiedy wpisujesz kod, zwróć uwagę na wcięcia linii po instrukcji while i dodatkowe wcięcia linii po if i elif. Zwróć także uwagę na dwukropki na końcach niektórych linii. Jeśli wpiszesz dwukropek we właściwym miejscu, edytor pomoże ci, wcinając następny wiersz. Po zapisaniu kodu uruchom go za pomocą polecenia Uruchom > Uruchom moduł, tak jak w przypadku pierwszego programu. Spróbuj zagrać w grę i zobacz, co się stanie. Oto przykład, kiedy go ją uruchomiłem:
>>> ======================= RESTART =================
>>>
AHOY! Jestem Dread Pirate Roberts i mam sekret!
Jest to liczba od 1 do 99. Dam ci 6 prób.
Czy masz na myśli? 40
Za duża , szczurze lądowy!
Czy masz na myśli ? 20
Za duża , szczurze lądowy!
Co masz na myśli? 10
Za mała, ty szkarłatna papugo
Co masz na myśli? 11
Za mała, ty szkarłatna papugo
Co masz na myśli? 12
Avast! Masz to! Znalazłeś mój sekret, tak!
>>>
Zdobycie tajnej liczby zajęło mi pięć odgadnięć, okazało się być 12. Dowiesz się wszystkiego o while, if, else ,elif i instrukcjach wprowadzania później. Ale prawdopodobnie już wiesz, jak działa ten program:
1 Tajna liczba jest losowo wybierana przez program.
2 Użytkownicy odgadują.
3 Program sprawdza każde zgadywanie tajnej liczby : czy jest on wyższy czy niższy?
4 Użytkownik próbuje, dopóki nie odgadnie liczby lub nie skończy się tu
Gdy odgadnienie pasuje do tajnej liczby, gracz wygrywa.
Czego się nauczyłeś?
• Zainstalowałeś Python
• Nauczyłeś się, jak rozpocząć pracę z IDLE
• Dowiedziałeś się więcej o trybie interaktywnym
• Dałeś Pythonowi pewne instrukcje i je wykonałeś
• Widziałeś, że Python wie, jak wykonywać arytmetykę (w tym naprawdę duże liczby!)
• Uruchomiono edytor tekstu IDLE, aby wpisać pierwszy program
• Uruchomiłem swój pierwszy program w Pythonie
• Dowiedziałeś się o komunikatach o błędach
• Uruchomiłeś swój drugi program Python: grę polegającą na odgadywaniu liczb
Sprawdź swoją wiedzę
1 Jak uruchomić IDLE?
2 Co robi print?
3 Jaki jest symbol mnożenia w Pythonie?
4 Co wyświetla IDLE po uruchomieniu programu?
5 Jakie jest inne słowo do uruchomienia programu?
Wypróbuj to
1 W trybie interaktywnym użyj Pythona do obliczenia liczby minut w tygodniu.
2 Napisz krótki program, aby wydrukować trzy linie: swoje imię i nazwisko, datę urodzenia i ulubiony kolor. Wynik powinien wyglądać mniej więcej tak:
Nazywam się
..
Urodziłem się
Mój ulubiony kolor to
...
Zapisz program i uruchom go. Jeśli program nie robi tego, czego oczekujesz lub otrzymujesz komunikaty o błędach, spróbuj to naprawić i sprawić, by działał.
Co to jest program? Hej, poczekaj chwilę, myślałem, że odpowiedzieliśmy na to w części 1! Powiedzieliśmy, że program to seria instrukcji dla komputera. To prawda. Ale prawie wszystkie programy, które robią coś użytecznego lub zabawnego, mają inne cechy:
• Otrzymują dane wejściowe.
• Przetwarzają dane wejściowe.
• Wytwarzają dane wyjściowe.
Wejście, przetwarzanie, wyjście
Twój pierwszy program (listing 1.1) nie miał żadnych danych wejściowych ani przetwarzania. To jeden z powodów, dla których nie było to zbyt interesujące. Wyjściem były komunikaty, które program wyświetlił na ekranie. Twój drugi program, gra z odgadywaniem numerów (listing 1.2), miał wszystkie trzy podstawowe elementy:
•   Wprowadzono dane, które gracz wpisał.
•   Przetwarzanie było programem sprawdzającym domysły i zliczanie kolejek
•   Wyjściem były komunikaty wydrukowane przez program.
Oto kolejny przykład programu, który ma wszystkie trzy elementy: w grze wideo wejście to sygnały z joysticka lub kontrolera gier; przetwarzanie to program zastanawiający się, czy zastrzeliłeś kosmitę, uniknąłeś kuli ognia, ukończyłeś poziom, czy cokolwiek innego; a wyjście to grafika na ekranie i dźwięk z głośników lub słuchawek. Ok, więc komputer potrzebuje danych wejściowych. Ale co robi z tym wejściem? Aby zrobić coś z wejściem, komputer musi go zapamiętać lub zachować gdzieś. Komputer przechowuje rzeczy, w tym dane wejściowe (i sam program), w pamięci.
Prawdopodobnie słyszałeś o pamięci komputera, ale co to tak naprawdę znaczy? Powiedzieliśmy, że komputery były tylko włącznikiem i wyłącznikiem. Cóż, pamięć jest jak grupa przełączników, które pozostają w tej samej pozycji przez chwilę. Po ustawieniu przełączników w określony sposób pozostają tak, dopóki ich nie zmienisz. Pamiętają, gdzie je ustawiłeś…
Voila: pamięć! Możesz zapisać do pamięci (ustawić przełączniki) lub odczytać z pamięci (sprawdź, jak przełączniki są ustawione, bez ich zmiany). Ale jak powiedzieć Pythonowi, gdzie w pamięci umieścić coś? A kiedy już tam jest, jak możemy to znaleźć? W Pythonie, jeśli chcesz, aby Twój program zapamiętał coś, abyś mógł z niego korzystać później, musisz tylko nadać mu nazwę. Python będzie miejscem dla rzeczy w pamięci komputera, niezależnie od tego, czy jest to liczba, jakiś tekst, obraz czy utwór muzyczny. Kiedy chcesz odwołać się do tej rzeczy, po prostu używasz tej samej nazwy. Użyjmy Pythona w trybie interaktywnym i dowiedzmy się więcej o nazwach.
Nazwy
Wróć do okna Python Shell. (Jeśli zamknąłeś IDLE od wykonania przykładu w Części 1, otwórz go ponownie.) W wierszu polecenia wpisz
>>> Nauczyciel = "Pan Kowalski"
>>> print Nauczyciel
(Pamiętaj, że >>> jest monitem wyświetlanym przez Pythona. Po prostu wpisz to, co jest po nim i naciśnij Enter.) Powinieneś to zobaczyć:
Pan Kowalski
>>>
Właśnie stworzyłeś coś, co składa się z liter "Pan Kowalski" i nadałeś mu nazwę Nauczyciel. Znak równości (=) mówi Pythonowi, aby przypisał lub "uczynił równym". Nazwę Nauczyciela przypisałeś do serii liter "Pan Kowalski". Gdzieś w części pamięci twojego komputera istnieją litery "Pan Kowalskin". Nie musisz dokładnie wiedzieć, gdzie. Powiedziałeś Pythonowi, że nazwa tej serii liter to Nauczyciel, i tak będziesz odnosił się do niej od teraz. Nazwa jest jak etykieta lub karteczka, którą dołączasz do czegoś, aby określić, czym ona jest.
Kiedy umieszczasz cudzysłowy wokół czegoś, Python bierze to dosłownie. Drukuje dokładnie to, co znajduje się w cudzysłowie. Gdy nie umieszczasz cudzysłowów na temat, Python musi dowiedzieć się, o co chodzi. Może to być liczba (np. 5), wyrażenie (jak 5 + 3) lub nazwa (jak Nauczyciel). Ponieważ zrobiłeś nazwę, Nauczyciel, Python wypisuje to, co należy do tej nazwy, co jest serią liter "Pan Kowalski". To tak, jakby ktoś powiedział: "Zapisz swój adres". Jeśli napisałeś "Twój adres", dosłownie przyjmowałbyś to stwierdzenie. Python nie traktuje rzeczy dosłownie, chyba że użyjesz cudzysłowów. Oto kolejny przykład:
>>> print "53 + 28"
53 + 28
>>>print 53 + 28
81
Dzięki cudzysłowom Python wyświetlił dokładnie to, co wpisałeś: 53 + 28. Bez znaków cudzysłowu Python traktował 53 + 28 jako wyrażenie arytmetyczne i oszacował to wyrażenie. W tym przypadku było to wyrażenie do dodania dwóch liczb razem, więc Python dał ci sumę.
Wyrażenie arytmetyczne to kombinacja liczb i symboli, które Python może określić jako wartość. Oszacuj tylko oznacza "oblicz wartość".
Python dba o to, ile pamięci potrzebuje do przechowywania liter i jakiej części pamięci będzie używać. Aby odzyskać swoje informacje (odzyskaj je), musisz ponownie użyć tej samej nazwy. Użyłeś nazwy wraz ze słowem kluczowym print, które wyświetla rzeczy (takie jak liczby lub tekst) na ekranie.
Myśląc jak programista
Po przypisaniu wartości do nazwy (np. przypisaniu wartości "Pan Kowalski" do Nauczyciel) jest ona przechowywana w pamięci i nazywana zmienną. W większości języków programowania mówimy, że przechowujesz wartość w zmiennej. Ale Python robi trochę inaczej niż większość innych języków komputerowych. Zamiast przechowywać wartości w zmiennych, bardziej przypomina umieszczanie nazw na wartościach. Niektórzy programiści Pythona twierdzą, że Python nie ma "zmiennych" - zamiast tego ma "nazwy". Ale zachowują się prawie tak samo. To jest tekst o programowaniu (tak się składa, że używa Pythona), a nie tylko o Pythonie. Więc użyjemy terminów zmienna, nazwa lub nazwa zmiennej, gdy mówimy o nazwie Pythona. To naprawdę nie ma znaczenia, jak je nazwiesz, o ile rozumiesz, jak zachowują się zmienne i jak ich używać w swoich programach. Przy okazji, Guido van Rossum, osoba, która stworzyła Pythona, mówi w swoim samouczku Pythona: "Znak" = "jest używany aby przypisać wartość zmiennej. "Myślę więc, że myśli, że Python ma zmienne!
Czysty sposób przechowywania rzeczy
Używanie nazw w Pythonie jest jak chodzenie do pralni chemicznej. Twoje ubrania są umieszczane na wieszaku, twoje nazwisko jest przymocowane, a one są umieszczane na dużym obrotowym wieszaku-wózku. Kiedy wrócisz, aby odebrać ubrania, nie musisz dokładnie wiedzieć, gdzie są one przechowywane na dużym wieszaku-wózku. Po prostu podajesz osobie swoje imię i zwracają ci ubrania. W rzeczywistości twoje ubrania mogą znajdować się w innym miejscu niż w momencie, gdy je wprowadziłeś. Ale pralnia na sucho to śledzi. Wszystko, czego potrzebujesz, to twoje nazwisko , aby odzyskać swoje ubrania. Zmienne są takie same. Nie musisz dokładnie wiedzieć, gdzie w pamięci przechowywane są informacje. Musisz po prostu użyć tej samej nazwy, jak podczas przypisywania. Możesz tworzyć zmienne dla innych rzeczy oprócz liter. Możesz nazwać wartości numeryczne. Pamiętasz nasz przykład z wcześniejszego?
>>> 5 + 3
8
Spróbujmy tego ze zmiennymi:
>>> Pierwszy = 5
>>> Drugi = 3
>>> print Pierwszy + Drugi
8
Tutaj stworzyliśmy dwie nazwy, Pierwszy i Drugi. Liczba 5 została przypisana do Pierwszy, a liczba 3 do Drugi. Następnie wydrukowaliśmy sumę dwóch. Jest inny sposób, aby to zrobić. Spróbuj tego:
>>> Trzeci = Pierwszy + Drugi
>>> Trzeci
8
Zauważ, co tu zrobiliśmy. W trybie interaktywnym możemy wyświetlić wartość zmiennej po prostu wpisując jej nazwę, bez używania wyświetlania. (To nie działa w programie). W tym przykładzie zamiast zrobić sumę w instrukcji print, wzięliśmy rzecz o nazwie Pierwszy i rzecz o nazwie Drugi i dodaliśmy je razem, tworząc nową rzecz o nazwie Trzeci. Trzeci jest sumą Pierwszy i Drugi.
Możesz mieć więcej niż jedną nazwę dla tego samego. Wypróbuj to w trybie interaktywnym:
>>> MyTeacher = "Pani Kowalska"
>>> YourTeacher = MyTeacher
>>> MyTeacher
"Pani Kowalska"
>>> YourTeacher
"Pani Kowalska"
To jest jak przyklejanie dwóch tagów do tego samego. Jeden tag mówi YourTeacher a drugi tag mówi MyTeacher, ale oba utknęły na "Pani Kowalska".
Co jest w nazwie?
Możesz nazwać zmienną jakkolwiek chcesz (cóż, prawie). Nazwa może być tak długa, jak chcesz, i może zawierać litery i cyfry, a także znak podkreślenia (_). Ale istnieje kilka zasad dotyczących nazw zmiennych. Najważniejsze jest to, że uwzględniają wielkość liter, co oznacza, że wielkie i małe litery mają znaczenie. Tak więc nauczyciel i NAUCZYCIEL to dwie różne nazwy. Więc są pierwszy i Pierwszy.
Inna reguła jest taka, że nazwa zmiennej musi zaczynać się od litery lub znaku podkreślenia. Nie może zaczynać się od liczby. Więc 4fun nie jest dozwolone. Jeszcze jedna reguła: nazwa zmiennej nie może zawierać żadnych spacji.
W niektórych wczesnych językach programowania nazwy zmiennych mogły mieć długość tylko jednej litery. Niektóre komputery miały tylko wielkie litery, co oznaczało, że masz tylko 26 opcji dla nazw zmiennych: A - Z! Jeśli potrzebujesz więcej niż 26 zmiennych w programie, nie miałeś szczęścia!
Liczby i łańcuchy
Do tej pory zmieniliśmy zarówno litery, jak i liczby. Ale w przykładzie dodawania, jak Python wiedział, że mamy na myśli liczby 5 i 3, a nie znaki "5" i "3"? Cóż, tak jak w ostatnim zdaniu, cudzysłów robi różnicę. Znak lub seria znaków (litery, cyfry lub znaki interpunkcyjne) nazywana jest łańcuchem. Sposób mówienia Pythonowi, że tworzysz łańcuch, polega na umieszczaniu cudzysłowów wokół znaków. Python nie jest zbyt wybredny jeśli chodzi o używanie pojedynczych lub podwójnych cudzysłowów. Każda z nich zadziała:
>>> teacher = "Pan Kowalski" <- podwójny cudzysłów
>>> teacher = ' Pan Kowalski ' <- pojedynczy cudzysłów
Ale musisz użyć tego samego rodzaju cuzysłowów na początku i na końcu łańcucha. Jeśli wpiszesz liczbę bez cudzysłowu, Python wie, że masz na myśli wartość liczbową, a nie znak. Spróbuj tego, aby zobaczyć różnicę:
>>> pierwszy = 5
>>> drugi = 3
>>> pierwszy + drugi
8
>>> pierwszy = '5'
>>> drugi = '3'
>>> pierwszy + drugi
"53"
Bez cudzysłowu 5 i 3 były traktowane jako liczby, więc otrzymaliśmy sumę. Z cytatami "5" i "3" były traktowane jako ciągi, więc mamy dwa znaki "dodane" razem lub "53". Możesz również dodać ciągi liter razem, jak widziałeś w Części 1:
>>> print "kot" + "pies"
kotpies
Zauważ, że gdy dodasz dwa ciągi razem, nie ma między nimi spacji. Zacinają się razem.
Konkatenacja
Nie jest dobrze powiedzieć "dodane", gdy mówimy o łańcuchach (tak jak my po prostu). Kiedy umieszczasz znaki lub łańcuchy razem, aby utworzyć dłuższy ciąg, istnieje dla niego specjalna nazwa. Zamiast "dodawać" (co dotyczy tylko liczb), nazywa się to konkatenacją. Mówimy, że łączysz dwa ciągi.
Długie stringi
Jeśli chcesz mieć ciąg obejmujący więcej niż jedną linię, musisz użyć specjalnego rodzaju łańcucha zwanego ciągiem z trzema cudzysłowami. Oto jak to wygląda:
long_string = "" "Zaśpiewaj piosenkę sześciopensówki, kieszeń pełną żyta, cztery i dwadzieścia kosów upieczonych w cieście. Gdy ciasto się otworzyło, ptaki zaczęły śpiewać. Czyż nie było to smaczne danie postawione przed królem? "" "
Ten rodzaj łańcucha rozpoczyna się i kończy trzema znakami cudzysłowu. Znaki cudzysłowu mogą być podwójnymi lub pojedynczymi cudzysłowami, więc możesz to zrobić w ten sposób:
long_string = '' 'Zaśpiewaj piosenkę sześciopensówki, kieszeń pełną żyta, cztery i dwadzieścia kosów pieczonych w cieście. Kiedy ciasto zostało otwarte, ptaki zaczęły śpiewać. Czyż nie było to smaczne danie postawione przed królem? ' ''
Ciągi z trzema cudzysłowami mogą być bardzo przydatne, gdy masz kilka wierszy tekstu, które chcesz wyświetlić razem, a nie chcesz używać osobnego ciągu dla każdej linii.
Jakie są "zmienne"?
Zmienne nie są bez powodu nazywane "zmiennymi". To dlatego, że są …dobrze … zmienne! Oznacza to, że możesz zmieniać lub zmieniać przypisaną im wartość. W Pythonie robisz to, tworząc nową rzecz, która różni się od starej i umieszczając starą etykietę (nazwę) w nowej rzeczy. Spróbujmy czegoś innego. Pamiętasz zmienną Nauczyciel, którą stworzyłeś wcześniej? Jeśli nie zamknąłeś IDLE, nadal tam jest. Sprawdź i zobacz:
>>> Nauczyciel
"Pan Kowalski"
Tak, wciąż tam. Ale zamiast tego możemy go zmienić na coś innego:
>>> Nauczyciel = 'Mr. Kowal'
>>> Nauczyciel
'Pan. Kowal'
Stworzyliśmy nową rzecz: "Pan Kowal "i nazwaliśmy go Nauczyciel. Tag został przeniesiony ze starego do nowego. Ale co stało się ze starą rzeczą: "Panem Kowalskim"? Pamiętaj, że rzeczy mogą mieć więcej niż jedną nazwę (więcej niż jeden tag na nich tkwi). Jeśli "Pan Kowalski "nadal ma na sobie inny tag, a następnie pozostaje w pamięci komputera. Ale jeśli nie ma już żadnych tagów, Python oblicza, że nikt go już nie potrzebuje, więc zostanie usunięty z pamięci. W ten sposób pamięć nie zapełnia się rzeczami, których nikt nie używa. Python wykonuje to czyszczenie automatycznie i nie musisz się tym martwić. Ważną rzeczą, którą należy wiedzieć, jest to, że tak naprawdę nie zmieniliśmy "Pan Kowalski "w "Pan Kowal". Właśnie przenieśliśmy tag (ponownie przypisaliśmy nazwę) z jednej rzeczy na drugą. Niektórych rzeczy w Pythonie (takich jak liczby i łańcuchy) nie można zmienić. Możesz zmienić przypisanie ich nazw do czegoś innego (jak właśnie zrobiłeś), ale nie możesz zmienić oryginalnej nazwy. W Pythonie można zmienić inne rodzaje rzeczy. Dowiesz się więcej na ten temat w Części 12, kiedy będziemy mówić o listach.
Nowy ja
Możesz również utworzyć zmienną równą jej samej:
>>> Score = 7
>>> Score = Score
Założę się, że myślisz: "Cóż, to całkiem bezużyteczne!" I masz rację. To trochę jak powiedzenie "Jestem mną". Ale z małą zmianą możesz stać się zupełnie nowym! Spróbuj tego:
>>> Score = Score + 1 <- zmień Score z 7 na 8
>>> print Score
8
Co tu się stało? W pierwszym wierszu znacznik Score utknął na wartości 7. Zrobiliśmy nową rzecz, którą było Score + 1, lub 7 + 1. Ta nowa rzecz to 8. Potem zdjęliśmy tag Score ze starej rzeczy (7 ) i przykleiłem go do nowej rzeczy (8). Tak więc wynik został ponownie przypisany z 7 na 8. Za każdym razem, gdy zmienna jest równa czemuś, zmienna zawsze pojawia się po lewej stronie znaku równości (=). Sztuczka polega na tym, że zmienna może również pojawić się po prawej stronie. Okazuje się to całkiem przydatne, a zobaczysz je w wielu programach. Najczęstszym zastosowaniem jest to aby zwiększyć zmienną (zwiększyć ją o pewną ilość), tak jak właśnie to zrobiliśmy, lub odwrotnie, aby zmniejszyć zmienną (zmniejsz ją o pewną kwotę):
1 Start ze Score = 7.
2 Zrób nową rzecz, dodając do niej 1 (co daje 8).
3 Nadaj nazwę Score nowej rzeczy.
Tak więc wynik zmienił się z 7 na 8.
Oto kilka ważnych rzeczy do zapamiętania na temat zmiennych:
• Zmienna może być ponownie przypisana (znacznik może zostać zablokowany na nowej rzeczy) w dowolnym momencie przez program. Jest to bardzo ważne do zapamiętania, ponieważ jednym z najczęstszych "błędów" w programowaniu jest zmiana niewłaściwej zmiennej lub zmiana odpowiedniej zmiennej w niewłaściwym czasie. Jednym ze sposobów zapobiegania temu jest używanie nazw zmiennych, które są łatwe do zapamiętania. Moglibyśmy użyć jednego z tych:
t = "Pan Kowalski"
lub
x1796vc47blahblah = 'Pan Kowalski'
Ale to utrudniłoby im zapamiętanie w programie. Bardziej prawdopodobne jest, że popełnimy błąd, jeśli użyjemy tych nazw. Spróbuj użyć nazw, które mówią ci, do czego służy zmienna.
• W nazwach zmiennych rozróżniana jest wielkość liter. Oznacza to duże i małe litery. Tak więc nauczyciel i Nauczyciel to dwie różne nazwy.
Myśląc jak programista
Czego się nauczyłeś?
W tej części dowiedziałeś się
• Jak "pamiętać" lub przechowywać rzeczy w pamięci komputera za pomocą zmiennych
• Zmienne te nazywane są również "nazwami" lub "nazwami zmiennych"
• Zmienne mogą być różnymi rodzajami rzeczy, takimi jak liczby i łańcuchy
Sprawdź swoją wiedzę
1 Jak powiedzieć Pythonowi, że zmienna jest łańcuchem (znakami) zamiast liczbą?
r
2 Czy po utworzeniu zmiennej możesz zmienić przypisaną jej wartość?
3 Z nazwami zmiennych, NAUCZYCIEL jest taki sam jak nAUCZYCIEL?
4 Czy "Blah" jest taki sam jak 'Blah' dla Pythona?
5 Czy "4" jest takie samo jak 4 ,dla Pythona?
a) Nauczyciel2
b) 2Nauczyciel
c) nauczyciel_25
d) TeaCher
7 Czy "10" jest liczbą czy ciągiem?
Wypróbuj to
1 Utwórz zmienną i przypisz jej numer (dowolną liczbę, którą lubisz). Następnie wyświetl zmienną za pomocą print.
2 Zmodyfikuj zmienną, zastępując starą wartość nową wartością lub dodając coś do starej wartości. Wyświetl nową wartość za pomocą print.
3 Utwórz inną zmienną i przypisz do niej ciąg (jakiś tekst). Następnie wyświetl go za pomocą print.
4 Podobnie jak w poprzedniej części, w trybie interaktywnym poproś Pythona, aby obliczył liczbę minut w tygodniu. Ale tym razem użyj zmiennych. Utwórz zmienne dla DaysPerWeek, HoursPerDay i MinutesPerHour (lub utwórz własne nazwy), a następnie pomnóż je razem.
5 Ludzie zawsze mówią, że nie ma wystarczająco dużo czasu, aby wszystko zrobić. Ile minut zajmie tydzień, jeśli w ciągu dnia będzie 26 godzin? (Wskazówka: zmień zmienną HoursPerDay.)
Kiedy po raz pierwszy próbowaliśmy użyć Pythona w trybie interaktywnym, zauważyliśmy, że może on wykonywać prostą arytmetykę. Teraz zobaczymy, co jeszcze Python może zrobić z liczbami i matematyką. Być może nie zdajesz sobie z tego sprawy, ale matematyka jest wszędzie! Szczególnie w programowaniu matematyka jest używana cały czas. To nie znaczy, że musisz być mistrzem matematyki, aby nauczyć się programowania, ale pomyśl o tym. Każda gra ma jakiś wynik, który należy dodać. Grafika jest rysowana na ekranie za pomocą liczb, aby określić pozycje i kolory. Ruchome obiekty mają kierunek i prędkość, które są opisane liczbami. Prawie każdy interesujący program użyje liczb i matematyki w jakiś sposób. Więc nauczmy się podstaw matematyki i liczb w Pythonie. Przy okazji, wiele z tego, czego się tutaj nauczymy, dotyczy innych języków programowania i innych programów, takich jak arkusze kalkulacyjne. Nie tylko Python robi matematykę w ten sposób.
Cztery podstawowe operacje
Już widzieliśmy, jak Python odrobił matematykę w rozdziale 1: dodawanie, używając znaku plus (+) i mnożenie, używając znaku gwiazdki (*). Python używa myślnika (-) (nazywanego również znakiem minus) do odejmowania, jak można by oczekiwać:
>>> print 8 - 5
3
Ponieważ klawiatury komputerowe nie mają symbolu dzielenia (÷), wszystkie programy używają ukośnika (/) do dzielenia:
>>> print 6/2
3
To się udało. Czasami jednak Python robi coś, czego nie można się spodziewać po dzieleniu
>>> print 3/2
1
Co? Myślałem, że komputery są dobre w matematyce! Wszyscy to wiedzą
3/2 = 1,5
Co się stało?
Cóż, chociaż wydaje się, że zachowuje się głupio, Python naprawdę stara się być mądry. Aby to wyjaśnić, musisz wiedzieć co nieco o liczbach całkowitych i dziesiętnych. Jeśli nie znasz różnicy, sprawdź pole tekstowe, aby uzyskać szybkie wyjaśnienie. Liczby całkowite to liczby, które można łatwo policzyć, np. 1, 2, 3, a także 0 i liczby ujemne, takie jak -1, -2, -3. Liczby dziesiętne (zwane również liczbami rzeczywistymi) to liczby z kropką/przecinkiem dziesiętną i kilkoma cyframi po niej, np. 1,25, 0.3752 i -101.2. W programowaniu komputerowym liczby dziesiętne są również nazywane liczbami zmiennoprzecinkowymi lub czasami float w skrócie. Dzieje się tak, ponieważ kropka dziesiętna "pływa" wokół. Możesz mieć liczbę 0.00123456 lub 12345.6 jako liczbę float. Ponieważ wpisaliśmy zarówno 3, jak i 2 jako liczby całkowite, Python uważa, że chcemy także odpowiedzi całkowitej. Zaokrąglił więc odpowiedź 1,5 do najbliższej liczby całkowitej, która wynosi 1. Innymi słowy, Python robi podział bez reszty. Aby to naprawić, spróbuj tego:
>>> print 3.0 / 2
1.5
Lepiej! Jeśli wprowadzisz jedną z dwóch liczb jako liczbę dziesiętną, Python wie, że chcesz, aby odpowiedź była liczbą dziesiętną.
Dzielenie bez reszty>
Sposób podziału Pythona 2 nazywa się "dzieleniem bez reszty". Ale Python 3 działa inaczej. W Pythonie 3, jeśli używasz operatora dzielenia całkowitego (ukośnik), otrzymasz dzielenie całkowite, a nie dzielenie bez reszty
>>> print 3/2
1.5
Aby uzyskać dzielenie bez reszty w Pythonie 3, możesz użyć podwójnego ukośnika:
>>> print 3//2
1
Jest to jedna z najbardziej zauważalnych różnic między Pythonem 2 i Pythonem 3
Operatory
Symbole +, -, * i / nazywane są operatorami. To dlatego, że "działają" lub pracują z liczbami, które wokół nich umieszczasz. Znak = jest również operatorem i nazywany jest operatorem przypisania, ponieważ używa się go do przypisywania wartości do zmiennej.
Operator to coś, co ma wpływ na rzeczy wokół niego lub "działa". Skutkiem może być przypisanie wartości, przetestowanie lub zmiana jednej lub więcej z tych rzeczy.
myNumber + yourNumber
operand Operator operand
Symbole +, -, * i /, których używamy do wykonywania arytmetyki, to operatory. Rzeczy na których działają operatory nazywane są operandami.
Kolejność operacji
Który z nich jest poprawny?
2 + 3 * 4 = 20
lub
2 + 3 * 4 = 14
To zależy od tego, w jakiej kolejności robimy rzeczy. Jeśli najpierw dodamy, otrzymamy
2 + 3 = 5, a więc 5 * 4 = 20
Jeśli najpierw wykonamy mnożenie, otrzymamy
3 * 4 = 12, a więc 2 + 12 = 14
Prawidłowa kolejność to druga, więc poprawna odpowiedź to 14. W matematyce jest coś, co nazywa się kolejnością operacji, która mówi ci, które operatory powinny być wykonane przed innymi, nawet jeśli są zapisywane po nich. W naszym przykładzie, mimo że znak + pojawia się przed znakiem *, mnożenie jest wykonywane jako pierwsze. Python przestrzega odpowiednich reguł matematycznych, więc robi mnożenie przed dodaniem. Możemy wypróbować to w trybie interaktywnym, aby upewnić się, że:
>>> print 2 + 3 * 4
14
Kolejność, w jakiej używa się Pythona, jest taka sama, jakiej nauczyłeś się (lub uczysz się) na matematyce. Najpierw pojawiają się wykładniki, potem mnożenie i dzielenie, a następnie dodawanie i odejmowanie. Jeśli chcesz zmienić kolejność operacji i zrobić coś, co będzie pierwsze, po prostu umieść nawiasy (okrągłe nawiasy) dookoła, tak:
>>> print (2 + 3) * 4
20
Tym razem Python najpierw wykonał 2 + 3 (ze względu na nawiasy), aby uzyskać 5, a następnie pomnożył 5 * 4 aby uzyskać 20
Ponownie jest to dokładnie to samo, co na matematyce. Python (i wszystkie inne języki programowania) przestrzegają odpowiednich reguł matematycznych i kolejności operacji.
Dwa więcej operatory
Chciałbym ci pokazać jeszcze dwa operatory matematyczne. Te dwa plus cztery podstawowe, które właśnie widziałeś, są potrzebne do 99 procent twoich programów. Potęgowanie - podniesienie do potęgi Jeśli chciałbyś pomnożyć 3 przez siebie 5 razy, możesz napisać:
>>> print 3 * 3 * 3 * 3 * 3
243
Ale to jest to samo, co 35 lub "trzy wykładniki pięć" lub "trzy do potęgi pięć". Python używa podwójnej gwiazdy (gwiazdki) dla wykładników lub podnosi liczbę do potęgi:
>>> print 3 ** 5
243
Wiele języków i programów używa innych symboli do podnoszenia mocy. Wspólnym jest ^ (na przykład 3 ^ 5). Jeśli używasz tego z Pythonem, nie otrzymasz komunikatu o błędzie; otrzymasz złą odpowiedź. (To dlatego, że ^ oznacza coś innego w Pythonie - to nie jest to, czego chcemy!) Może to być bardzo trudne do debugowania. Upewnij się, że używasz operatora ** do podniesienia do potęgi (zwanej również potęgowaniem).
Jednym z powodów użycia wykładnika zamiast wielokrotnego mnożenia jest to, że łatwiej jest pisać. Ale ważniejszym powodem jest to, że z ** możesz mieć wykładniki, które nie są liczbami całkowitymi, jak poniżej:
>>> print 3 ** 5.5
420.888346239
Nie ma prostego sposobu, aby to zrobić za pomocą mnożenia.
Moduł - uzyskiwanie reszty
Kiedy po raz pierwszy spróbowałeś dzielenia w Pythonie, zauważyłeś, że jeśli podzielisz dwie liczby całkowite, Python 2 da ci odpowiedź jako liczbę całkowitą. (A Python 3 robi to samo z // operatorem.) Robi to dzielenie na liczby całkowite. Ale w dzieleniu na liczby całkowite odpowiedź ma dwie części. Czy pamiętasz, kiedy dowiedziałeś się o dzieleniu? Jeśli liczby nie dzieliły się całkowicie, otrzymałeś resztę:
7/2 = 3, z resztą 1
Odpowiedź na 7/2 ma iloraz (3, w tym przypadku) i resztę (1, w tym przypadku). Jeśli podzielisz dwie liczby całkowite w Pythonie, otrzymasz iloraz. Ale co z resztą? Python ma specjalny operatora do obliczania pozostałej części dla podziału całkowitoliczbowego. Nazywa się operatorem modułu, a symbolem jest symbol procentu (%). Używasz go w ten sposób:
>>> print 7 % 2
1
Więc jeśli używasz / i % razem, możesz uzyskać pełną odpowiedź na problemy z podziałem liczb całkowitych:
>>> print 7 / 2
3
>>> print 7 % 2
1
Odpowiedź 7 podzielone przez 2 to 3, reszta 1. Jeśli wykonujesz podział zmiennoprzecinkowy, otrzymasz odpowiedź dziesiętną:
>>> print 7.0 / 2
3.5
Właściwie, skoro o tym wspomniałeś, są podobne … Operator arytmetyczny łączy liczby w sposób, w jaki staromodny operator telefoniczny używał ich do łączenia telefonów. Są jeszcze dwa operatory, o których chciałbym wam powiedzieć. Wiem, powiedziałem jeszcze tylko dwa, ale to naprawdę proste!
Zwiększanie i zmniejszenie
Pamiętasz przykład z ostatniego rozdziału: score = score + 1? Powiedzieliśmy, że nazywa się to zwiększaniem. Podobną rzeczą jest wynik = wynik - 1, który nazywa się zmniejszaniem. Operacje te są wykonywane tak często w programowaniu, że mają swoje własne operatory: += (przyrost) i -= (zmniejszenie).
Używasz ich w ten sposób:
>>> liczba = 7
>>> liczba += 1 <- Liczba zwiększona o 1
>>> print liczba
8
lub
>>> liczba = 7
>>> liczba -= 1 <- Liczba zmniejszona o 1
>>> print liczba
6
Pierwszy przykład dodaje jeden do liczba. (Zmienia się z 7 na 8.) Drugi odejmuje jeden od liczba. (Zmienia się z 7 na 6.) Naprawdę duży i naprawdę mały Pamiętasz, z Części 1, kiedy pomnożyliśmy te dwie naprawdę duże liczby razem? Mamy bardzo dużą liczbę do odpowiedzi. Czasami Python pokazuje ci duże liczby nieco inaczej. Wypróbuj to w trybie interaktywnym:
>>> print 9938712345656.34 * 4823459023067.456
4.79389717413e+025
(Nie ma znaczenia, jakie liczby wpiszesz - zrobi to każda duża liczba z miejscami dziesiętnymi).
e jest jednym ze sposobów wyświetlania naprawdę dużych lub bardzo małych liczb na komputerze. To się nazywa e-notacja. Kiedy pracujesz z naprawdę dużymi (lub naprawdę małymi) liczbami, pokazanie wszystkich cyfr i miejsc dziesiętnych może być trochę bolesne. Te rodzaje liczb pojawiają się bardzo często w matematyce i nauce. Na przykład, jeśli program astronomiczny wyświetlał liczbę kilometrów od Ziemi do gwiazdy Alfa Centauri, mógłby wykazywać 38000000000000000 lub 38 000 000 000 000 000 lub 38 000 000 000 000 000. (To 38 biliardów kilometrów!) Ale tak czy inaczej, byłbyś zmęczony od liczenia wszystkich tych zer. Innym sposobem wyświetlenia tej liczby jest użycie notacji naukowej, która używa potęgi 10 wraz z liczbami dziesiętnymi. W notacji naukowej odległość do Alfa Centauri byłaby zapisana w następujący sposób: 3,8 x 1016 (Zobacz, jak 16 jest uniesione ponad linię i jest mniejsza?) Odnosi się to do "trzy przecinek osiem razy dziesięć do potęgi szesnastej" lub "trzy przecinek osiem razy dziesięć do szesnastu". Oznacza to, że bierzesz 3,8 i przesuwasz punt dziesiętny 16 miejsc w prawo, dodając zera w razie potrzeby
3.800000000000000000000
Przenieś punkt dziesiętny w prawo 16 miejsc.
380000000000000000.0 = 3,8 x 1016
Notacja naukowa jest świetna, jeśli możesz napisać 16 jako wykładnik, podniesiony powyżej linii i mniejszy, tak jak tutaj. Jeśli pracujesz z ołówkiem i papierem lub programem obsługującym indeksy górne, możesz użyć notacji naukowej.
Indeks górny oznacza znak lub znaki, które są uniesione ponad resztę tekstu, jak poniżej: 1013. 13 jest tutaj indeksem górnym. Indeksy górne są zwykle mniejsze niż tekst główny. Indeksy dolne są podobne, ale są to znaki poniżej reszty tekstu i mniejsze, takie jak: log2. Tutaj 2 jest indeksem dolnym.
Ale nie zawsze można używać indeksów górnych, więc innym sposobem pokazania tego samego jest e-notacja. E-notacja to kolejny sposób zapisu notacji naukowej.
E-notacja
W notacji E nasza liczba wynosiłby 3.8E16 lub 3.8e16. Zakłada się, że wykładnik ma podstawę 10. To jest to samo, co zapis 3,8 x 1016.
Większość programów i języków komputerowych, w tym Python, pozwala używać wielkich lub małych liter E.
W przypadku bardzo małych liczb, np. 0,0000000000001752, używany jest wykładnik ujemny. Notacja naukowa wynosiłaby 1,752 x 10--13, a notacja E wynosiłaby 1.752e-13. Ujemny wykładnik oznacza przesunięcie miejsca dziesiętnego w lewo zamiast w prawo.
00000000000000001.752
Przesuń punkt dziesiętny w lewo o 13 miejsc.
0,00000000000011752 = 1,752e-13
Możesz użyć notacji E, aby wprowadzić bardzo duże i bardzo małe liczby (lub dowolną ich liczbę) do Pythona. Później zobaczysz, jak sprawić, by Python wyświetlił liczby za pomocą notacji elektronicznej. Spróbuj wpisać kilka liczb w e-notacji:
>>> a = 2.5e6
>>> b = 1.2e7
>>> print a + b
14500000.0
Chociaż wprowadziliśmy liczby w notacji E, odpowiedź pojawiła się jako regularna liczba dziesiętna. Dzieje się tak, ponieważ Python nie wyświetla liczb w notacji E, chyba że wyraźnie to powiesz, lub liczby są naprawdę duże lub naprawdę małe (wiele zer). Spróbuj tego:
>>> c = 2.6e75
>>> d = 1.2e74
>>> print c + d
2.72e+75
Tym razem Python automatycznie wyświetlał odpowiedź w notacji E, ponieważ wyświetlanie liczby z 73 zerami nie miałoby sensu!
Jeśli chcesz, aby liczby takie jak 14 500 000 były wyświetlane w notacji elektronicznej, musisz podać specjalne instrukcje Pythona. Dowiesz się więcej o tym później
Jeśli nie rozumiesz, jak działa e-notacja, nie martw się. Nie jest używana w programach w pozostałej części kursu. Chciałem ci tylko pokazać, jak to działa, jeśli kiedykolwiek tego potrzebujesz. Przynajmniej teraz, jeśli użyjesz Pythona do zrobienia matematyki i otrzymasz liczbę jak 5.673745e16 , będziesz wiedział, że jest to naprawdę duża liczba, a nie jakiś błąd.
Wykładniki vs. e-notacja
Nie należy mylić między podniesieniem liczby do potęgi (zwanej również potęgowaniem) a E-notacją :
• 3 ** 5 oznacza 35 lub "trzy do piątej potęgi" lub 3 * 3 * 3 * 3 * 3, co jest równe 243.
• 3e5 oznacza 3 * 105 lub "trzy razy dziesięć do piątej potęgi" lub 3 * 10 * 10 * 10 * 10 * 10, co odpowiada 300 000.
• Podnoszenie do potęgi oznacza, że podnosisz liczbę do tej potęgi. E-notacja oznacza, że mnożymy przez potęgę 10.
Czego się nauczyłeś?
• Jak wykonywać podstawowe operacje matematyczne w Pythonie
• O liczbach całkowitych i zmiennoprzecinkowych
• O potęgowaniu (podnoszenie liczby do potęgi)
• Jak obliczyć moduł (reszta)
• Wszystko o e-notacji
Sprawdź swoją wiedzę
1 Jakiego symbolu używa Python do mnożenia?
2 Jaką odpowiedź dałby Python 2 dla 8/3?
3 Jaką otrzymasz resztę dla 8/3?
4 Jaką otrzymasz odpowiedź dziesiętną dla 8/3 w Pythonie 2?
5 Jaki jest inny sposób obliczania 6 * 6 * 6 * 6 w Pythonie?
6 Jak napisałbyś 17 000 000 w e-notacji?
7 Jak wyglądałby 4.56e-5 w notacji regularnej (nie E-notacji)?
Wypróbuj to
1 Rozwiąż następujące problemy za pomocą trybu interaktywnego lub pisząc mały program:
a) Trzy osoby zjadły obiad w restauracji i chcą podzielić rachunek. Suma wynosi 35,27 $ i chcą zostawić 15% napiwku. Ile powinna płacić każda osoba?
b) Oblicz powierzchnię i obwód prostokątnego pomieszczenia, 12,5 metra na 16,7 metra.
2 Napisz program do konwersji temperatur z Fahrenheita na Celsjusza. Wzór na to: C = 5/9 * (F - 32). (Podpowiedź: uważaj na pułapkę z podziałem całkowitym!)
3 Czy wiesz, jak obliczyć, ile czasu zajmie ci dotarcie gdziekowliek samochodem? Formuła (słownie) to "czas podróży równy odległości podzielonej przez prędkość". Zrób program, aby obliczyć czas potrzebny na przejechanie 200 km z prędkością 80 km na godzinę i wyświetlenie odpowiedzi.
Widzieliśmy, że istnieją co najmniej trzy różne typy rzeczy, które możemy przypisać do zmiennej (do przechowywania w pamięci komputera): liczby całkowite, liczby zmiennoprzecinkowe i łańcuchy. Istnieją inne typy danych w Pythonie, o których dowiesz się później, ale na razie te trzy będą działać. Tu dowiesz się, w jaki sposób możesz określić, czym jest coś. Zobaczysz również, jak zrobić jeden typ z innego.
Konwersja typów
Dość często musimy konwertować dane z jednego typu na inny. Na przykład, gdy chcemy wyświetlić numer, należy go przekonwertować na tekst, aby tekst pojawił się na ekranie. Polecenie print Pythona może to zrobić dla nas, ale czasami musimy przekonwertować bez wyświetlania lub przekonwertować ciągi znaków na liczby (czego print nie może zrobić). Nazywa się to konwersją typu. Jak to działa? Python nie "konwertuje" rzeczy z jednego typu na inny. Tworzy nową rzecz, takiej, jaką chcesz, z oryginalnej rzeczy. Oto niektóre funkcje, które konwertują dane z jednego typu na inny:
• float() utworzy nowy float (liczbę dziesiętną) z ciągu lub liczby całkowitej.
• int() utworzy nową liczbę całkowitą z łańcucha lub float.
• str() utworzy nowy łańcuch z liczby (lub dowolnego innego typu).
Nawiasy na końcu float(), int() i str() są tam, ponieważ nie są one słowami kluczowymi Pythona (jak print) - są to niektóre z wbudowanych funkcji Pythona. W dalszej części dowiesz się więcej o funkcjach. Na razie wystarczy wiedzieć, że w nawiasach umieszczasz wartość, którą chcesz przekonwertować. Najlepszym sposobem na pokazanie tego jest kilka przykładów. Postępuj zgodnie z trybem interaktywnym w powłoce IDLE.
Zmiana int na float
Zacznijmy od liczby całkowitej i utwórz z niej nową liczbę zmiennoprzecinkową (liczbę dziesiętną), używając float ():
>>> a = 24
>>> b = float (a)
>>> a
24
>>> b
24,0
Zauważ, że b otrzymuje kropkę dziesiętną i 0 na końcu. To mówi nam, że jest zmiennoprzecinkowa, a nie całkowita. Zmienna a pozostaje taka sama, ponieważ float() nie zmienia oryginalnej wartości - tworzy nową. Pamiętaj, że w trybie interaktywnym możesz po prostu wpisać nazwę zmiennej (bez używania drukowania), a Python wyświetli wartość zmiennej. To działa tylko w trybie interaktywnym, a nie w programie. Zmiana float na int Teraz spróbujmy na odwrót - zacznij od liczby dziesiętnej i utwórz liczbę całkowitą, używając int():
>>> c = 38,0
>>> d = int (c)
>>> c
38,0
>>> d
38
Stworzyliśmy nową liczbę całkowitą, d, która jest częścią całkowitą liczby c. Pamiętasz, jak mówiliśmy, że komputery używają plików binarnych? Cóż, wszystkie liczby, które Python przechowuje, przechowuje jako binarne. Dla sumy 0,1 i 0,2 Python tworzy zmiennoprzecinkowe (liczba dziesiętna) z wystarczającą liczbą cyfr binarnych (bitów), aby uzyskać 15 miejsc po przecinku. Ale ta liczba binarna nie jest dokładnie równa 0.3, jest bardzo, bardzo blisko. (W tym przypadku jest to błędne przez 0.000000000000004.) Różnica jest nazywana błędem zaokrąglania. Po wpisaniu wyrażenia 0.1 + 0.2 w trybie interaktywnym Python pokazał surową liczbę, którą zapisał, ze wszystkimi miejscami dziesiętnymi. Kiedy używałeś print, masz to, czego oczekiwałeś, ponieważ print jest trochę mądrzejszy i wie wystarczająco dużo, aby zaokrąglić i wyświetlić 0.3. To jak zapytać kogoś o czas. Może powiedzieć "dwunasta czterdzieści cztery i pięćdziesiąt trzy sekundy". Ale większość ludzi powiedziałaby "za kwadrans pierwsza", ponieważ wiedzą, że nie trzeba być tak precyzyjnym. Błędy zaokrąglania występują przy liczbach zmiennoprzecinkowych w dowolnym języku komputerowym. Liczba poprawnych cyfr, które otrzymasz, może się różnić w zależności od komputera lub języka, ale wszystkie używają tej samej podstawowej metody przechowywania pływaków. Zwykle błędy zaokrąglania są na tyle małe, że nie musisz się nimi martwić.
Spróbujmy innego:
>>> e = 54.99
>>> f = int(e)
>>> print e
54.99
>>> print f
54
Mimo że 54,99 jest bardzo blisko 55, wciąż otrzymujemy 54 jako liczbę całkowitą. Funkcja int() zawsze zaokrągla w dół. Nie podaje najbliższej liczby całkowitej, daje następną najniższą liczbę całkowitą. Funkcja int() zasadniczo odcina część dziesiętną. Jeśli chcesz uzyskać najbliższą liczbę całkowitą, istnieje sposób.
Zmiana string na float
Możesz także utworzyć numer z ciągu, tak jak poniżej:
>>> a = '76 .3 '
>>> b = float (a)
>>> a
'76 .3 '
>>> b
76.3
Zauważ, że kiedy wyświetlamy a, wynik ma wokół niego cudzysłów. To sposób, w jaki Python mówi nam, że a jest to łańcuch znaków. Kiedy wyświetlamy b, otrzymujemy wartość zmiennoprzecinkową.
Uzyskiwanie dodatkowych informacji: type()
W ostatniej sekcji polegaliśmy na widzeniu cudzysłowów, aby wiedzieć, że wartość jest liczbą lub ciągiem znaków. Jest bardziej bezpośredni sposób, aby się tego dowiedzieć. Python ma inną funkcję, type(), która wyraźnie podaje nam typ zmiennej. Spróbujmy:
>>> a = '44.2'
>>> b = 44.2
>>> type(a)
< type 'str' >
>>> type(b)
< type 'float' >
Funkcja type() mówi nam, że a jest typu "str", co oznacza ciąg, a b jest typu "float". Nigdy więcej zgadywania!
Błędy konwersji typu
Oczywiście, jeśli podamy int() lub float() coś, co nie jest liczbą, nie zadziała. Wypróbuj i zobacz:
>>> print float ('fred')
Śledzenie (ostatnie połączenie):
Plik "< pyshell # 1 >", wiersz 1, w < module >
print float ("fred")
ValueError: nie można przekonwertować łańcucha na float: fred
Mamy komunikat o błędzie. Komunikat o błędzie oznacza, że Python nie wie, jak utworzyć numer z "fred". Czy ty?
Używanie konwersji typu
Wracając do programu konwersji temperatury Fahrenheita na Celsjusza z sekcji "Wypróbuj" w części 3, pamiętaj, że aby uzyskać właściwą odpowiedź, musisz naprawić zachowanie dzielenia liczb całkowitych, zmieniając wartość 5 na 5,0 lub 9 na 9,0:
cel = 5,0 / 9 * (fahr - 32)
Funkcja float() daje ci inny sposób:
cel = float (5) / 9 * (fahr - 32)
lub
cel = 5 / float (9) * (fahr - 32)
Wypróbuj i zobacz.
Czego się nauczyłeś?
• Konwersji między typami (lub, bardziej poprawnie, tworzenie typów z innych typów): str(), int() i float()
• Wyświetlania wartości bezpośrednio bez print
• Sprawdzanie typu zmiennej za pomocą type()
• Zaokrąglania błędów i przyczyny ich wystąpienia
Sprawdź swoją wiedzę
1 Kiedy używasz int() do konwersji liczby dziesiętnej na liczbę całkowitą, czy wynik jest zaokrąglany w górę lub w dół?
2 Czy w twoim programie konwersji temperatury zadziałałoby?
cel = float (5/9 * (fahr - 32))
A co z tym:
cel = 5/9 * float (fahr - 32)
Jeśli nie, dlaczego nie?
3 (Dodatkowe wyzwanie) Bez użycia innych funkcji oprócz int(), w jaki sposób można uzyskać liczbę zaokrągloną w górę zamiast zaokrąglać w dół? (Na przykład 13,2 zaokrągli w dół do 13, ale 13,7 zaokrągli do 14).
Wypróbuj to
1 Użyj float(), aby utworzyć liczbę z łańcucha, np. "12,34". Upewnij się, że wynik jest naprawdę liczbą!
2 Spróbuj użyć int(), aby utworzyć liczbę całkowitą z liczby dziesiętnej, takiej jak 56,78. Czy odpowiedź została zaokrąglona w górę czy w dół?
3 Spróbuj użyć int (), aby utworzyć liczbę całkowitą z ciągu. Upewnij się, że wynik jest naprawdę liczbą całkowitą!
Dane wejściowe
Do tej pory, jeśli chciałeś, aby twój program "skracał niektóre liczby", musisz umieścić te liczby bezpośrednio w kodzie. Na przykład, jeśli napisałeś program konwersji temperatury w sekcji "Wypróbuj" w Części 3, prawdopodobnie ustawisz temperaturę do konwersji bezpośrednio w kodzie. Jeśli chciałbyś przekonwertować inną temperaturę, musiałbyś zmienić kod. Co zrobić, jeśli chcesz, aby użytkownik wprowadził dowolną temperaturę, jaką chce, gdy program działa? Powiedzieliśmy wcześniej, że program ma trzy komponenty: wejście, przetwarzanie i wyjście. Nasz pierwszy program miał tylko wyjście. Program konwersji temperatury miał pewne przetwarzanie (konwertowanie temperatury) i pewne wyjście, ale bez wprowadzania. Nadszedł czas, aby dodać trzeci składnik do naszych programów: wejście. Wejście oznacza uzyskanie czegoś, pewnego rodzaju informacji, w trakcie działania programu. W ten sposób możemy pisać programy, które współdziałają z użytkownikiem, co sprawi, że wszystko stanie się bardziej interesujące. Python ma wbudowaną funkcję o nazwie raw_input(), która jest używana do pobierania danych od użytkownika.
raw_input()
Funkcja raw_input() pobiera ciąg znaków od użytkownika. Normalny sposób, w jaki to robi, pochodzi z klawiatury - użytkownik wpisuje dane wejściowe. raw_input() to kolejna z wbudowanych funkcji Pythona, takich jak str(), int(), float() i type(). Później dowiesz się więcej o funkcjach. Ale na razie musisz tylko pamiętać o umieszczeniu nawiasów (nawiasy okrągłe), gdy używasz raw_input().
Surowe dane wejściowe
W Pythonie 3 funkcja raw_input () nazywa się input(). Działa dokładnie tak samo jak raw_input () w Pythonie 2.
Oto jak jej używać:
someName = raw_input()
Pozwoli to użytkownikowi wpisać ciąg znaków i przypisać mu nazwę someName. Teraz umieśćmy to w programie. Utwórz nowy plik w IDLE i wpisz kod na poniższej liście.
Listing 5.1 Pobieranie ciągu za pomocą raw_input
print "Wpisz swoje imię:"
somebody = raw_input()
print"Cześć", somebody, "jak się masz?
Zapisz i uruchom ten program w IDLE, aby zobaczyć, jak działa. Powinieneś zobaczyć coś takiego:
Wpisz swoje imię:
Albert
Cześć Albert, jak się masz?
Wpisałeś swoje imię, a program zrobił resztę.
Polecenie print i przecinek
Zwykle, gdy chcesz wprowadzić dane od użytkownika, musisz mu powiedzieć, czego szukasz, z krótką wiadomością w następujący sposób:
print "Wpisz swoje imię:"
Następnie możesz uzyskać jego odpowiedź za pomocą funkcji raw_input():
someName = raw_input ()
Kiedy uruchamiasz te linie kodu i wpisujesz swoje imię, wygląda to tak:
Wpisz swoje imię:
Albert
Jeśli chcesz, aby użytkownik wpisał swoją odpowiedź w tym samym wierszu, co wiadomość, po prostu umieść przecinek na końcu instrukcji print, jak poniżej:
print "Wpisz swoje imię:",
someName = raw_input ()
Zauważ, że przecinek wykracza poza cudzysłowy. Jeśli uruchomisz ten kod, będzie on wyglądał następująco:
Wpisz swoje imię: Albert
Przecinek może być użyty do połączenia wielu instrukcji print w jednym wierszu. Przecinek naprawdę oznacza "nie przeskakuj do następnego wiersza po wyświetleniu". Zrobiliśmy to w ostatnim wierszu listingu 5.1. Spróbuj wpisać następujący kod w oknie edytora IDLE i uruchom go.
Listing 5.2 Co robi przecinek
print "Moje",
print "imię",
print "to",
print "Albert".
Powinieneś to otrzymać po uruchomieniu:
Moje imię to Albert.
Czy zauważyłeś, że nie ma spacji na końcach poszczególnych słów w cudzysłowach, ale między każdym słowem mamy spację, kiedy uruchamialiśmy program? Python dodaje spację, gdy używasz przecinka do łączenia instrukcji drukowania w jednym wierszu.
Przecinek końcowy
W Pythonie3 sztuczka polegająca na umieszczeniu przecinka na końcu, aby kontynuować wyświetlanie w tej samej linii nie działa. Również w Pythonie 3, kiedy używasz print(), to, co wyświetlasz, musi być w nawiasach. Więc jeśli używasz Python 3, listing 5.2 wygląda tak:
print ("Moje", end = "")
print ("imię", end = "")
print ("to", end = "")
print ("Albert.", end = "")
Skrót do monitów raw_input()
Istnieje skrót do wyświetlania komunikatów. Funkcja raw_input () może wyświetlić wiadomość dla ciebie, więc nie musisz używać instrukcji print:
someName = raw_input ("Wpisz swoje imię:")
To tak, jak funkcja raw_input () ma wbudowaną funkcję drukowania. Od tej chwili użyjemy tego skrótu.
Wprowadzanie liczb
Widziałeś, jak użyć raw_input(), aby pobrać łańcuchy. Ale co, jeśli zamiast tego chcesz uzyskać liczbę? Ostatecznie powodem, dla którego zaczęliśmy rozmawiać o wprowadzeniu, było umożliwienie użytkownikowi wprowadzenia temperatur do programu konwersji temperatury. Znasz już odpowiedź, jeśli przeczytałeś Część 4. Możemy użyć funkcji int() lub float() do utworzenia liczby z ciągu, który daje raw_input(). Wyglądałoby to tak:
temp_string = raw_input()
fahrenheit = float(temp_string)
Otrzymujemy dane wejściowe użytkownika jako ciąg znaków, używając raw_input(). Następnie robimy z tego liczbę używając float(). Kiedy temperatura osiągnie wartość float, nadamy mu nazwę fahrenheit. Ale jest mały skrót. Możemy to zrobić w jednym kroku, tak:
fahrenheit = float(raw_input ())
To robi dokładnie to samo. Pobiera łańcuch od użytkownika, a następnie tworzy z niego liczbę. Po prostu robi to z nieco mniejszym kodem. Teraz użyjmy tego w naszym programie konwersji temperatury. Wypróbuj następujący program i zobacz, co otrzymujesz.
Listing 5.3
print "Ten program konwertuje Fahrenheita na Celsjusza"
print "Wpisz temperaturę w stopniach Fahrenheita:",
fahrenheit = float (raw_input ()) <- Użyj float (raw_input ()), aby uzyskać temperaturę Fahrenheita od użytkownika
C = (Fahrenheit - 32) * 5,0 / 9
print "Jest", ><- Zwróć uwagę na przecinki
print Celsjusza, <- na końcach tych linii
print "stopni Celsjusza"
Możemy również połączyć trzy ostatnie linie listingu 5.3 w jeden, tak jak poniżej:
print"Jest", Celsjusza, "stopni Celsjusza"
To jest naprawdę skrót dla trzech instrukcji drukowania, które mieliśmy wcześniej.
Używanie int() z raw_input()
Jeśli liczba, którą chcesz wprowadzić, zawsze będzie liczbą całkowitą (bez miejsc dziesiętnych), możesz przekonwertować ją za pomocą int(), tak jak poniżej:
response = raw_input("Ilu studentów jest w twojej klasie:")
numberOfStudents = int (response)
Myśl jak programista (Python)
Jest inny sposób na uzyskanie liczb jako danych wejściowych. Python 2 ma funkcję input(), która daje ci liczbę bezpośrednio, więc nie musisz używać int() lub float(), aby go przekonwertować. Użyliśmy go w programie zgadywania liczb w części 1, ponieważ jest to najprostszy sposób na uzyskanie liczby od użytkownika. Ponadto funkcja input() (ta, która pobiera liczby bezpośrednio bez konieczności ich konwersji) została usunięta w Pythonie 3. Jest tylko raw_input(). Aby uczynić rzeczy trochę bardziej mylącymi, funkcja Python 2 raw_input() jest nazywana input() w Pythonie 3, ale jest to ta sama funkcja, którą widziałeś już, która pobiera tylko łańcuchy. Ponieważ wiesz, jak utworzyć numer z łańcucha, zalecam używanie raw_input () zamiast input () w Pythonie 2.
Wejście z sieci
Zwykle otrzymujesz dane wejściowe dla programu od użytkownika. Ale są też inne sposoby na wejście. Możesz go pobrać z pliku na dysku twardym komputera lub możesz go pobrać z Internetu. Jeśli masz połączenie internetowe, możesz wypróbować program z listingu 5.4.
Listing 5.4 Pobieranie danych z pliku w sieci Web
import urllib2
file = urllib2.urlopen ("http://helloworldbook2.com/data/message.txt")
message = file.read ()
print message
To jest to. Z zaledwie czterema liniami kodu komputer sięga po sieć, aby pobrać plik z witryny i wyświetlić go. Jeśli wypróbujesz ten program (zakładając, że masz działające połączenie internetowe), zobaczysz wiadomość.
Jeśli wypróbujesz ten programu z komputera biurowego lub szkolnego, istnieje szansa, że nie zadziała. To dlatego, że niektóre biura i szkoły używają czegoś, co nazywa się proxy, aby połączyć się z Internetem. Serwer proxy to inny komputer, który działa jak most lub brama między Internetem a szkołą lub biurem. W zależności od konfiguracji serwera proxy ten program może nie wiedzieć, jak połączyć się z Internetem za pośrednictwem serwera proxy. Jeśli masz szansę wypróbować go w domu (lub w innym miejscu, które ma bezpośrednie połączenie internetowe bez serwera proxy), powinno działać.
Myśl jak programista
W zależności od używanego systemu operacyjnego (Windows, Linux lub Mac OS X), możesz zobaczyć małe kwadraty lub coś podobnego na końcu każdej linii, gdy próbujesz uruchomić program z lsitingu 5.4. Powodem jest to, że różne systemy operacyjne używają różnych sposobów wskazywania końca linii tekstu. Windows (i MS-DOS przed nim) używają dwóch znaków: CR (Carriage Return) i LF (Line Feed). Linux używa tylko LF. Mac OS X używa tylko CR. Niektóre programy mogą obsługiwać dowolne z nich, ale niektóre, na przykład IDLE, są zdezorientowane, jeśli nie widzą dokładnie oczekiwanych znaków kończących linię. Kiedy to się dzieje, wyświetlają mały kwadrat, co oznacza "Nie rozumiem tego znak". Możesz zobaczyć lub nie zobaczyć małe kwadraty, w zależności od używanego systemu operacyjnego i sposobu uruchamiania programu (przy użyciu IDLE lub jakąś inną metodę). #! / bin / env python # Plik tekstowy paginatae, dodawanie nagłówka i stopki import sys, time, string # Jeśli nie podano argumentów, wypisz pomocny komunikat, jeśli len (sys.argv)! = 2: print 'Użycie: pyprint filename'sys.exit (0) klasa # Zwiększ liczbę stron i zresetuj liczbę linii self.header_written = 1; self.count = 1; self.page = self.
Czego się nauczyłeś?
• Wprowadzanie tekstu za pomocą raw_input()
• Dodawanie komunikatu zachęty do raw_input()
• Wprowadzanie liczb za pomocą int() i float() z raw_input()
• Wyświetlania kilku rzeczy w jednej linii za pomocą przecinka
Sprawdź swoją wiedzę
1 Z tym kodem
response = raw_input()
jeśli użytkownik wpisze 12, jaki rodzaj danych odpowiada? Czy to ciąg czy liczba?
2 Jak użyć raw_input(), aby wyświetlić komunikat zachęty?
3 Jak uzyskać liczbę całkowitą za pomocą raw_input()?
4 Jak uzyskać float (liczbę dziesiętną) przy użyciu raw_input()?
Wypróbuj to
1 W trybie interaktywnym utwórz dwie zmienne, jedną dla imienia i drugą dla nazwiska. Następnie, używając pojedynczego print, wyświetl razem imię i nazwisko.
2 Napisz program, który poprosi o imię, a następnie poprosi o podanie nazwiska, a następnie wyświetli wiadomość z imionami i nazwiskami.
3 Napisz program, który poprosi o wymiary (w stopach) prostokątnego pomieszczenia, a następnie obliczy i wyświetli całkowitą ilość dywanu potrzebną do pokrycia pokoju.
4 Napisz program, który robi to samo, co w # 3, ale prosi również o koszt za metr kwadratowy dywanu. Następnie program powinien wyświetlić te trzy rzeczy:
• Całkowita ilość dywanu w stopach kwadratowych
• Całkowita ilość dywanu w kwadratowych jardach (1 kwadratowy jard = 9 stóp kwadratowych)
• Całkowity koszt dywanu
GUI - Graficzne interfejsy użytkownika
Do tej pory wszystkie nasze dane wejściowe i wyjściowe były prostym tekstem w oknie IDLE. Ale nowoczesne komputery i programy używają dużo grafiki. Byłoby miło, gdybyśmy mogli mieć trochę grafiki w naszych programach. Tu zaczniemy tworzyć proste GUI. Oznacza to, że nasze programy zaczną wyglądać bardziej jak te, do których jesteś przyzwyczajony - z oknami, przyciskami i tak dalej.
Co to jest GUI?
GUI to skrót od graphical user interface (graficzny interfejs użytkownika). W graficznym interfejsie użytkownika zamiast wpisywać tekst i odbierać tekst, użytkownik widzi graficzne elementy, takie jak okna, przyciski, pola tekstowe itd. a on może używać myszy do klikania rzeczy i pisania na klawiaturze. Typy programów, które do tej pory zrobiliśmy, to programy wiersza poleceń lub programy tekstowe. GUI to po prostu inny sposób interakcji z programem. Programy, które mają GUI, wciąż mają trzy podstawowe elementy: wejście, przetwarzanie i wyjście. Ale ich wejście i wyjście są nieco bardziej wyszukane. Przy okazji, skrót GUI jest zwykle wymawiany "gui" zamiast wypowiadania liter".
Nasze pierwszy GUI
Używałeś już GUI - w rzeczywistości kilka z nich. Przeglądarka internetowa to GUI. IDLE to GUI. Teraz będziesz tworzyć własne GUI. Aby to zrobić, otrzymasz pomoc od czegoś o nazwie EasyGui. EasyGui to moduł Pythona, który bardzo ułatwia tworzenie prostych GUI. Tak naprawdę jeszcze nie rozmawialiśmy o modułach , ale moduł jest sposobem na dodanie czegoś do Pythona, który nie jest jeszcze wbudowany. Jeśli masz już zainstalowany EasyGui to dobrze ,jeśli nie, możesz go pobrać z easygui.sourceforge.net/.
Instalowanie EasyGui
Możesz pobrać easygui.py lub plik zip, który zawiera easygui.py. Aby go zainstalować, wystarczy umieścić plik easygui.py w miejscu, w którym Python może go znaleźć. Gdzie to jest?
Ścieżka Pythona
Python ma listę miejsc na dysku twardym, gdzie szuka modułów, z których może korzystać. Może to być trochę skomplikowane, ponieważ jest inne dla Windows, Mac OS X i Linux. Ale jeśli umieścisz easygui.py w tym samym miejscu, w którym zainstalowany jest sam Python, Python go znajdzie. Tak więc na dysku twardym poszukaj folderu o nazwie Python i umieść easygui.py w tym folderze.
Przyjrzyjmy się GUI
Uruchom IDLE i wpisz następujące polecenie w trybie interaktywnym:
>>> import easygui
To mówi Pythonowi, że zamierzasz używać modułu EasyGui. Jeśli nie otrzymasz komunikatu o błędzie, Python odnalazł moduł EasyGui. Zróbmy teraz proste okno wiadomości z przyciskiem OK:
>>> easygui.msgbox ("Hello There!")
Funkcja EasyGui msgbox() służy do tworzenia okna wiadomości. W większości przypadków nazwy funkcji EasyGui są tylko skróconymi wersjami angielskich słów. Kiedy używasz msgbox (), powinieneś zobaczyć coś, co wygląda tak:
A jeśli klikniesz przycisk OK, okno wiadomości zostanie zamknięte.
Wejście GUI
Właśnie zobaczyłeś rodzaj wyjścia GUI - okno wiadomości. Ale co z wejściem? Możesz również uzyskać dane wejściowe za pomocą EasyGui. Czy po uruchomieniu poprzedniego przykładu w trybie interaktywnym kliknięto przycisk OK? Jeśli tak, powinieneś zobaczyć coś takiego w powłoce, terminalu lub oknie poleceń
>>> import easygui
>>> easygui.msgbox ("Witaj!")
'OK'
Częścią "OK" był Python i EasyGui informujący, że użytkownik kliknął przycisk OK. EasyGui przekazuje informacje zwrotne, aby powiedzieć, co zrobił użytkownik w GUI - jaki przycisk kliknął, co wpisał i tak dalej. Możesz nadać tej odpowiedzi nazwę (przypisz ją do zmiennej). Spróbuj tego:
>>> user_response = easygui.msgbox ("Witaj!")
Kliknij OK w oknie komunikatu, aby je zamknąć. Następnie wpisz to:
>>> print user_response
OK
Teraz odpowiedź użytkownika, OK, ma nazwę zmiennej user_response. Przyjrzyjmy się kilku innym sposobom uzyskiwania danych wejściowych za pomocą EasyGui. Okno wiadomości, które właśnie widziałeś, jest tak naprawdę jednym z przykładów czegoś, co nazywa się oknem dialogowym. Okna dialogowe są elementami GUI, które są używane do informowania użytkownika o czymś lub uzyskiwania informacji od użytkownika. Wprowadzeniem może być kliknięcie przycisku (np. OK) lub nazwa pliku lub jakiś tekst (ciąg). msg EasyGui to okno dialogowe z komunikatem i pojedynczym przyciskiem, OK. Ale możesz mieć różne rodzaje okien dialogowych z większą liczbą przycisków i innych rzeczy.
Wybierz swój smak
Wykorzystamy przykład wyboru ulubionego smaku lodów, aby przyjrzeć się różnym sposobom uzyskiwania danych wejściowych (smak lodów) od użytkownika za pomocą EasyGui.
Okno dialogowe z wieloma przyciskami
Zróbmy okno dialogowe (takie jak okno wiadomości) z więcej niż jednym przyciskiem. Można to zrobić za pomocą skrzynki z przyciskami (buttonbox). Zróbmy program, zamiast robić to w trybie interaktywnym. Rozpocznij nowy plik w IDLE. Wpisz program na poniższej liście
Listing 7.1 Pobieranie danych za pomocą przycisków
import easygui
flavor = easygui.buttonbox ("Jaki jest twój ulubiony smak lodów?",
options = ['Vanilla', 'Chocolate', 'Strawberry']) - lista wyborów
easygui.msgbox ("Wybrałeś" + flavor)
Część kodu w nawiasach kwadratowych nazywana jest listą. Nie rozmawialiśmy jeszcze o listach, ale dowiesz się o nich wszystkiego w Części 12. Na razie wpisz kod, aby umożliwić działanie programu EasyGui. (Lub, jeśli jesteś naprawdę ciekawy, możesz przejść dalej
) Zapisz plik (nazwałem mój ice_cream1.py) i uruchom go. Powinieneś to zobaczyć:
A następnie, w zależności od tego, który smak klikniesz, zobaczysz coś takiego:
Jak to działa? Etykieta z dowolnego przycisku, który kliknął użytkownik, była wejściem. Przydzieliliśmy to wejście nazwę zmiennej - w tym przypadku flavor. Podobnie jak w przypadku raw_input(), z wyjątkiem tego, że użytkownik nie wpisuje danych wejściowych, po prostu klika przycisk. Właśnie o to chodzi w GUI.
Pole wyboru
Wypróbujmy inny sposób wyboru smaku przez użytkownika. EasyGui ma coś zwanego polem wyboru (pole wyboru), które przedstawia listę wyborów. Użytkownik wybiera jeden, a następnie klika przycisk OK. Aby to wypróbować, wystarczy zrobić jedną małą zmianę w naszym programie z listingu 7.1: zmienić skrzynkę przycisków na pole wyboru. Nowa wersja zostanie wyświetlona obok.
Listing 7.2 Pobieranie danych wejściowych za pomocą pola wyboru
import easygui
flavor= easygui.choicebox ("Jaki jest twój ulubiony smak lodów?",
options = ['Vanilla', 'Chocolate', 'Strawberry'])
easygui.msgbox ("Wybrałeś" + flavor)
Zapisz program z listingu 7.2 i uruchom go. Powinieneś zobaczyć coś takiego:
Po kliknięciu smaku, a następnie kliknięciu OK, zobaczysz ten sam rodzaj okna wiadomości, co poprzednio. Zauważ, że oprócz klikania za pomocą myszy, możesz wybrać smak za pomocą klawiszy strzałek w górę iw dół na klawiaturze. Jeśli klikniesz Anuluj, program zakończy się, a zobaczysz również błąd. Dzieje się tak, ponieważ ostatni wiersz programu oczekuje jakiegoś tekstu (np. Vanilla), ale jeśli klikniesz Anuluj, nic nie dostanie. To samo stało się ze mną. Ale to duże pole wyboru nie pasowało do tego tekstu. Więc trochę oszukałam! Zmodyfikowałem easygui.py, abym mógł sprawić, że pole wyboru będzie mniejsze, by wyglądało ładniej. To nie jest coś, co musisz zrobić, ale jeśli naprawdę chcesz, oto są kroki. Ostrzegam, to trochę skomplikowane!
1 Znajdź sekcję w pliku easygui.py, która zaczyna się od def__choicebox (około linii 934 w mojej wersji easygui.py). Pamiętaj, że większość redaktorów pokazuje numery linii kodu gdzieś w dolnej części okna.
2 Około 30 linii w dół (od linii 970) zobaczysz kilka linii wyglądających tak:
root_width = int((screen_width * 0.8))
root_height = int((screen_height * 0.5))
Zmień wartość 0,8 na 0,4 i 0,5 na 0,25. Zapisz zmiany w easygui.py. Przy następnym uruchomieniu programu okno wyboru będzie mniejsze.
Wprowadzanie tekstu
Przykłady w tej części pozwoliły użytkownikowi wybrać z zestawu opcji, pod warunkiem. A co jeśli chcesz czegoś bardziej podobnego do raw_input(), gdzie użytkownik może wpisać tekst? W ten sposób może wprowadzić dowolny smak. EasyGui ma coś, co nazywa się Enter Box (Enterbox). Wypróbuj program na poniższej liście.
Listing 7.3 Pobieranie danych wejściowych za pomocą pola wprowadzania
import easygui
flavor = easygui.enterbox ("Jaki jest twój ulubiony smak lodów?")
easygui.msgbox ("Wprowadziłeś" + flavor)
Kiedy go uruchomisz, powinieneś zobaczyć coś takiego:
A potem, kiedy wpiszesz swój ulubiony smak i klikniesz OK, zostanie wyświetlony w oknie wiadomości, tak jak wcześniej. To jest tak samo jak raw_inpu(). Dostaje tekst (ciąg) od użytkownika.
Domyślne wejście
Czasami, gdy użytkownik wprowadza informacje, oczekiwane, wspólne ,najprawdopodobniej zostanie wprowadzona pewna odpowiedź. To się nazywa default. Możesz zaoszczędzić użytkownikowi pisania na maszynie, automatycznie wprowadzając dla niego najczęstszą odpowiedź. Wtedy musiałby tylko wpisać odpowiedź, gdyby miał inne dane wejściowe. Aby umieścić domyślne w polu wprowadzania, zmień swój program tak, aby wyglądał tak.
Listing 7.4 Jak dokonać domyślnych wyborów
import easygui
flavor = easygui.enterbox ("Jaki jest twój ulubiony smak lodów?",
default = 'Vanilla') <- tu mamy default
easygui.msgbox ("Wprowadziłeś" + flavor)
Po uruchomieniu "Vanilia" jest już wprowadzona w polu wprowadzania. Możesz go usunąć i wpisać wszystko, co chcesz, ale jeśli twój ulubiony smak jest waniliowy, nie musisz nic wpisywać: po prostu kliknij OK.
A co z liczbami?
Jeśli chcesz wprowadzić liczbę w EasyGui, zawsze możesz użyć pola wprowadzania, aby uzyskać ciąg, a następnie utworzyć z niego numer za pomocą int() lub float(). EasyGui ma również coś, co nazywa się polem całkowitym (integerbox), której możesz użyć do wprowadzania liczb całkowitych. Możesz ustawić dolny i górny limit liczby, którą można wprowadzić. Nie pozwala jednak na wprowadzanie liczb zmiennoprzecinkowych (liczb dziesiętnych). Aby wprowadzić liczby dziesiętne, należy użyć pola wprowadzania, pobrać ciąg, a następnie użyć float() do konwersji ciągu.
Gra z odgadywaniem liczb
znowu
W Części 1 wykonaliśmy prosty program odgadywania liczb. Spróbujmy teraz tego samego, ale używając EasyGui dla wejścia i wyjścia. Oto kod.
import random, easygui
secret = random.randint(1, 99) <- Wybiera tajny liczbę
guess = 0
tries = 0
easygui.msgbox("""AHOY! Jestem Dread Pirate Roberts, i mam sekret!
Jest to liczba od 1 do 99. Dam ci 6 prób..""")
while guess != secret and tries < 6:
guess = easygui.integerbox("Jak jest twoja próba?") - Pobiera odgadnięcie gracza
if not guess: break
if guess < secret:
easygui.msgbox(str(guess) + " jest za mała, szkarłatny psie!")
elif guess > secret:
easygui.msgbox(str(guess) + " jest za duża , szczurze lądowy!")
tries = tries + 1 <- Wykorzystuje jedną próbę
if guess == secret:
easygui.msgbox("Avast! Dostałeś to! Znalazłeś mój sekret!")
else: <- Wyświetla wiadomość na końcu gry
easygui.msgbox("Nie ma więcej odgdanień! Liczba to " + str(secret))
Nadal nie dowiedziałeś się, jak działają wszystkie części tego programu, ale wpisz go i spróbuj.
Inne elementy GUI
EasyGui ma kilka innych dostępnych elementów GUI, w tym pole wyboru, które pozwala wybrać wiele opcji (zamiast tylko jednego), a także kilka specjalnych okien dialogowych do pobierania nazw plików i tak dalej. Ale te, na które patrzyliśmy, są na razie wystarczające. EasyGui sprawia, że generowanie prostych interfejsów graficznych jest bardzo proste, i ukrywa wiele złożoności związanych z GUI, więc nie musisz się o to martwić. Później przyjrzymy się innemu sposobowi tworzenia GUI, który zapewnia dużo większą elastyczność i kontrolę.
Myślenie jak programista (Python)
Jeśli chcesz dowiedzieć się więcej o czymś związanym z Pythonem, takim jak EasyGui (lub czymkolwiek innym), istnieje wbudowany system pomocy, który możesz wypróbuj. Jeśli jesteś w trybie interaktywnym, możesz wpisać
>>> help()
w interaktywnym pytaniu, aby wejść do systemu pomocy. Monit zmieni się tak:
help>
Gdy już tam będziesz, wpisz nazwę rzeczy, w której chcesz pomóc, w ten sposób:
help> time.sleep
lub
help> easygui.msgbox
a otrzymasz trochę informacji. Aby wydostać się z systemu pomocy i powrócić do zwykłego interaktywnego monitu, wpisz słowo quit:
help> quit
>>>
Część pomocy jest trudna do odczytania i zrozumienia, a Ty nie zawsze znajdziesz to, czego szukasz. Ale jeśli szukasz więcej informacji na temat czegoś w Pythonie, warto spróbować.
Czego się nauczyłeś?
• Jak tworzyć proste GUI za pomocą EasyGui
• Jak wyświetlać wiadomości za pomocą okna komunikatu: msgbox
• Jak uzyskać dane wejściowe za pomocą przycisków, pól wyboru i pól wprowadzania tekstu: buttonbox, pole wyboru, enterbox, integerbox
• Jak ustawić domyślne wejście dla pola tekstowego
• Jak korzystać z wbudowanego systemu pomocy Pythona
Sprawdź swoją wiedzę
1 Jak wywołać okno wiadomości z EasyGui?
2 Jak uzyskać ciąg (jakiś tekst) jako dane wejściowe za pomocą EasyGui?
3 Jak uzyskać liczbę całkowitą jako dane wejściowe za pomocą EasyGui?
4 W jaki sposób uzyskać zmiennoprzecinkowy (numer dziesiętny) jako dane wejściowe za pomocą EasyGui?
5 Jaka jest wartość domyślna? Podaj przykład czegoś, z czego możesz go wykorzystać.
Wypróbuj to
1 Spróbuj zmienić program konwersji temperatury z Części 5, aby użyć wejścia i wyjścia GUI zamiast raw_input () i wydrukować.
2 Napisz program, który poprosi o Twoje imię, numer domu, następnie ulicę, miasto, następnie prowincję / terytorium / stan, a następnie kod pocztowy / pocztowy (wszystkie w oknach dialogowych EasyGui). Program powinien następnie wyświetlić pełny adres pocztowy, który wygląda mniej więcej tak:
Jan Sonik
ul. Błotna 3
Kostomłoty
W pierwszych kilku częściach zobaczyliśmy niektóre podstawowe elementy programu. Możemy teraz utworzyć program z wejściem, przetwarzaniem i wyjściem. Możemy nawet wprowadzić nasze dane wejściowe i wyprowadzić trochę bardziej wyszukanych użytkowników za pomocą GUI. Możemy przypisać dane wejściowe do zmiennej, abyśmy mogli z niej korzystać później i możemy użyć trochę matematyki do przetworzenia tego. Teraz zaczniemy szukać sposobów kontrolowania tego, co robi program. Gdyby program robił to samo za każdym razem, byłoby to trochę nudne i mało przydatne. Programy muszą mieć możliwość podejmowania decyzji, co robić. Zamierzamy dodać kilka różnych technik podejmowania decyzji do naszego repertuaru przetwarzania.
Testowanie, testowanie
Programy muszą mieć możliwość robienia różnych rzeczy w oparciu o ich dane wejściowe. Oto kilka przykładów:
• Jeśli Tomek otrzyma właściwą odpowiedź, dodaj 1 punkt do jego wyniku.
• Jeśli Janka uderzy obcego, wykonaj dźwięk eksplozji.
• Jeśli pliku nie ma, wyświetl komunikat o błędzie.
Aby podejmować decyzje, programy sprawdzają (wykonują test), aby sprawdzić, czy określony warunek jest prawdziwy, czy nie. W pierwszym przykładzie powyżej warunek "ma właściwą odpowiedź". Python ma tylko kilka sposobów na przetestowanie czegoś i są tylko dwie możliwe odpowiedzi dla każdego testu: prawda lub fałsz.
Oto kilka pytań, o które Python może poprosić o przetestowanie:
• Czy dwie rzeczy są równe?
• Czy jedna rzecz jest mniejsza niż inna?
• Czy jedna rzecz jest większa niż inna?
Ale poczekaj chwilę, "otrzymałem właściwą odpowiedź", czy nie jest to jeden z testów, które możesz wykonać, przynajmniej nie bezpośrednio. Oznacza to, że musisz opisać test w sposób zrozumiały dla Pythona. Kiedy chcemy wiedzieć, czy Tomek dostał właściwą odpowiedź, prawdopodobnie znamy poprawną odpowiedź, jak również odpowiedź Tomka . Gdyby Tomek miał prawidłową odpowiedź, wówczas dwie zmienne byłyby równe, a warunek byłby prawdziwy. Gdyby miał złą odpowiedź, dwie zmienne nie byłyby równe, a warunek byłby fałszywy. Wykonywanie testów i podejmowanie decyzji na podstawie wyników nazywa się rozgałęzianiem. Program decyduje, w którą stronę pójść lub jaką gałąź wybrać, na podstawie wyniku testu.
Python używa słowa kluczowego, if do testowania warunków, takich jak:
if timsAnswer == correctAnswer:
print "Masz rację!"
score = score + 1
print "Dzięki za grę."
Blok kodu to jedna lub więcej linii kodu, które są zgrupowane razem. Wszystkie są związane z określoną częścią programu (np. z instrukcją if). W Pythonie bloki kodu są tworzone przez wcięcie linii kodu w bloku.
Dwukropek (:) na końcu wiersza if mówi Pythonowi, że następny będzie blok instrukcji. Blok zawiera każdą linię wciętą od linii if, aż do następnej linii, która nie jest wcięta.
Wcięcie oznacza, że linia kodu jest nieco przesunięta w prawo. Zamiast zaczynać od lewej strony, ma kilka spacji na początku, więc zaczyna się kilka znaków od lewej strony.
Jeśli warunek jest prawdziwy, wszystko w następnym bloku zostanie wykonane. W poprzednim krótkim przykładzie druga i trzecia linia tworzą blok instrukcji dla if w pierwszym wierszu. Teraz może być dobry moment, aby porozmawiać o wcięciach i blokach kodu.
Wcięcie
W niektórych językach wcięcie jest tylko kwestią stylu - możesz wcinać dowolnie (lub wcale). Ale w Pythonie wcięcie jest niezbędną częścią tego, jak piszesz kod. Wcięcie mówi Pythonowi, gdzie zaczynają się bloki kodu i gdzie się kończą. Niektóre instrukcje w Pythonie, takie jak instrukcja if, potrzebują bloku kodu, aby powiedzieć im, co mają robić. W przypadku instrukcji if blok informuje Pythona, co zrobić, jeśli warunek jest prawdziwy. Nie ma znaczenia, jak daleko wcinasz blok, o ile cały blok jest wcięty w tej samej ilości. Konwencja w Pythonie polega na użyciu czterech spacji do wcięcia bloków kodu. Dobrym pomysłem byłoby śledzenie tego stylu w swoich programach. Konwencja oznacza, że wielu ludzi robi to w ten sposób
Czy widzę podwójnie?
Czy w instrukcji if występują dwa znaki równości (jeśli timsAnswer == correctAnswer)? Tak, są i oto dlaczego. Ludzie mówią: "Pięć plus cztery równa się dziewięć" i pytają: "Czy pięć plus cztery równa się dziewięć?" Jedno jest stwierdzeniem; drugie to pytanie. W Pythonie mamy takie same rzeczy - stwierdzenia i pytania. Instrukcja może przypisać wartość zmiennej. Pytanie może sprawdzić, czy zmienna jest równa pewnej wartości. Pierwsze oznacza, że coś ustawiasz (przypisujesz lub wyrównujesz). Drugi oznacza, że coś sprawdzasz lub testujesz (czy jest równe, tak czy nie?). Tak więc Python używa dwóch różnych symboli. Widziałeś już znak równości (=) używany do ustawiania lub przypisywania wartości do zmiennych. Oto kilka przykładów:
correctAnswer = 5 + 3
temperatura = 35
name = "Bill"
Aby sprawdzić, czy dwie rzeczy są równe, Python używa podwójnego znaku równości (==), tak jak poniżej:
if myAnswer == correctAnswer:
if temperatura == 40:
if nazwa == "Fred":
Mieszanie = i == jest jednym z najczęstszych błędów w programowaniu. Kilka języków używa tych symboli (nie tylko Pythona), a wielu programistów codziennie używa niewłaściwego w niewłaściwym miejscu.
Testowanie lub sprawdzanie nazywane jest także porównywaniem. Podwójny znak równości nazywany jest operatorem porównania. Pamiętajmy, że mówiliśmy o operatorach w części 3. Operator jest specjalnym symbolem, który działa na otaczających go wartościach. W tym przypadku operacja polega na sprawdzeniu, czy wartości są równe.
Inne rodzaje testów
Na szczęście dla nas inne operatory porównania są łatwiejsze do zapamiętania: mniej niż (<), większe niż (>) i nie równe (! =). (Możesz także użyć <>, dla nie być równym, ale większość ludzi używa !=) . Możesz również połączyć > lub < z =, aby uzyskać wartość większą lub równą (> =) i mniejszą lub równą (<=). Być może widziałeś niektóre z nich na matematyce.
Nie równe
W Pythonie 3 składnia < > nie równa się nie jest już obsługiwana. W Python 3, musisz użyć != dla nie równy.
Możesz również połączyć dwa operatory większe lub mniejsze niż razem, aby wykonać test pośredni, taki jak ten:
if 8 < wiek < 12:
Sprawdzi to, czy zmienna wiek ma wartość między, ale nie zawiera, 8 i 12. Byłoby to prawdą, gdyby wiek był równy 9, 10 lub 11 (lub 8.1 lub 11.6 itd.). Gdybyśmy chcieli uwzględnić wiek 8 i 12 lat, zrobilibyśmy to zamiast tego:
if 8 <= wiek <= 12:
Operatory porównania są również nazywane operatorami relacyjnymi (ponieważ testują relację między dwiema stronami: równe lub nie równe, większe lub mniejsze niż). Porównanie nazywane jest również testem warunkowym lub testem logicznym. W programowaniu logiczne odnosi się do czegoś, gdzie odpowiedź jest prawdziwa lub fałszywa.
Listing 8.1 Korzystanie z operatorów porównania
num1 = float(raw_input("Wpisz pierwszą liczbę: "))
num2 = float(raw_input("Wpisz drugą liczbę: "))
if num1 < num2:
print num1, "mniejsza niż", num2
if num1 > num2:
print num1, "większa niż", num2
if num1 == num2: <- Pamiętaj ,że jest to podwójny znak równości
print num1, "jest równe", num2
if num1 != num2:
print num1, "nie jest równe", num2
Co się stanie, jeśli test jest fałszywy?
Widziałeś, jak sprawić, by Python zrobił coś, jeśli wynik testu jest prawdziwy. Ale co robi, jeśli test jest fałszywy? W Pythonie istnieją trzy możliwości:
• Wykonaj kolejny test. Jeśli pierwszy test jest fałszywy, możesz przekonać Pythona do przetestowania czegoś innego za pomocą słowa kluczowego elif (które jest skrótem od "inaczej jeśli"), tak jak poniżej:
if answer >= 10:
print " Masz co najmniej 10!"
elif answer >= 5:
print " Masz co najmniej 5!"
elif answer >= 3:
print " Masz co najmniej3!"
Możesz mieć tyle instrukcji elif, ile chcesz po if
• Zrób coś innego, jeśli wszystkie inne testy wyjdą fałszywie. Robisz to za pomocą słowa kluczowego else. To zawsze ma miejsce na końcu, po wykonaniu instrukcji if i wszelkich elifów:
if answer >= 10:
print " Masz co najmniej 10!"
elif answer >= 5:
print " Masz co najmniej 5!"
elif answer >= 3:
print " Masz co najmniej 3!"
else:
print " Masz mniej niż 3."
• Przejdź dalej. Jeśli nie umieścisz niczego innego po bloku if, program przejdzie do następnego wiersza kodu (jeśli taki istnieje) lub zakończy się (jeśli nie ma więcej kodu).
Spróbuj utworzyć program z powyższym kodem, dodając na początku wiersz, aby wprowadzić liczbę:
answer = float (raw_input("Wprowadź liczbę od 1 do 15")).
Pamiętaj, aby zapisać plik (tym razem wybierasz nazwę), a następnie uruchom go. Wypróbuj kilka razy z różnymi danymi wejściowymi, aby zobaczyć, co otrzymujesz.
Testowanie więcej niż jednego warunku
Co zrobić, jeśli chcesz przetestować więcej niż jedną rzecz? Powiedzmy, że stworzyliśmy grę dla ośmiolatków i staramy się upewnić, że gracz jest w co najmniej trzeciej klasie. Istnieją dwa warunki do spełnienia. Oto jeden ze sposobów, w jaki możemy przetestować oba warunki:
age = float(raw_input("Wpisz swój wiek: "))
grade = int(raw_input("Wpisz swoją ocenę: "))
if age >= 8:
if grade >= 3:
print "Możesz grać w tę grę."
else:
print "Sorry, nie możesz zagrać w tę grę"
Pierwsza linia wydruku powinna być wcięta na osiem spacji, a nie tylko cztery spacje. To dlatego, że każdy potrzebuje własnego bloku, więc każdy ma swoje własne wcięcia.
Przypomnienie
Pamiętaj, jeśli używasz Pythona 3, musisz zastąpić raw_input() input() i musisz użyć nawiasów z print, jak poniżej:
print("Możesz grać w tę gr.")
Używanie and
Ten ostatni przykład będzie działał dobrze. Ale istnieje krótszy sposób na zrobienie tego samego. Możesz połączyć takie warunki:
age = float(raw_input("Wpisz swój wiek: "))
grade = int(raw_input("Wpisz swoją ocenę: "))
if age >= 8 and grade >= 3: <- Połącz warunki z "and"
print " Możesz grać w tę grę."
else:
print "Sorry, nie możesz zagrać w tę grę."
Połączyliśmy te dwa warunki za pomocą słowa kluczowego and. Oznacza, że oba warunki muszą być prawdziwe, aby wykonać następny blok.
Możesz umieścić więcej niż dwa warunki razem z:
Sorry, nie możesz zagrać w tę grę)
color = raw_input("Enter your favorite color: ")
if age >= 8 and grade >= 3 and color == "green":
print "Możesz zagrać w tę grę."
else:
print "Sorry, nie możesz zagrać w tę grę"
Jeśli jest więcej niż dwa warunki, wszystkie warunki muszą być prawdziwe, aby instrukcja if była prawdziwa. Istnieją również inne sposoby łączenia warunków.
Używanie or
Słowo kluczowe or, to słowo kluczowe również używane do łączenia warunków. Jeśli używasz or blok jest wykonywany, jeśli którykolwiek z warunków jest prawdziwy
color = raw_input("Wpisz swój ulubiony kolor: ")
if color == "red" or color == "blue" or color == "green":
print "Możesz zagrać w tę grę."
else:
print "Sorry, nie możesz zagrać w tę grę
Używanie not
Możesz także odwrócić porównanie, aby oznaczyć coś przeciwnego, używając nie:
color = raw_input("Wpisz swój ulubiony kolor: ")
if color == "red" or color == "blue" or color == "green":
print "Możesz zagrać w tę grę."
else:
print "Sorry, nie możesz zagrać w tę grę
Ta linia:
if not (age < 8)
oznacza to samo co :
if age >= 8:
W obu przypadkach blok jest wykonywany, gdy wiek wynosi 8 lat lub więcej, a wiek nie jest niższy niż 8. W części 4 widziałeś operatory matematyczne takie jak +, -, * i /. W tej sekcji zobaczyłeś operatory porównania <,>, == i tak dalej. Słowa kluczowe and, or not, są również operatorami. Nazywane są operatorami logicznymi. Są one używane do modyfikowania porównań, łącząc dwa lub więcej z nich (i, lub) lub odwracając je (nie). Tabela 1 zawiera listę wszystkich operatorów, o których do tej pory rozmawialiśmy
Lista operatorów matematycznych i porównawczych
Operatora : Nazwa : Co robi
Operatory matematyczne
= Przypisanie Przypisuje wartość do nazwy (zmiennej).
+ Dodawanie Dodaje dwie liczby razem. Może to być również używane do łączenia łańcuchów.
- Odejmowanie Odejmuje dwie liczby.
+= Przyrost Dodaje jeden do liczby.
-= Zmniejszenie Odejmuje jeden od liczby.
* Mnożenie Mnoży dwie liczby razem.
/ Dzielenie Dzieli dwie liczby. Jeśli obie liczby są liczbami całkowitymi, wynik będzie równy ilorazowi całkowitemu, bez reszty.
% Modulus Pobiera resztę (lub moduł) dla dzielenia liczb całkowitych dwóch liczb.
** Potęgowanie Podnosi liczbę do potęgi. Zarówno liczba, jak i moc mogą być liczby całkowite lub float.
Operatory porównania
== Równość Sprawdza, czy dwie rzeczy są równe.
< Mniej niż Sprawdza, czy pierwsza liczba jest mniejsza niż druga liczba.
> Większa niż Sprawdza, czy pierwsza liczba jest większa niż druga liczba.
<= Mniej niż lub równe Sprawdza, czy pierwsza liczba jest mniejsza lub równa drugiej liczbie.
>= Większy niż lub równy Sprawdza, czy pierwsza liczba jest większa lub równa drugą liczbę.
! = , < > Nie równy Sprawdza, czy dwie rzeczy nie są równe. (Można użyć dowolnego operatora
Możesz dodać tę stronę do zakładek, aby łatwo było powrócić do tej tabeli
Czego się nauczyłeś?
• Testy porównawcze i operatory relacyjne
• Wcięcia i bloki kodu
• Łączenie testów za pomocą and oraz or
• Cofanie testu przy użyciu not
Sprawdź swoją wiedzę
1 Jaki będzie wynik po uruchomieniu tego programu?
my_number = 7
if my_number < 20:
print 'Poniżej 20'
else:
print '20 lub powyżej'
2 Jakie będzie wyjście z programu w pierwszym pytaniu, jeśli zmienisz mój numer na 25?
3 Jakiej instrukcji if użyłbyś do sprawdzenia, czy liczba była większa niż 30, ale mniejsza lub równa 40?
4 Jakiej instrukcji if użyłbyś do sprawdzenia, czy użytkownik wprowadził literę "Q" wielkimi lub małymi literami?
Wypróbuj to
1 Sklep prowadzi sprzedaż. Daje 10% zniżki na zakupy o wartości 10 USD lub niższej i 20% zniżki na zakupy powyżej 10 USD. Napisz program, który zapyta o cenę zakupu i wyświetli rabat (10% lub 20%) i ostateczną cenę.
2 Drużyna piłkarska poszukuje dziewczyn w wieku od 10 do 12 lat, aby grać w drużynie. Napisz program, aby zapytać o wiek użytkownika i czy użytkownik jest mężczyzną czy kobietą (używając "m" lub "k"). Wyświetl wiadomość wskazującą, czy dana osoba kwalifikuje się do gry w zespole. Bonus: uczyń program tak, aby nie pytał o wiek, chyba że użytkownik jest dziewczyną.
3 Jesteś na długiej podróży samochodem i przyjedziesz na stację benzynową. 200 km do następnej stacji. Napisz program, aby dowiedzieć się, czy musisz kupić gaz tutaj, czy możesz poczekać na następną stację.
Program powinien zadać następujące pytania:
• Jak duży jest twój zbiornik paliwa w litrach?
• Jak pełny jest twój zbiornik (w procentach - na przykład w połowie pełny = 50)?
• Ile kilometrów na litr pali Twój samochód?
Wyjście powinno wyglądać mniej więcej tak
Rozmiar zbiornika: 60
procent pełny: 40
litr na km : 10
Możesz jechać kolejne 240 km
Następna stacja benzynowa znajduje się 200 km od hotelu
Możesz poczekać na następną stację.
lub
Rozmiar zbiornika: 60
procent pełny: 30 km na litr: 8
Możesz jechać kolejne 144 km
Następna stacja benzynowa znajduje się 200 km od hotelu
Zdobądź teraz benzynę!
Bonus: dołącz do swojego programu bufor o pojemności 5 litrów, na wypadek, gdyby wskaźnik paliwa nie był dokładny.
4 Utwórz program, w którym użytkownik musi wprowadzić tajne hasło, aby korzystać z programu. Oczywiście znasz hasło (ponieważ będzie w Twoim kodzie). Ale twoi znajomi będą musieli albo zapytać cię, odgadnąć hasło, albo nauczyć się Pythona na tyle, by spojrzeć na kod i dowiedzieć się tego! Program może być dowolny, w tym taki, który już napisałeś, lub po prostu taki, który wyświetla komunikat typu "Trafiłeś!"
Dla większości ludzi robienie tego samego w kółko jest bardzo nudne, więc czemu nie pozwolić komputerowi zrobić tego za nas? Komputery nigdy się nie nudzą, więc świetnie radzą sobie z powtarzającymi się zadaniami. W tej części zobaczymy, jak sprawić, by komputer powtórzył wszystko. Programy komputerowe często powtarzają te same kroki w kółko. Nazywa się to zapętleniem. Istnieją dwa główne rodzaje pętli:
• Te, które powtarzają się określoną liczbę razy - nazywane są pętlami zliczającymi.
• Te, które powtarzają się, dopóki nie wydarzy się pewna rzecz - nazywane są pętlami warunkowymi, ponieważ ciągną się tak długo, jak długo są pewne warunki.
Pętla zliczająca
Pierwszy rodzaj pętli nazywany jest pętlą zliczającą. Usłyszysz również, że nazywa się pętlą for, ponieważ wiele języków, w tym Python, używa słowa kluczowego for do tworzenia tego rodzaju pętli w programie. Wypróbujmy program, który używa pętli zliczającej. Uruchom nowe okno edytora tekstu w IDLE, używając polecenia Plik > Nowy (tak jak w przypadku naszego pierwszego programu). Następnie wpisz następujący program.
Listing 9.1 Bardzo prosta pętla
for looper in [1, 2, 3, 4, 5]:
print "hello"
Zapisz go jako Loop1.py i uruchom go. (Możesz użyć opcji menu Uruchom> Uruchom moduł lub skrótu naciśnięcia klawisza F5.) Powinieneś zobaczyć coś takiego:
>>> ================ RESTART ================
>>>
hello
hello
hello
hello
hello
Hej, czy jest tu jakieś echo? Program wydrukował "hello" pięć razy, mimo że było tylko jedno polecenie wydruku. W jaki sposób? Pierwsza linia (dla looper w [1, 2, 3, 4, 5] :) przetłumaczona na zwykły angielski oznacza to:
1. Zmienna looper zaczyna się od wartości 1 (więc looper = 1).
2.Pętla wykonuje wszystko, co jest w następnym bloku instrukcji, raz dla każdej wartości na liście. (Lista zawiera te liczby w nawiasach kwadratowych).
3. Za każdym razem w pętli looper przypisywana jest następna wartość na liście.
Druga linia (print "hello") to blok kodu, który Python wykonuje za każdym razem w pętli. Pętla for wymaga bloku kodu, aby powiedzieć programowi, co ma robić w każdej pętli. Ten blok (wcięta część kodu) nazywany jest ciałem pętli.
Każde przejście przez pętlę nazywa się iteracją.
Spróbujmy czegoś innego. Zamiast drukować to samo za każdym razem, sprawmy, aby program drukował coś innego za każdym razem w pętli.
Listing 9.2 Robienie czegoś innego za każdym razem w pętli for
for looper in [1, 2, 3, 4, 5]:
print looper
Zapisz to jako Loop2.py i uruchom je. Wyniki powinny wyglądać tak:
>>> ================ RESTART ================
>>>
1
2
3
4
5
Tym razem zamiast pięć razy wydrukować "cześć", wydrukowano wartość zmiennej looper. Za każdym razem w pętli looper pobiera następną wartość z listy.
Uciekające pętle
Uciekające pętle (zwane również pętlami nieskończonymi lub niekończącymi się pętlami) zdarzają się każdemu programiście raz na jakiś czas. Aby zatrzymać program w Pythonie w dowolnym momencie (nawet w niekontrolowanej pętli), naciśnij CTRL-C. Oznacza to, że naciskamy i przytrzymujemy klawisz CTRL i przytrzymując wciśnięty klawisz C. To będzie bardzo przydatne później! Gry i programy graficzne ciągle działają w pętli. Muszą uzyskiwać dane wejściowe z myszy, klawiatury lub kontrolera gier, przetwarzać dane wejściowe i aktualizować ekran. Kiedy zaczniemy pisać tego typu programy, będziemy używać wielu pętli. Istnieje duża szansa, że jeden z naszych programów w pewnym momencie utknie w pętli, więc musimy wiedzieć, jak ją odblokować
Do czego służą nawiasy kwadratowe?
Być może zauważyłeś, że lista wartości pętli jest ujęta w nawiasy kwadratowe. Nawiasy kwadratowe i przecinki między liczbami to sposób tworzenia listy w Pythonie. Wkrótce dowiesz się więcej o listach). Ale na razie wiem, że lista jest rodzajem "kontenera" do przechowywania kilku rzeczy razem. W tym przypadku rzeczy są liczbami - wartościami, które bierze looper, przechodząc przez różne iteracje pętli.
Korzystanie z pętli zliczającej
Zróbmy teraz coś bardziej użytecznego z pętlami. Wydrukujmy tabliczkę mnożenia. To zajmuje tylko małą zmianę w naszym programie. Oto nowa wersja
Listing 9.3 Drukowanie 8-krotnej tabeli
for looper in [1, 2, 3, 4, 5]:
print looper, "times 8 =", looper * 8
Zapisz go jako Loop3.py i uruchom go. Powinieneś zobaczyć coś takiego:
>>> =================== RESTART ===================
>>>
1 times 8 = 8
2 times 8 = 16
3 times 8 = 24
4 times 8 = 32
5 times 8 = 40.
Teraz zaczynamy dostrzegać moc pętli. Bez pętli musielibyśmy napisać taki program, aby uzyskać ten sam wynik:
print "1 times 8 =", 1 * 8
print "2 times 8 =", 2 * 8
print "3 times 8 =", 3 * 8
print "4 times 8 =", 4 * 8
print "5 times 8 =", 5 * 8
Aby utworzyć dłuższą tablicę mnożenia (powiedzmy do 10 lub 20), ten program byłby znacznie dłuższy, ale nasz program pętli byłby prawie taki sam (tylko z większą liczbą liczb na liście). Pętle to znacznie ułatwiają!
Skrót - range()
W poprzednim przykładzie zapętliliśmy tylko 5 razy:
for looper in [1, 2, 3, 4, 5]:
Ale co, jeśli chcieliśmy, aby pętla działała 100 razy lub 1000 razy? To byłoby dużo pisania!
Na szczęście istnieje skrót. Funkcja range() umożliwia wprowadzenie tylko wartości początkowych i końcowych, a także tworzy wszystkie wartości pomiędzy nimi. range() tworzy listę zawierającą zakres liczb. Następna lista używa funkcji range() w przykładzie tablicy mnożenia.
Listing 9.4 Pętla używająca range()
for looper in range (1, 5):
print looper, "times 8 =", looper * 8
Zapisz to jako Loop4.py i uruchom je. (Możesz użyć opcji menu Uruchom> Uruchom moduł lub skrótu naciśnięcia klawisza F5.) Powinieneś zobaczyć coś takiego:
>>> ================= RESTART =================
>>>
1 times 8 = 8
2 times 8 = 16
3 times 8 = 24
4 times 8 = 32
Jest prawie taki sam jak pierwszy wynik, poza tym, że brakowało mu ostatniej pętli! Czemu? Odpowiedź brzmi: zakres (1, 5) podaje nam listę [1, 2, 3, 4]. Możesz spróbować tego w trybie interaktywnym:
>>> print range(1, 5)
[1, 2, 3, 4]
Dlaczego nie 5?
Tak właśnie działa funkcja range(). Daje listę numerów zaczynających się od pierwszego numeru i kończących się tuż przed ostatnim numerem. Musisz wziąć to pod uwagę i dostosować zakres, aby uzyskać żądaną liczbę pętli.
Zasięg
Jeśli zrobisz to w Pythonie 3, otrzymasz coś innego:
>>> print(range(1, 5))
range(1,5)
Dzieje się tak, ponieważ w Pythonie 3 funkcja range() nie daje listy liczb, daje ci coś, co nazywa się iterowalnością. To jest coś, nad czym pętle mogą się iterować. (Pamiętaj o polu tekstowym powyżej.) Jeśli chodzi o używanie range() w pętli for, działa dokładnie tak samo. Pod maską jest trochę inaczej. Poniższa lista pokazuje nasz program zmodyfikowany, aby dać nam 8-krotny stół do 10.
Listing 9.5 Drukowanie 8-krotnej tabeli do 10 przy użyciu zakresu ()
for looper in range(1, 11):
print looper, "times 8 =", looper * 8
A oto co otrzymujemy po uruchomieniu:
>>> ================== RESTART ==================
>>>
1 times 8 = 8
2 times 8 = 16
3 times 8 = 24
4 times 8 = 32
5 times 8 = 40
6 times 8 = 48
7 times 8 = 56
8 times 8 = 64
9 times 8 = 72
10 times 8 = 80
W programie z listingu 9.5 zakres (1, 11) dał nam listę liczb od 1 do 10, a pętla wykonała jedną iterację dla każdego numeru na liście. Za każdym razem w pętli zmienna looper pobiera następną wartość z listy. Nawiasem mówiąc, nazwaliśmy pętlę zmienną looper, ale możesz ją nazwać dowolnie.
Kwestia stylu - nazwy zmiennych pętli
Zmienna pętli nie różni się od żadnej innej zmiennej. Nie ma w tym nic specjalnego - to tylko nazwa wartości. Nie ma znaczenia, że używasz zmiennej jako licznika pętli. Powiedzieliśmy wcześniej, że należy używać nazw zmiennych, które opisują, co robią zmienne. Dlatego w poprzednim przykładzie wybrałem nazwę looper. Ale zmienne pętli to jedno miejsce, w którym czasami możesz zrobić wyjątek. Dzieje się tak, ponieważ istnieje praktyka (pamiętajcie, że to powszechna praktyka) w programowaniu do używania liter i, j, k itd. Dla zmiennych pętli. Ponieważ wiele osób używa i, j i k dla zmiennych pętli, programiści przyzwyczajają się do tego w programach. Doskonale nadaje się do użycia innych nazw dla zmiennych pętlowych, tak jak my. Ale nie powinieneś używać i, j, k do niczego innego niż zmienne pętli.
Dlaczego i, j, i k dla pętli?
To dlatego, że wcześni programiści używali programów do obliczania rzeczy matematycznych, a matematyka już używa a, b, c i x, y, z dla innych rzeczy. Również w jednym popularnym języku programowania zmienne i, j oraz k były zawsze liczbami całkowitymi - nie można było ich zmienić na inne. Ponieważ liczniki pętli są zawsze liczbami całkowitymi, programiści zwykle wybierali i, j i k dla swoich liczników pętli i stało się to powszechną praktyką
Jeśli użyjemy tej konwencji, nasz program będzie wyglądał następująco:
for i in range(1, 5):
print i, "times 8 =", i * 8
I działałoby dokładnie tak samo. (Spróbuj i zobacz!) Które nazwy używasz dla zmiennych pętli to kwestia stylu. Styl dotyczy wyglądu programów, a nie tego, czy działają. Ale jeśli użyjesz tego samego stylu co inni programiści, twoje programy będą łatwiejsze do odczytania, zrozumienia i debugowania.
Skrót do range()
Nie zawsze musisz podawać range() dwie liczby, tak jak to robiliśmy w listingu 9.5. Możesz dać mu tylko jeden numer:
for i in range(5):
To to samo co zapisanie
for i in range (0, 5):
która daje ci listę liczb: [0, 1, 2, 3, 4]. W rzeczywistości większość programistów uruchamia pętle na 0 zamiast na 1. Jeśli użyjesz zakresu (5), otrzymasz 5 iteracji pętli, co jest łatwe do zapamiętania. Musisz tylko wiedzieć, że za pierwszym razem, będę równy 0, a nie 1, a ostatni raz będzie równy 4, a nie 5. Więc dlaczego większość programistów zaczyna pętle od 0 zamiast 1? Cóż, w dawnych dobrych czasach niektórzy ludzie zaczęli od 1, a niektórzy zaczęli od 0. Mieli te bardzo mądre argumenty, które z nich były lepsze. Ostatecznie wygrało 0 osób. Więc masz to. Większość ludzi zaczyna dzisiaj od 0, ale możesz użyć dowolnego z nich. Pamiętaj tylko, aby dostosować górny limit, aby uzyskać odpowiednią liczbę iteracji.
Ciąg jest jak lista znaków. Nauczyłeś się, że zliczanie pętli używa list do ich iteracji. Oznacza to, że możesz przejść przez łańcuch. Każdy znak w ciągu jest jedną iteracją w pętli. Jeśli więc wypiszemy zmienną pętli, drukujemy litery w łańcuchu, po jednym na raz. Ponieważ każda instrukcja drukowania rozpoczyna nową linię, każda z liter drukowana jest we własnej linii.
Liczenie krokami
Jak dotąd, twoje pętle liczące odliczały o 1 każdą iterację. Co jeśli chcesz, aby pętla liczyła się w krokach 2? lub 5? lub 10? Co z liczeniem wstecz? Funkcja range() może mieć dodatkowy argument, który pozwala zmienić rozmiar kroków z domyślnego 1 na inny rozmiar.
Argumenty to wartości, które umieszczasz w nawiasach, gdy używasz funkcji takiej jak range(). Mówimy, że przekazujesz argument do funkcji. Termin parametr jest również używany, jak w "przekazać parametr".
Wypróbujmy kilka pętli w trybie interaktywnym. Kiedy wpiszesz w pierwszej linii, z dwukropkiem na końcu, IDLE automatycznie wcina następny wiersz, ponieważ wie, że pętla for wymaga bloku kodu następującego po nim. Po zakończeniu bloku kodu naciśnij dwukrotnie klawisz Enter (lub Return). Spróbuj:
>>> for i in range(1, 10, 2):
print i
1
3
5
7
9
Dodaliśmy trzeci parametr, 2, do funkcji range(). Teraz pętla liczy się w krokach 2. Wypróbujmy inny:
>>> for i in range(5, 26, 5):
print i
5
10
15
20
25
Teraz przechodzimy przez 5. Jak liczyć wstecz?
>>> for i in range(10, 1, -1):
print i
10
9
8
7
6
5
4
3
2
Gdy trzeci parametr w funkcji range() jest ujemny, pętla odlicza w dół zamiast w górę. Pamiętaj, że pętla zaczyna się od pierwszej liczby i idzie do (lub w dół), ale nie obejmuje drugiej liczby, więc w naszym ostatnim przykładzie osiągnęliśmy tylko 2, a nie 1. Możemy to wykorzystać do wykonania programu odliczającego czas . Musimy tylko dodać kilka kolejnych linii. Otwórz nowe okno edytora w IDLE i wpisz następujący program. Następnie spróbuj go uruchomić.
Listing 9.6 Gotowy do startu?
import time
for i in range(10, 0, -1): <- Liczy do tyłu
print i
time.sleep(1) <- Czeka sekundę
print "BLAST OFF!"
>>> for i in range(10, 1, -1):
print i
10
9
8
7
6
5
4
3
2
Nie martw się o rzeczy w programie, o których jeszcze nie powiedziałem, takie jak import, time i sleep. Dowiesz się o tym wszystkiego w następnych częściach. Po prostu wypróbuj program z listingu 9.6 i zobacz, jak to działa. Ważna jest tu część zakresu (10, 0, -1), która tworzy pętlę, która liczy wstecz od 10 do 1.
Liczenie bez liczb
We wszystkich poprzednich przykładach zmienna pętli była liczbą. W kategoriach programowania mówimy, że pętla iteruje po liście liczb. Ale lista nie musi być listą liczb. Jak już zauważyłeś , może to być lista znaków . Może to być także lista ciągów lub cokolwiek innego. Najlepszym sposobem, aby zobaczyć, jak to działa, jest przykład. Wypróbuj następny program i zobacz, co się stanie.
Listing 9.7 Kto jest najfajniejszy z nich wszystkich?
for cool_guy in ["Spongebob", "Spiderman", "Justin Timberlake", "My Dad"]:
print cool_guy, "jest najfajniejszym facetem w historii!"
Teraz nie zapętlamy listy numerów, zapętlamy listę ciągów. I zamiast i dla zmiennej pętli użyłem cool_guy. Zmienna pętli cool_guy za każdym razem pobiera inną wartość z listy. Jest to nadal rodzaj pętli zliczającej, ponieważ nawet jeśli lista nie jest listą liczb, Python zlicza, ile elementów znajduje się na liście, aby wiedzieć, ile razy należy zapętlić. (Tym razem nie pokażę, jak wygląda wyjście - zobaczysz to po uruchomieniu programu). Ale co, jeśli nie wiesz z wyprzedzeniem, ile iteracji wykonałeś? A jeśli nie ma listy wartości, których można użyć? Nie dotykaj tego pokrętła, ponieważ nadchodzi następne!
W tym temacie
Właśnie dowiedziałeś się o pierwszym rodzaju pętli, pętli for lub pętli zliczającej. Drugi rodzaj pętli nazywany jest pętlą while lub pętlą warunkową. Pętla for jest świetna, jeśli z góry wiesz, ile razy chcesz uruchomić pętlę. Ale czasami chcesz, aby pętla działała, dopóki coś się nie wydarzy, a ty nie wiesz, ile iteracji będzie, dopóki to się nie wydarzy. Pętla while pozwala to zrobić. W ostatniej części dowiedziałeś się o warunkach i testowaniu oraz instrukcji if. Zamiast liczyć, ile razy uruchomić pętlę, podczas gdy pętle używają testu, aby zdecydować, kiedy zatrzymać pętlę. Pętle while nazywane są również pętlami warunkowymi. Pętla warunkowa jest zapętlona, gdy spełniony jest jakiś warunek. Zasadniczo, pętla warunkowa pyta: "Czy już skończyłem? … Czy już skończyłem? … Czy już skończyłem? … "Aż do końca. Wykonywana jest , aż do momentu gdy warunek nie jest już prawdą. Pętle while używają słowa kluczowego while Pythona. Listing 9.8 pokazuje przykład. Wpisz program, wypróbuj go i zobacz, jak działa. (Pamiętaj, że musisz go zapisać, a następnie go uruchomić).
Listing 9.8 Warunek lub pętla while
print "Wpisz 3, aby kontynuować, cokolwiek innego kończy."
someInput = raw_input()
while someInput == '3': <-Kontynuuj zapętlanie tak długo, jak someInput = '3'
print " Dziękuję za 3. Bardzo miło z twojej strony."
print "Wpisz 3, aby kontynuować, cokolwiek innego kończy."
someInput = raw_input()
print " To nie jest 3, więc teraz kończę."
Ten program nadal prosi o dane wejściowe od użytkownika. Podczas gdy wejście jest równe 3, warunek jest prawdziwy i pętla działa. Dlatego ten rodzaj pętli warunkowej jest również nazywany pętlą while i używa słowa kluczowego while. Gdy wejście nie jest równe 3, warunek jest fałszywy, a pętla zatrzymuje się.
Wycofywanie się z pętli - przerwanie i kontynuacja
Czasami chcesz wydostać się z pętli pośrodku, zanim pętla for zostanie zakończona, lub zanim pętla zostanie znaleziona. Można to zrobić na dwa sposoby: możesz przeskoczyć do następnej iteracji pętli, z continue, lub możesz przerwać zapętlanie z break. Przyjrzyjmy się im bliżej.
Skakanie do przodu - continue
Jeśli chcesz przestać wykonywać bieżącą iterację pętli i przejść do następnej iteracji, instrukcja continue jest tym, czego potrzebujesz. Najlepszym sposobem na pokazanie tego jest przykład.
Listing 9.9 Używanie continue w pętli
for i in range(1, 6):
print
print 'i =', i,
print 'Hello, jak',
if i == 3:
continue
print 'się masz?'
Jeśli uruchomimy ten program, dane wyjściowe będą wyglądać następująco:
>>> ================== RESTART ==================
>>>
i = 1 Hello jak się masz ?
i = 2 Hello jak się masz ?
i = 3 Hello jak
i = 4 Hello jak się masz ?
i = 5 Hello jak się masz?
Zauważ, że po raz trzeci w pętli (gdy i == 3) ciało pętli nie skończyło się, przeskoczyło do następnej iteracji (i == 4). To było działanie continue. Działa w ten sam sposób w pętlach while.
Wycofywanie się - break
Co zrobić, jeśli chcesz całkowicie wyskoczyć z pętli - nigdy nie kończyć liczenia lub zrezygnować z czekania na stan końcowy? Instrukcja break to robi. Zmieńmy tylko wiersz 6 listingu 9.9, zastąp continue break i uruchom ponownie program, aby zobaczyć, co się stanie:
>>> ================== RESTART ==================
>>>
i = 1 Hello jak się masz?
i = 2 Hello jak się masz?
i = 3 Hello jak
Tym razem pętla nie pominęła reszty iteracji 3; całkowicie się zatrzymała. To właśnie robi break. Działa w ten sam sposób w pętlach while. Powinienem powiedzieć, że niektórzy ludzie myślą, że używanie przerwy i kontynuowanie to zły pomysł. Osobiście nie sądzę, żeby były złe, ale rzadko z nich korzystam. Pomyślałem, że powiem ci o przerwie i kontynuuję na wypadek, gdybyś ich kiedykolwiek potrzebował.
Czego się nauczyłeś?
• pętli for (zwanych również pętlami zliczającymi)
• Funkcji range() - skrót do liczenia pętli
• Różne rozmiary stopni dla range()
• pętli while (zwanyche również pętlami warunkowymi)
• Przejście do następnej iteracji z continueą
• Wyskakiwanie z pętli z break
Sprawdź swoją wiedzę
1 Ile razy uruchomi się następująca pętla?
for i in range(1, 6):
print 'Hi, Wanda'
2 Ile razy uruchomi się następująca pętla? A jakie byłyby wartości dla każdej pętli?
for i in range(1, 6, 2):
print 'Hi, Wanda'
3 Jaka lista liczb może być w zakresie(1, 8)?
4 Jaka lista liczb może być w zakresie (8)?
5 Jaka jest lista liczb (2, 9, 2)?
6 Jaka lista liczb mieściłaby się w przedziale (10, 0, -2)?
7 Jakiego słowa kluczowego używasz, aby zatrzymać bieżącą iterację pętli i przejść do następnej iteracji?
8 Kiedy kończy się pętla czasu?
Wypróbuj to
1 Napisz program, aby wydrukować tabliczkę mnożenia (tabela czasów). Na początku powinien zapytać użytkownika, którą tabelę wydrukować. Wynik powinien wyglądać mniej więcej tak:
Jaką tabliczkę mnożenia chcesz?
5
Oto twoja tabliczka:
5 x 1 = 5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45
5 x 10 = 50
2 Prawdopodobnie użyłeś pętli for w swoim pytaniu dla pytania 1. W ten sposób większość ludzi by to zrobiła. Ale tylko dla praktyki, spróbuj zrobić to samo z pętlą while. Lub jeśli użyłeś pętli while w pytaniu 1, spróbuj z pętlą for.
3 Dodaj coś innego do programu tabliczki mnożenia. Po zapytaniu, którego stołu chce użytkownik, zapytaj go, jak wysoko powinien iść stół. Wynik powinien wyglądać następująco:
Jaką tabliczkę mnożenia chcesz?
7
Jak wysoko chcesz iść?
12
Oto twój stół:
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70
7 x 11 = 77
7 x 12 = 84
Możesz to zrobić za pomocą wersji programu dla pętli for, wersji pętli while lub obu.
Tylko dla Ciebie - Komentarze
Do tej pory wszystko, co wpisaliśmy do naszych programów (i w trybie interaktywnym), było instrukcjami dla komputera. Ale to bardzo dobry pomysł, aby dołączyć do siebie kilka notatek w swoich programach, opisując, co robi program i jak działa. To pomoże ci (lub komuś innemu) spojrzeć na swój program później i dowiedzieć się, co zrobiłeś. W programie komputerowym te notatki są nazywane komentarzami.
Dodawanie komentarzy
Komentarze są tylko do przeczytania, a nie do uruchomienia komputera. Komentarze są częścią dokumentacji programu, a komputer ignoruje je podczas uruchamiania programu. Python ma kilka sposobów dodawania komentarzy do swojego programu.
Dokumentacja
Dokumentacja to informacja o programie opisującym program i sposób jego działania. Komentarze są częścią dokumentacji programu, ale mogą istnieć inne części, poza samym kodem, które opisują takie rzeczy
• Dlaczego program został napisany (jego cel)
• Kto to napisał
• Dla kogo jest przeznaczony (jego użytkowników)
• Jak to jest zorganizowane
i wiele więcej. Większe, bardziej skomplikowane programy zazwyczaj mają więcej dokumentacji. Pomoc Pythona to rodzaj dokumentacji. Ma pomóc użytkownikom - tak jak Ty - zrozumieć, jak działa Python.
Komentarze pojedynczej linii
Możesz dodać dowolną linię do komentarza, rozpoczynając od znaku numeru (#, czasami nazywanego znakiem funta):
# To jest komentarz w programie Python
print"To nie jest komentarz"
Jeśli uruchomimy te dwie linie, otrzymamy następujące dane wyjściowe:
To nie jest komentarz
Pierwsza linia jest ignorowana podczas działania programu. Komentarz zaczynający się od znaku # jest przeznaczony tylko dla Ciebie i innych osób czytających ten kod.
Komentarze końca linii
Możesz także umieścić komentarze na końcu wiersza kodu, jak poniżej:
area = length * width # Oblicz obszar prostokąta
Komentarz zaczyna się od znaku #. Wszystko przed # jest normalną linią kodu. Wszystko po tym jest komentarzem
Komentarze wielowierszowe
Czasami chcesz użyć więcej niż jednej linii do komentarzy. Możesz użyć kilku linii ze znakiem # na początku każdego z nich, tak jak poniżej:
# ***************
# Jest to program ilustrujący, w jaki sposób komentarze są używane w Pythonie
# Wiersz gwiazd służy do wizualnego oddzielenia komentarzy
# z reszty kodu
# ***************
Komentarze wielowierszowe są przydatne do wizualnego wyróżniania sekcji kodu, gdy go czytasz. Możesz ich użyć, aby opisać, co dzieje się w sekcji kodu. Komentarz wielowierszowy na początku programu może zawierać nazwę autora, nazwę programu, datę jego napisania lub aktualizacji, a także wszelkie inne informacje, które Twoim zdaniem mogą być przydatne.
Łańcuchy z potrójnymi cudzysłowami
Jest inny sposób na zrobienie czegoś, co działa jak komentarz wielowierszowy w Pythonie. Możesz po prostu utworzyć ciąg trzykrotnych dwucdzysłowów bez nazwy. Pamiętasz z Części 2, że ciąg z trzema cudzysłowami jest ciągiem, który może obejmować wiele linii. Możesz to zrobić:
"""Oto komentarz, który jest na wielu
liniach, używając potrójnie cytowanego ciągu.
To nie jest komentarz, ale to
zachowuje się jak jeden.
"""
Ponieważ łańcuch nie ma nazwy, a program nie robi "nic" z łańcuchem, nie ma to wpływu na sposób działania programu. Więc działa jak komentarz, mimo że nie jest komentarzem w ścisłych terminach Pythona
Myślenie jak programista (Python)
Niektórzy programiści Pythona twierdzą, że nie należy używać potrójnie cytowanych łańcuchów (łańcuchów wielowierszowych) jako komentarzy. Osobiście nie widzę powodu, by tego nie robić. Powodem komentarzy jest stworzenie kodu bardziej czytelnego i zrozumiałego. Jeśli stwierdzisz, że potrójne łańcuchy są dla Ciebie wygodne, bardziej prawdopodobne jest, że dodasz komentarze do kodu, co jest dobrą rzeczą.
Jeśli wpiszesz komentarze do edytora IDLE, zobaczysz, że komentarze mają swój własny kolor. Ma to ułatwić czytanie kodu. Większość edytorów kodu pozwala zmienić kolor komentarzy (i innych części kodu). Domyślnym kolorem komentarzy w IDLE jest czerwony. Ponieważ potrójne łańcuchy nie są prawdziwe Komentarze w Pythonie, będą innego koloru. W IDLE będą zielone, ponieważ zielony jest domyślnym kolorem IDLE dla ciągów.
Styl komentowania
Teraz wiesz, jak dodawać komentarze. Ale jakie rzeczy należy w nich umieścić? Ponieważ nie mają wpływu na działanie programu, mówimy, że są one kwestią stylu. Oznacza to, że możesz umieścić w komentarzach wszystko, co chcesz (lub nie używać ich wcale). Ale to nie oznacza, że komentarze nie są ważne. Większość programistów uczy się tego na własnej skórze, kiedy wracają do programu, który napisali kilka tygodni, miesięcy lub lat temu (lub nawet tego, który napisali wczoraj) i nie mogą tego zrozumieć! Zwykle dlatego, że nie przedstawili wystarczających komentarzy, aby wyjaśnić, jak działa program. Może się wydawać oczywiste, kiedy to piszesz, ale może to być kompletna tajemnica, gdy spojrzysz na to później
Nie ma sztywnych zasad dotyczących tego, co powinieneś umieścić w komentarzach, ale zachęcam do dodawania tylu komentarzy, ile chcesz. Na razie im więcej, tym lepiej. Lepiej błądzić po stronie zbyt wielu komentarzy niż za mało. Gdy zdobędziesz więcej doświadczenia w programowaniu, poczujesz, jak dużo i jaki rodzaj komentarzy działa najlepiej dla Ciebie.
Komentowanie
Możesz także użyć komentarzy, aby tymczasowo wykluczyć części programu z uruchomienia. Wszystko, co jest komentarzem, zostanie zignorowane:
#print "Hello"
print "World"
>>> =============== RESTART ================
>>>
World
Ponieważ polecenie print "Hello" zostało skomentowane, ta linia nie została wykonana, więc słowo "Hello" nie zostało wyświetlone. Jest to przydatne, gdy debugujesz program i chcesz, aby niektóre części były uruchamiane, a inne części ignorowane. Po prostu umieść # przed dowolnym wierszem, który chcesz, aby komputer ignorował, lub umieść potrójne cytaty w części kodu, którą komputer ma ignorować. Większość edytorów kodu, w tym IDLE, ma funkcję, która pozwala szybko komentować (i odkomentować) całe bloki kodu. W edytorze IDLE zajrzyj do menu Format.
Czego się nauczyłeś?
• Komentarze są tylko dla Ciebie (i innych ludzi), a nie dla komputera.
• Komentarze mogą być również używane do blokowania części kodu, aby zapobiec ich uruchomieniu.
• Możesz użyć potrójnie cytowanych ciągów jako rodzaju komentarza obejmującego wiele linii.
Sprawdź swoją wiedzę
Ponieważ komentarze są dość proste, zrobimy sobie przerwę i nie będziemy mieć żadnych pytań testowych.
Wypróbuj to
Wróć do programu konwersji temperatury i dodaj kilka komentarzy. Uruchom ponownie program, aby zobaczyć, że nadal działa tak samo.
Czas Gry
Jedną z wielkich tradycji nauki programowania jest wpisywanie kodu, którego nie rozumiesz. Naprawdę!
Czasami po prostu wpisanie kodu daje poczucie, jak wszystko działa, nawet jeśli nie rozumiesz każdej linii lub słowa kluczowego. Zrobiliśmy to w Części 1, z grą zgadywania liczb. Teraz zrobimy to samo, ale z dłuższym, bardziej interesującym programem.
Narciarz
Narciarz to bardzo prosta gra narciarska, inspirowana grą o nazwie SkiFree. Zjeżdżasz w dół wzgórza, starając się unikać drzew i dotykać flag. Dotknięcie flagi odejmuje 10 punktów. Wpadnięcie na drzewo sprawia, że tracisz 100 punktów. Narciarz używa czegoś, co nazywa się Pygame, aby pomóc w grafice. Pygame to moduł Pythona. Jeśli uruchomiłeś instalator, Pygame jest zainstalowane. Jeśli nie, możesz pobrać go z www.pygame.org.
Możesz je znaleźć w folderze przykładów (jeśli uruchomiłeś instalator). Po prostu umieść je w tym samym folderze lub katalogu, w którym zapisujesz program. To bardzo ważne. Jeśli nie znajdują się w tym samym katalogu co program, Python ich nie znajdzie, a program nie zadziała. Kod dla narciarza znajduje się na listingu 11.1. Listing jest nieco długa, około 100 linii kodu (plus kilka pustych linii, aby ułatwić jej czytanie), ale zachęcam do poświęcenia czasu na jej wpisanie. W wykazie znajduje się kilka notatek, które wyjaśniają nieco co robi kod. Zauważ, że kiedy widzisz __init__ w kodzie, po obu stronach init znajdują się dwa podkreślniki. To dwa podkreślenia przed i dwa podkreślenia po, a nie tylko jeden po obu stronach.
Listing 11.1 Narciarz
import pygame, sys, random
skier_images = ["pyth65.png", "pyth67.png",
"pyth68.png", "pyth66.png",
"pyth67.png"]
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("skier_down.png")
self.rect = self.image.get_rect()
self.rect.center = [320, 100]
self.angle = 0
def turn(self, direction):
self.angle = self.angle + direction
if self.angle < -2: self.angle = -2 <- Obroty narciarza
if self.angle > 2: self.angle = 2
center = self.rect.center
self.image = pygame.image.load(skier_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle, 6 - abs(self.angle) * 2]
return speed
def move(self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 20: self.rect.centerx = 20
if self.rect.centerx > 620: self.rect.centerx = 620
class ObstacleClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, type):
pygame.sprite.Sprite.__init__(self)
self.image_file = image_file
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.center = location
self.type = type
self.passed = False
def update(self):
global speed
self.rect.centery -= speed[1]
if self.rect.centery < -32:
self.kill()
def create_map():
global obstacles
locations = []
for i in range(10):
row = random.randint(0, 9)
col = random.randint(0, 9)
location = [col * 64 + 20, row * 64 + 20 + 640]
if not (location in locations):
locations.append(location)
type = random.choice(["tree", "flag"])
if type == "tree": img = "skier_tree.png"
elif type == "flag": img = "skier_flag.png"
obstacle = ObstacleClass(img, location, type)
obstacles.add(obstacle)
def animate():
screen.fill([255, 255, 255])
obstacles.draw(screen)
screen.blit(skier.image, skier.rect)
screen.blit(score_text, [10, 10])
pygame.display.flip()
pygame.init()
screen = pygame.display.set_mode([640,640])
clock = pygame.time.Clock()
skier = SkierClass()
speed = [0, 6]
obstacles = pygame.sprite.Group()
map_position = 0
points = 0
create_map()
font = pygame.font.Font(None, 50)
running = True
while running:
clock.tick(30) <- Aktualizowanie grafiki co 30 sekund
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed = skier.turn(-1)
elif event.key == pygame.K_RIGHT:
speed = skier.turn(1)
skier.move(speed) <- Ruch narciarza
map_position += speed[1] <- Przewinięcie ekranu
if map_position >=640:
create_map()
map_position = 0
hit = pygame.sprite.spritecollide(skier, obstacles, False)
if hit:
if hit[0].type == "tree" and not hit[0].passed:
points = points - 100
skier.image = pygame.image.load("skier_crash.png")
animate()
pygame.time.delay(1000)
skier.image = pygame.image.load("skier_down.png")
skier.angle = 0
speed = [0, 6]
hit[0].passed = True
elif hit[0].type == "flag" and not hit[0].passed:
points += 10
hit[0].kill()
obstacles.update()
score_text = font.render("Score: " +str(points), 1, (0, 0, 0)) <-Wyświetlanie wyniku
animate()
pygame.quit()
Kod 11.1 znajduje się w folderze przykładów, więc jeśli utkniesz lub nie chcesz go wpisywać, możesz użyć tego pliku. Ale wierzcie lub nie, dowiesz się więcej, wpisując go, niż otwierając i przeglądając listę. W kolejnych częściach dowiesz się o wszystkich słowach kluczowych i technikach używanych w Narciarzu. Na koniec jest cała sekcja wyjaśniająca szczegółowo, jak działa program Narciarz. Ale na razie wpisz to i spróbuj.
Widzieliśmy już, że w ciele pętli (która jest blokiem kodu) możemy umieścić inne rzeczy, które mają własne bloki. Jeśli spojrzysz na program zgadywania liczb z części 1, zobaczysz to:
while guess != secret and tries < 6:
guess = input("What's yer guess? ") <- blok pętli while
if guess < secret:
print "Zbyt niska, szkarłatna papugo !" <- blok if
elif guess > secret:
print "Zbyt wysoka, szczurze lądowy!" <- blok elif
tries = tries + 1
Blok zewnętrzny, jest blokiem pętli while, a pozostałe bloki są blokami if i elif w tym bloku pętli while. Możesz także umieścić pętlę w innej pętli. Pętle te nazywane są pętlami zagnieżdżonymi. Bez części wprowadzonej przez użytkownika może wyglądać mniej więcej tak:
multiplier = 5
for i in range (1, 11):
print i, "x", multiplier, "=", i * multiplier
Co jeśli chciałbyś wydrukować trzy tabliczki mnożenia na raz? Właśnie do tego nadaje się pętla zagnieżdżona. Zagnieżdżona pętla to jedna pętla w innej pętli. Dla każdej iteracji zewnętrznej pętli wewnętrzna pętla przechodzi przez wszystkie iteracje. Aby wydrukować trzy tabliczki mnożenia, wystarczy zamknąć oryginalną pętlę (która drukuje pojedynczą tabliczkę mnożenia) w zewnętrznej pętli (która działa trzy razy). Dzięki temu program drukuje trzy tabele zamiast jednej. Poniższa lista pokazuje, jak wygląda kod.
Listing 12.1 Drukowanie trzech tabliczek mnożenia na raz
for multiplier in range (5, 8):
for i in range (1, 11):
print i, "x", multiplier, "=", i * multiplier
print
Zauważ, że musieliśmy wciąć pętlę wewnętrzną i instrukcję print dodatkowe cztery spacje od początku zewnętrznej pętli for. Ten program wydrukuje 5 razy, 6 razy i 7 razy tabele, maksymalnie 10 dla każdej tabeli:
>>> ==================== RESTART ===================
>>>
1 x 5 = 5
2 x 5 = 10
3 x 5 = 15
4 x 5 = 20
5 x 5 = 25
6 x 5 = 30
7 x 5 = 35
8 x 5 = 40
9 x 5 = 45
10 x 5 = 50
1 x 6 = 6
2 x 6 = 12
3 x 6 = 18
4 x 6 = 24
5 x 6 = 30
6 x 6 = 36
7 x 6 = 42
8 x 6 = 48
9 x 6 = 54
10 x 6 = 60
1 x 7 = 7
2 x 7 = 14
3 x 7 = 21
4 x 7 = 28
5 x 7 = 35
6 x 7 = 42
7 x 7 = 49
8 x 7 = 56
9 x 7 = 63
10 x 7 = 70
Chociaż możesz pomyśleć, że jest to dość nudne, dobrym sposobem, aby zobaczyć, co dzieje się z zagnieżdżonymi pętlami, jest wydrukowanie kilku gwiazdek na ekranie i ich policzenie. Zrobimy to w następnej sekcji.
Zmienne pętli
Stałe liczby, takie jak te, których używałeś w funkcji range (), są również nazywane stałymi. Jeśli użyjesz stałych w funkcji range() pętli for, pętla będzie działać tyle samo razy, gdy program zostanie uruchomiony. W takim przypadku mówimy, że liczba pętli jest zakodowana na stałe, ponieważ jest zdefiniowana w kodzie i nigdy się nie zmienia. To nie zawsze jest to, czego chcesz. Czasami chcesz, aby liczba pętli była określana przez użytkownika lub inną część programu. Do tego potrzebujesz zmiennej. Załóżmy na przykład, że tworzyłeś kosmiczną strzelankę. Musisz ciągle przerysowywać ekran, ponieważ obcy zostali wymazani. Miałbyś pewien licznik, który śledziłby liczbę pozostałych kosmitów, a kiedy ekran byłby aktualizowany, musiałbyś przejść przez pozostałych kosmitów i narysować ich obrazy na ekranie. Liczba kosmitów zmieniałaby się za każdym razem, gdy gracz wymazał innego. Ponieważ nie nauczyłeś się jeszcze rysować kosmitów na ekranie, oto prosty przykładowy program, który używa zmiennej pętli:
for i in range(1, numStars):
print '*',
>>> ====================== RESTART ======================
>>>
Ile gwiazdek chcesz? 5
* * * *
Program zapytał użytkownika, ile gwiazdek chciał, a następnie użył zmiennej pętli do wydrukowania tak wielu. Cóż prawie! Poprosiliśmy o pięć gwiazdek i tylko cztery! Ups, zapomnieliśmy, że pętla for zatrzymuje jedną krótką z drugiej liczby w zakresie. Musimy więc dodać 1 do wejścia użytkownika:
numStars = int(raw_input ("Ile gwiazdek chcesz? "))
for i in range(1, numStars + 1): <-Dodaje 1, więc jeśli poprosi o 5 gwiazdek, dostaje 5 gwiazdek
print '*',
Innym sposobem na zrobienie tego samego jest rozpoczęcie liczenia pętli od 0, zamiast 1. Oto jak to wyglądałoby:
numStars = int(raw_input ("Ile gwiazdek chcesz? "))
for i in range(0, numStars):
print '*',
>>> ====================== RESTART =====================
>>>
Ile gwiazdek chcesz? 5
* * * * *
Zmienne pętle zagnieżdżone
Wypróbujmy teraz zmienną pętlę zagnieżdżoną. To tylko pętla zagnieżdżona, w której jedna lub więcej pętli używa zmiennej w funkcji range(). Oto przykład:
Listing 12.2 Zmienna pętla zagnieżdżona
numLines = int(raw_input ('Ile linii gwiazdek chcesz? '))
numStars = int(raw_input (Ile gwiazdek na linię? '))
for line in range(0, numLines):
for star in range(0, numStars):
print '*',
print
Spróbuj uruchomić ten program, aby sprawdzić, czy ma to sens. Powinieneś zobaczyć coś takiego:
>>> ============================ RESTART ============================
>>>
Ile linii gwiazdek chcesz ? 3
Ile gwiazdek na linii? 5
*****
*****
*****
Pierwsze dwie linie pytają użytkownika, ile linii chce i ile gwiazdek w linii. Zapamiętuje odpowiedzi używając zmiennych numLines i numStars. Potem mamy dwie pętle:
• Wewnętrzna pętla (dla gwiazdy w zakresie (0, numStars) :) drukuje każdą gwiazdę i uruchamia się raz dla każdej gwiazdy na linii.
• Zewnętrzna pętla (dla linii w zakresie (0, numLines) :) działa raz dla każdej linii gwiazd.
Drugie polecenie drukowania jest potrzebne do rozpoczęcia nowej linii gwiazd. Gdybyśmy tego nie mieli, wszystkie gwiazdy byłyby drukowane w jednym wierszu z powodu przecinka w pierwszej instrukcji drukowania.
Możesz nawet mieć zagnieżdżone pętle zagnieżdżone (lub podwójnie zagnieżdżone pętle). Wyglądają tak
Listing 12.3 Bloki gwiazd z podwójnie zagnieżdżonymi pętlami
numBlocks = int(raw_input ('Ile bloków gwiazd chcesz? '))
numLines = int(raw_input ('Ile linii w każdym bloku? '))
numStars = int(raw_input ('Ile gwiazdek na linię? '))
for block in range(0, numBlocks):
for line in range(0, numLines):
for star in range(0, numStars):
print '*',
print
print
Oto wyjście:
>>> ======================= RESTART =======================
>>>
Ile bloków gwiazd chcesz? 3
Ile linii w każdym bloku? 4
Ile gwiazdek na linię ? 8
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
Mówimy, że pętla jest zagnieżdżona "na poziomie trzecim".
Jeszcze bardziej zagnieżdżone zmienne pętle
Następny listing pokazuje trudniejszą wersję programu z listingu 12.3.
Listing 12.4 Trudniejsza wersja bloków gwiazd
numBlocks = int(raw_input('Ile bloków gwiazdek chcesz? '))
for block in range(1, numBlocks + 1):
for line in range(1, block * 2 ):
for star in range(1, (block + line) * 2):
print '*',
print
print
Oto wyjście:
>>> ======================= RESTART =======================
>>>
Ile bloków gwiazdek chcesz ? 3
* * * *
* * * * *
* * * * * * *
* * * * * * * * *
* * * * * * *
* * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * * * * *
W listingu 12.4 zmienne pętli zewnętrznych pętli są używane do ustawiania zakresów dla pętli wewnętrznych. Więc zamiast każdego bloku mającego tę samą liczbę linii i każdą linię o tej samej liczbie gwiazd, różnią się za każdym razem w pętli. Możesz zagnieżdżać pętle tak głęboko, jak chcesz. Śledzenie tego, co się dzieje, może być trochę włochate, więc czasami pomaga wydrukować wartości zmiennych pętli, jak pokazano poniżej.
Listing 12.5 Drukowanie zmiennych pętli w zagnieżdżonych pętlach
numBlocks = int(raw_input(' Ile bloków gwiazdek chcesz ? '))
for block in range(1, numBlocks + 1):
print 'block = ', block
for line in range(1, block * 2 ):
for star in range(1, (block + line) * 2):
print '*',
print ' line = ', line, 'star = ', star
print
Oto rezultat programu:
>>> ======================= RESTART =======================
>>>
Ile bloków gwiazdek chcesz? 3
block = 1
* * * line = 1 star = 3
block = 2
* * * * * line = 1 star = 5
* * * * * * * line = 2 star = 7
* * * * * * * * * line = 3 star = 9
block = 3
* * * * * * * line = 1 star = 7
* * * * * * * * * line = 2 star = 9
* * * * * * * * * * * line = 3 star = 11
* * * * * * * * * * * * * line = 4 star = 13
* * * * * * * * * * * * * * * line = 5 star = 15
Wyświetlanie wartości zmiennych może pomóc w wielu sytuacjach - nie tylko w pętlach. Jest to jedna z najpopularniejszych metod debugowania.
Korzystanie z zagnieżdżonych pętli
Co więc możemy zrobić ze wszystkimi zagnieżdżonymi pętlami? Jedną z rzeczy, dla których są dobre, jest określenie wszystkich możliwych permutacji i kombinacji szeregu decyzji.
Permutacja to termin matematyczny, który oznacza unikalny sposób łączenia zestawu rzeczy. Połączenie oznacza coś bardzo podobnego. Różnica polega na tym, że w przypadku kombinacji kolejność nie ma znaczenia, ale z permutacją kolejność ma znaczenie. Gdybym poprosił cię o wybranie trzech liczb od 1 do 20, możesz wybrać
• 5, 8, 14
• 2, 12, 20
i tak dalej. Gdybyśmy próbowali stworzyć listę wszystkich permutacji trzy liczby od 1 do 20, te dwa byłyby osobnymi wpisami:
• 5, 8, 14
• 8, 5, 14
To dlatego, że z permutacjami kolejność, w jakiej one się znajdują pojawiają się sprawy. Jeśli zrobimy listę wszystkich kombinacji, wszystkie będą liczone jako pojedynczy wpis:
• 5, 8, 14
• 8, 5, 14
• 8, 14, 5
To dlatego, że porządek nie ma znaczenia dla kombinacji
Najlepszym sposobem na wyjaśnienie tego jest przykład. Wyobraźmy sobie, że prowadzimy stoisko z hot dogami podczas wiosennych targów w naszej szkole i chcemy zrobić plakat pokazujący, jak zamawiać wszystkie możliwe kombinacje hot doga, bułki, ketchupu, musztardy i cebuli według liczby. Musimy więc dowiedzieć się, jakie są wszystkie możliwe kombinacje. Jednym ze sposobów myślenia o tym problemie jest użycie czegoś, co nazywa się drzewem decyzyjnym. Następny rysunek przedstawia drzewo decyzyjne dla problemu hot dogów. Każdy punkt decyzji ma tylko dwie możliwości: Tak lub Nie. Każda inna ścieżka w dół drzewa opisuje inną kombinację części hot doga. Podświetlona ścieżka mówi "Tak" dla hot doga, "Nie" dla bułki, "Tak" dla musztardy i "Tak" dla ketchupu. Teraz użyjemy zagnieżdżonych pętli, aby wyświetlić listę wszystkich kombinacji - wszystkie ścieżki w drzewie decyzyjnym. Ponieważ istnieje pięć punktów decyzyjnych, w naszym drzewie decyzyjnym jest pięć poziomów, więc w naszym programie będzie pięć zagnieżdżonych pętli. Wpisz kod z poniższej listy w oknie edytora IDLE i zapisz go jako hotdog1.py.
Listing 12.6 Kombinacje hot dogów
print "\tDog \tBun \tKetchup\tMustard\tOnions"
count = 1
for dog in [0, 1]: <- pętla dog
for bun in [0, 1]: <- pętla bułka
for ketchup in [0, 1]: <- pętla ketchup
for mustard in [0, 1]: <- pętla musztarda
for onion in [0, 1]:
print "#", count, "\t",
print dog, "\t", bun, "\t", ketchup, "\t", <- pętla onion
print mustard, "\t", onion
count = count + 1
Widzisz, jak wszystkie pętle są jedno w drugim? Właśnie tak naprawdę są zagnieżdżone pętle - pętle wewnątrz innych pętli:
• Zewnętrzna pętla (dog) działa dwukrotnie.
• Pętla pętli działa dwukrotnie dla każdej iteracji pętli dog. Działa więc 2 x 2 = 4 razy.
• Pętla ketchupu działa dwukrotnie dla każdej iteracji pętli dog. Działa więc 2 x 2 x 2 = 8 razy.
I tak dalej.
Najgłębsza pętla (czyli najdalej w pętli onion) działa 2 x 2 x 2 x 2 x 2 = 32 razy. Obejmuje to wszystkie możliwe kombinacje. Tak więc są 32 możliwe kombinacje. Jeśli uruchomisz program z listingu 12.6, powinieneś otrzymać coś takiego:
>>> =========================== RESTART =================== ========
>>>
Dog : Bułka : Ketchup : Musztarda : Cebula
# 1 : 0 : 0 : 0 : 0 : 0
# 2 : 0 : 0 : 0 : 0 : 1
# 3 : 0 : 0 : 0 : 1 : 0
# 4 : 0 : 0 : 0 : 1 : 1
# 5 : 0 : 0 : 1 : 0 : 0
# 6 : 0 0 : 1 : 0 : 1
# 7 : 0 : 0 : 1 : 1 : 0
# 8 : 0 : 0 : 1 : 1 : 1
# 9 : 0 : 1 : 0 : 0 : 0
# 10 : 0 : 1 : 0 : 0 : 1
# 11 : 0 : 1 : 0 : 1 : 0
# 12 : 0 : 1 : 0 : 1 : 1
# 13 : 0 : 1 : 1 : 0 : 0
# 14 : 0 : 1 : 1 : 0 : 1
# 15 : 0 : 1 : 1 : 1 : 0
# 16 : 0 : 1 : 1 : 1 : 1
# 17 : 1 : 0 : 0 : 0 : 0
# 18 : 1 : 0 : 0 : 0 : 1
# 19 : 1 : 0 : 0 : 1 : 0
# 20 : 1 : 0 : 0 : 1 : 1
# 21 : 1 : 0 : 1 : 0 : 0
# 22 : 1 : 0 : 1 : 0 : 1
# 23 : 1 : 0 : 1 : 1 : 0
# 24 : 1 : 0 : 1 : 1 : 1
# 25 : 1 : 1 : 0 : 0 : 0
# 26 : 1 : 1 : 0 : 0 : 1
# 27 : 1 : 1 : 0 : 1 : 0
# 28 : 1 : 1 : 0 : : 1 1
# 29 : 1 : 1 : 1 : 0 : 0
# 30 : 1 : 1 : 1 : 0 : 1
# 31 : 1 : 1 : 1 : 1 : 0
# 32 : 1 : 1 : 1 : 1 : 1
Pięć zagnieżdżonych pętli przebiega przez wszystkie możliwe kombinacje dog, bułka, ketchupu, musztardy i cebuli. W listingu 12.6 użyliśmy znaku tabulacji do wyrównania wszystkiego. To są części. Nie rozmawialiśmy jeszcze o formatowaniu wyświetlania, ale jeśli chcesz dowiedzieć się więcej na ten temat, możesz rzucić okiem na Część 21. Użyliśmy zmiennej o nazwie count do numerowania każdej kombinacji. Na przykład hot doga z bułeczką i musztardą byłaby #27. Oczywiście niektóre z 32 kombinacji nie mają sensu. (Hot dog bez kok, ale z musztardą i ketchupem byłby trochę bałaganiarski.) Ale wiesz, co mówią: "Klient ma zawsze rację!"
Liczenie kalorii
Ponieważ w dzisiejszych czasach wszyscy martwią się odżywianiem, dodajmy w menu liczbę kalorii dla każdej kombinacji. (Możesz nie przejmować się kaloriami, ale założę się, że twoi rodzice to robią!) Pozwoli nam to wykorzystać niektóre umiejętności matematyczne Pythona, o których dowiedzieliśmy się w części trzeciej. Wiemy już, które elementy są w każdej kombinacji. Teraz potrzebujemy tylko kalorii dla każdego przedmiotu. Następnie możemy dodać je wszystkie w najbardziej wewnętrznej pętli. Oto kod, który określa liczbę kalorii w każdym elemencie:
dog_cal = 140
bun_cal = 120
mus_cal = 20
ket_cal = 80
cebula_cal = 40
Teraz musimy je tylko dodać. Wiemy, że w każdej kombinacji menu jest 0 lub 1 każdego elementu. Możemy więc pomnożyć ilość przez wieczny element kalorii, taki jak ten:
tot_cal = ((dog * dog_cal) + (bun * bun_cal) + \
(musztarda * mus_cal) + (ketchup * ket_cal) +\
(cebula * cebula_cal))
Ponieważ kolejność operacji jest najpierw mnożeniem, a potem dodawanie, tak naprawdę nie musiałem umieszczać nawiasów. Po prostu umieściłem je, aby łatwiej było zobaczyć, co się dzieje.
Długie linie kodu
Czy zauważyłeś znaki odwrotnego ukośnika () na końcu wierszy poprzedniego kodu? Jeśli masz długie wyrażenie, które nie zmieści się w jednej linii, możesz użyć znaku odwrotnego ukośnika, aby powiedzieć Pythonowi: "Ta linia nie jest ukończona. Traktuj wszystko, co znajduje się w następnym wierszu, jakby było częścią tej linii. "Tutaj użyliśmy dwóch odwrotnych ukośników, aby podzielić naszą długą linię na trzy krótkie linie. Backslash nazywany jest znakiem kontynuacji linii, a posiada je kilka języków programowania. Możesz także umieścić dodatkowy zestaw nawiasów wokół całego wyrażenia, a następnie możesz podzielić swoje wyrażenie na wiele wierszy bez użycia odwrotnego ukośnika, jak poniżej:
tot_cal = ((dog * dog_cal) + (bun * bun_cal) +
(musztarda * mus_cal) + (ketchup * ket_cal) +
(cebula * cebula_cal))
Łącząc to wszystko, nowa wersja programu Hot Dog z licznikiem kalorii jest pokazana dalej.
Listing 12.7 Program Hot Dog z licznikiem kalorii
dog_cal = 140
bun_cal = 120
ket_cal = 80
mus_cal = 20
<
br>
onion_cal = 40
print "\tDog \tBun \tKetchup\tMustard\tOnions\tCalories"
count = 1
for dog in [0, 1]:
for bun in [0, 1]:
for ketchup in [0, 1]:
for mustard in [0, 1]:
for onion in [0, 1]:
total_cal = (bun * bun_cal)+(dog * dog_cal) + \
(ketchup * ket_cal)+(mustard * mus_cal) + \
(onion * onion_cal)
print "#", count, "\t",
print dog, "\t", bun, "\t", ketchup, "\t",
print mustard, "\t", onion,
print "\t", total_cal
count = count + 1
Spróbuj uruchomić program w listingu 12.7 w IDLE. Wynik powinien wyglądać następująco:
>>> =========================== RESTART ===========================
>>>
Dog : Bułka : Ketchup : Musztarda : Cebula : Kalorie
# 1 : 0 : 0 : 0 : 0 : 0 : 0
# 2 : 0 : 0 : 0 : 0 : 1 : 40
# 3 : 0 : 0 : 0 : 1 : 0 : 20
# 4 : 0 : 0 0 : 1 : 1 : 60
# 5 : 0 : 0 1 : 0 : 0 : 80
# 6 : 0 : 0 : 1 : 0 : 1 : 120
# 7 : 0 : 0 1 : 1 : 0 : 100
# 8 : 0 : 0 1 : 1 : 1 : 140
# 9 : 0 : 1 : 0 : 0 : 0 : 120
# 10 : 0 : 1 : 0 : 0 : 1 : 160
# 11 : 0 : 1 : 0 : 1 : 0 : 140
# 12 : 0 : 1 : 0 : 1 : 1 : 180
# 13 : 0 : 1 : 1 : 0 : 0 : 200
# 14 : 0 : 1 : 1 : 0 : 1 : 240
# 15 v 0 : 1 : 1 : 1 : 0 : 220
# 16 : 0 : 1 : 1 : 1 : 1 : 260
# 17 : 1 : 0 : 0 : 0 : 0 : 140
# 18 : 1 : 0 : 0 : 0 : 1 : 180
# 19 : 1 : 0 : 0 : 1 : 0 : 160
# 20 : 1 : 0 : 0 : 1 : 1 : 200
# 21 : 1 : 0 : 1 : 0 : 0 : 220
# 22 : 1 : 0 : 1 : 0 : 1 : 260
# 23 : 1 : 0 : 1 : 1 : 0 : 240
# 24 : 1 : 0 : 1 : 1 : 1 : 280
# 25 : 1 : 1 : 0 : 0 : 0 : 260
# 26 : 1 : 1 : 0 : 0 : 1 : 300
# 27 : 1 : 1 : 0 : 1 : 0 : 280
# 28 : 1 : 1 : 0 : 1 : 1 : 320
# 29 : 1 : 1 : 1 : 0 : 0 : 340
# 30 : 1 : 1 : 1 : 0 : 1 : 380
# 31 : 1 : 1 : 1 : 1 : 0 : 360
# 32 : 1 : 1 : 1 : 1 : 1 : 400
Wyobraź sobie, jak żmudne byłoby ręczne obliczanie kalorii dla wszystkich tych kombinacji, nawet gdybyś miał kalkulator do matematyki. Bardziej zabawnie jest napisać program, który pomoże ci to zrozumieć. Zapętlanie i odrobina matematyki w Pythonie sprawiają, że jest to proste!
Czego się nauczyłeś?
• Zagnieżdżone pętle
• Zmienne pętle
• Permutacje i kombinacje
• Drzewa decyzyjne
Sprawdź swoją wiedzę
1 Jak utworzyć zmienną pętlę w Pythonie?
2 Jak utworzyć pętlę zagnieżdżoną w Pythonie?
3 Jaka jest łączna liczba gwiazdek wydrukowanych przez następujący kod?
for i in range(5):
for j in range(3):
print '*',
print
4. Jak będzie wyglądał wynik z kodu w pytaniu 3?
5 Jeśli drzewo decyzyjne ma cztery poziomy i dwie możliwości wyboru na poziomie, ile jest możliwych wyborów (ścieżek przez drzewo decyzyjne)?
Wypróbuj to
1 Zapamiętaj program licznika czasu, który stworzyliśmy w części 8? Oto, aby odświeżyć pamięć:
import time
for i in range (10, 0, -1):
print i
time.sleep(1)
print "BLAST OFF!"
Zmodyfikuj program, aby używał pętli zmiennej. Program powinien zapytać użytkownika, gdzie powinno się rozpocząć odliczanie, w ten sposób:
Licznik czasu: Ile sekund? 4
4
3
2
1
BLAST OFF!
2 Weź program, który napisałeś w pytaniu # 1, i wydrukuj wiersz gwiazd obok każdego numeru, tak jak poniżej:
Licznik czasu: Ile sekund? 4
4 * * * *
3 * * *
2 * *
1 *
BLAST OFF!
(Podpowiedź: Prawdopodobnie musisz użyć pętli zagnieżdżonej.)
Widzieliśmy, że Python może przechowywać rzeczy w swojej pamięci i pobierać je, używając nazw. Do tej pory mamy zapisane łańcuchy i liczby (zarówno liczby całkowite, jak i zmiennoprzecinkowe). Czasami przydatne jest przechowywanie kilku rzeczy razem w rodzaju grupy lub kolekcji. Wtedy możesz robić rzeczy naraz i łatwiej śledzić grupy rzeczy. Jednym z rodzajów kolekcji jest lista, a inny to słownik. W tej części dowiemy się o listach i słownikach - czym są i jak je tworzyć, modyfikować i używać. Listy są bardzo przydatne i używane w wielu, wielu programach. Wiele z nich wykorzystamy w przykładach w nadchodzących rozdziałach, kiedy zaczniemy robić grafikę i programowanie gier, ponieważ wiele obiektów graficznych w grze jest często przechowywanych na liście.
Co to jest lista?
Jeśli poprosiłem cię o sporządzenie listy członków twojej rodziny, możesz napisać coś takiego:
• Mama
• Tato
• Junior
• Niemowlę
W Pythonie napisałeś to:
family = ['Mama', 'Tato', 'Junior', 'Niemowlę']
Gdybym poprosił cię o zapisanie szczęśliwych liczb, możesz napisać to:
2,7,14,26,30
W Pythonie napisałeś to:
luckyNumbers = [2, 7, 14, 26, 30]
Zarówno rodzina, jak i luckyNumbers są przykładami list Pythona, a poszczególne elementy wewnątrz list nazywane są elementami. Jak widać, listy w Pythonie nie różnią się zbytnio od list tworzonych w codziennym życiu. Listy używają nawiasów kwadratowych, aby pokazać, gdzie zaczyna się i kończy lista, i używają przecinków, aby oddzielić elementy wewnątrz.
Tworzenie listy
Zarówno rodzina, jak i luckyNumbers są zmiennymi. Powiedzieliśmy wcześniej, że do zmiennych można przypisać różne rodzaje wartości. Użyliśmy ich już do liczb i łańcuchów, a także można im przypisać listę. Tworzysz listę tak, jakbyś tworzył dowolną inną zmienną - przypisując coś do niej, tak jak w przypadku luckyNumbers. Możesz także utworzyć pustą listę, taką jak ta:
newList = []
W nawiasach kwadratowych nie ma żadnych elementów, więc lista jest pusta. Ale co to jest pusta lista? Dlaczego chcesz go utworzyć? Cóż, dość często nie wiecie wcześniej, co będzie na liście. Nie wiesz, ile będzie w nim przedmiotów lub jakie będą te przedmioty. Po prostu wiesz, że będziesz ich używać do przechowywania listy. Gdy masz pustą listę, program może dodawać do niej rzeczy. Więc jak to robisz?
Dodawanie rzeczy do listy
Aby dodać rzeczy do listy, użyj append(). Wypróbuj to w trybie interaktywnym:
>>> friends = [] <- Stwórz nową, pustą listę
>>> friends.append ('Dawid') <- Dodaje element "Dawid" do listy
>>> print friends
Otrzymasz ten wynik:
['Dawid']
Spróbuj dodać inny element:
>>> friends.append ('Maryśka')
>>> print znajomych
['Dawid', 'Maryśka']
Pamiętaj, że musisz utworzyć listę (pustą lub nie), zanim zaczniesz dodawać do niej rzeczy. To tak, jakbyś robił ciasto: nie możesz po prostu wlewać składników razem - musisz najpierw wylać miskę. W przeciwnym razie skończysz z różnymi rzeczami!
Co to jest kropka?
Dlaczego użyliśmy kropki między friends a append()? Cóż, to zaczyna wpadać w całkiem spory temat: obiekty. Dowiesz się więcej o obiektach w Części 14, ale na razie jest to proste wyjaśnienie. Wiele rzeczy w Pythonie to obiekty. Aby zrobić coś z obiektem, potrzebujesz nazwy obiektu (nazwy zmiennej), następnie kropki, a następnie wszystkiego, co chcesz zrobić z obiektem. Aby dodać coś do listy znajomych, napisz to:
friends.append (coś)
Listy mogą pomieścić wszystko
Listy mogą zawierać dowolne dane, które Python może przechowywać. Obejmuje to liczby, łańcuchy, obiekty, a nawet inne listy. Elementy na liście nie muszą być tego samego typu ani rodzaju. Oznacza to, że pojedyncza lista może na przykład zawierać zarówno liczby, jak i łańcuchy. Lista może wyglądać tak:
my_list = [5, 10, 23.76, "Hello", myTeacher, 7, another_list]
Zróbmy nową listę z czymś prostym, takim jak litery alfabetu, aby łatwiej było zobaczyć, co się dzieje, gdy dowiadujemy się o listach. Wpisz to w trybie interaktywnym:
>>> litery = ['a', 'b', 'c', 'd', 'e']
Pobieranie elementów z listy
Możesz pobrać pojedyncze elementy z listy według numeru indeksu. Indeks listy zaczyna się od 0, więc pierwszym elementem na naszej liście są litery [0]:
>>> print letters[0]
a
Spróbujmy innego:
>>> print letters[3]
d
Dlaczego indeks zaczyna się od 0, a nie 1?
To pytanie zadawało wielu programistów, inżynierów i informatyków, odkąd wynaleziono komputery. Nie zamierzam wchodzić w środek tego argumentu, powiedzmy więc, że odpowiedź brzmi "ponieważ" i przejdź dalej…
Okay okay! Spójrz na "CO DZIAŁA W NIM?", Aby zobaczyć wyjaśnienie, dlaczego indeks zaczyna się od 0 zamiast 1.
Pamiętaj, że komputery używają cyfr binarnych lub bitów do przechowywania wszystkiego. W dawnych czasach te bity były drogie. Każdy z nich musiał być ręcznie zbierany i przenoszony przez osła z plantacji bitów
tylko żartowałem. Ale były drogie. Liczenie binarne rozpoczyna się od 0. Więc, aby maksymalnie efektywnie wykorzystywać bity i nie marnować żadnych, rzeczy takie jak lokalizacje pamięci i indeksy list zaczynają się od 0.
Szybko przyzwyczaisz się do indeksów zaczynających się od 0. To bardzo popularne w programowaniu.
Indeks oznacza pozycję czegoś. Liczba mnoga indeksu to indeksy (ale niektóre osoby używają indeksów jako liczby mnogiej dla indeksu). Jeśli jesteś czwartą osobą w kolejce, twój indeks w wierszu to 4. Ale jeśli jesteś czwartą osobą na liście Pythona, twój indeks wynosi 3, ponieważ indeksy listy Pythona zaczynają się od 0!
"Krojenie" listy
Możesz także użyć indeksów, aby uzyskać więcej niż jedną pozycję z listy naraz. Nazywa się to przecinaniem listy:
>>> print litery [1: 4]
['b', 'c', 'd']
Podobnie jak w przypadku range) w naszych pętlach for, krojenie pobiera elementy zaczynające się od pierwszego indeksu, ale zatrzymuje się przed przejściem do drugiego indeksu. Dlatego w poprzednim przykładzie otrzymaliśmy trzy elementy, nie cztery. Jednym ze sposobów na zapamiętanie tego jest to, że liczba przedmiotów, które otrzymujesz, jest zawsze różnicą między dwoma numerami indeksu. (4 - 1 = 3, a mamy trzy elementy z powrotem.) Oto jeszcze jedna rzecz, o której należy pamiętać przy krojeniu listy: To, co otrzymasz po pocięciu listy, to kolejna (zwykle mniejsza) lista. Ta mniejsza lista jest nazywana plasterkiem oryginalnej listy. Oryginalna lista nie uległa zmianie. Kawałek jest częściową kopią oryginału. Spójrz na różnicę tutaj:
>>> print litery [1]
b
>>> print litery [1: 2]
['b']
W pierwszym przypadku otrzymaliśmy pozycje. W drugim przypadku otrzymaliśmy listę zawierającą pozycję. To subtelna różnica, ale musisz o tym wiedzieć. W pierwszym przypadku użyliśmy pojedynczego indeksu, aby uzyskać jeden element z listy. W drugim przypadku użyliśmy notacji plasterka, aby uzyskać jeden element listy. Aby naprawdę zobaczyć różnicę, spróbuj tego:
>>> print type (litery [1])
>>> print type (litery [1: 2])
Wyświetlenie typu każdego z nich wskazuje na pewno, że w jednym przypadku otrzymasz pojedynczy element (w tym przypadku łańcuch), a w innym przypadku otrzymasz listę. Mniejsza lista, którą otrzymasz po pocięciu listy, to kopia elementów z oryginalnej listy. Oznacza to, że możesz go zmienić, a oryginalna lista nie zostanie zmieniona.
Skrócony skrót
Istnieje kilka skrótów, które można wykonać podczas używania plasterków. Nie oszczędzają na pisaniu, ale programiści są leniwymi grupami, więc często używają skrótów. Chcę, żebyś wiedział, jakie są skróty, abyś mógł je rozpoznać, gdy zobaczysz je w kodzie innych ludzi i zrozumiesz, co się dzieje. To ważne, ponieważ przeglądanie kodu innych ludzi i próba zrozumienia go to dobry sposób na nauczenie się nowego języka programowania lub ogólnie programowania. Jeśli żądany plasterek zawiera początek listy, skrótem jest użycie dwukropka, po którym następuje liczba elementów, które chcesz, w ten sposób:
>>> print litery [: 2]
['a', 'b']
Zauważ, że przed dwukropkiem nie ma numeru. To da ci wszystko, od początku listy, aż do (ale nie włączając) podanego indeksu. Możesz zrobić coś podobnego, aby uzyskać koniec listy:
>>> print litery [2:]
['c', 'd', 'e']
Użycie liczby, po której następuje dwukropek, daje wszystko, od indeksu określonego na końcu listy. Jeśli nie umieścisz żadnych liczb i użyjesz dwukropka, otrzymasz całą listę:
>>> print litery [:]
['a', 'b', 'c', 'd', 'e']
Pamiętasz, jak powiedziałem, że plasterki robią kopię oryginału? Więc litery [:] tworzą kopię całej listy. Jest to przydatne, jeśli chcesz dokonać pewnych zmian na liście, ale zachować oryginał bez zmian.
Modyfikowanie elementów
Możesz użyć indeksu, aby zmienić jeden z elementów listy:
>>> print letters
['a', 'b', 'c', 'd', 'e']
>>> letters[2] = 'z'
>>> print letters
['a', 'b', 'z', 'd', 'e']
Ale nie możesz użyć indeksu, aby dodać nowe elementy do listy. W tej chwili na liście znajduje się pięć elementów, z indeksami od 0 do 4. Więc nie możesz zrobić czegoś takiego:
letters [5] = 'f'
To by nie zadziałało. (Spróbuj, jeśli chcesz.) To tak, jakby próbować zmienić coś, czego jeszcze nie ma. Aby dodać elementy do listy, musisz zrobić coś innego, a to jest miejsce, do którego idziemy dalej. Ale zanim to zrobimy, zmieńmy naszą listę z powrotem na taką, jaka była:
>>> letters[2] = 'c'
>>> print letters
['a', 'b', 'c', 'd', 'e']
Inne sposoby dodawania do listy
Widziałeś już, jak dodawać rzeczy do listy za pomocą append(). Ale są też inne sposoby. W rzeczywistości istnieją trzy metody dodawania rzeczy do listy - append(), extend() i insert():
• append() dodaje jeden element na końcu listy.
• extend() dodaje wiele elementów na końcu listy.
• insert() dodaje jeden element gdzieś na liście, niekoniecznie na końcu. Mówisz, gdzie dodać element.
Dodawanie do końca: append()
Widziałeś już, jak działa append(). Dodaje jeden element na końcu listy:
>>> letters.append('n')
>>> print letters
['a', 'b', 'c', 'd', 'e', 'n']
Dodajmy jeszcze jedno:
>>> letters.append('g')
>>> print letters
['a', 'b', 'c', 'd', 'e', 'n', 'g']
Zauważ, że litery nie są w porządku. To dlatego, że append() dodaje element na końcu listy. Jeśli chcesz, aby elementy były w porządku, musisz je posortować. Wkrótce przejdziemy do sortowania.
Rozszerzenie listy: extend()
extend() dodaje kilka elementów na końcu listy:
>>> letters.extend(['p', 'q', 'r'])
>>> print letters
['a', 'b', 'c', 'd', 'e', 'n', 'g', 'p', 'q', 'r']
Zauważ, że w nawiasach okrągłych metody extend() znajduje się lista. Lista ma nawiasy kwadratowe, więc w przypadku extend() możesz mieć nawiasy okrągłe i kwadratowe. Wszystko na liście, którą podasz do extend() zostanie dodane na końcu oryginalnej listy.
Wstawianie elementu: insert()
insert() dodaje pojedynczy element gdzieś na liście. Mówisz, na jakiej pozycji na liście chcesz dodać element:
>>> letters.insert(2, 'z')
>>> print letters
['a', 'b', 'z', 'c', 'd', 'e', 'n', 'g', 'p', 'q', 'r']
Tutaj dodaliśmy literę z w indeksie 2. Indeks 2 to trzecia pozycja na liście (ponieważ indeksy zaczynają się od 0). Litera, która kiedyś znajdowała się na trzeciej pozycji, c została przeniesina o jedno miejsce, do czwartej pozycji. Każda inna pozycja na liście również została przesunięta o jedną pozycję. Różnica między append() i extend() Czasami append() i extend() wyglądają bardzo podobnie, ale robią różne rzeczy. Wróćmy do naszej oryginalnej listy. Najpierw spróbuj użyć extend(), aby dodać trzy elementy:
>>> letters = ['a','b','c','d','e']
>>> letters.extend(['f', 'g', 'h'])
>>> print letters
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Teraz spróbujemy użyć append(), aby zrobić to samo:
>>> letters = ['a', 'b', 'c', 'd', 'e']
>>> letters.append(['f', 'g', 'h'])
>>> print letters
['a', 'b', 'c', 'd', 'e', ['f', 'g', 'h']]
Co tu się stało? Powiedzieliśmy wcześniej, że append() dodaje jeden element do listy. W jaki sposób dodano trzy? To nie było to. Dodał jeden element, który jest kolejną listą zawierającą trzy elementy. Dlatego na naszej liście mamy dodatkowy zestaw nawiasów kwadratowych. Pamiętaj, że lista może pomieścić wszystko, w tym inne listy. Właśnie mamy insert() który działa tak samo jak append(), z tym wyjątkiem, że mówisz, gdzie umieścić nowy element. append() zawsze umieszcza go na końcu.
Usuwanie z listy
Jak usunąć pozycje z listy? Istnieją trzy sposoby: remove(), del i pop().
Usuwanie za pomocą remove ()
remove() usuwa wybrany element z listy i wyrzuca go:
>>> letters = ['a', 'b', 'c', 'd', 'e']
>>> letters.remove('c')
>>> print letters
['a', 'b', 'd', 'e']
Nie musisz wiedzieć, gdzie na liście znajduje się przedmiot. Musisz tylko wiedzieć, że gdzieś tam jest. Jeśli spróbujesz usunąć coś, czego nie ma na liście, pojawi się błąd:
>>> letters.remove('f')
Traceback (most recent call last):
File "< pyshell#32 >", line 1, in < module >
letters.remove('f')
ValueError: list.remove(x): x not in list
Jak więc dowiedzieć się, czy lista zawiera określony element? Po pierwsze, spójrzmy na inne sposoby usunięcia czegoś z listy.
Usuwanie za pomocą del
del umożliwia usunięcie elementu z listy za pomocą jego indeksu, takiego jak ten:
>>> letters = ['a', 'b', 'c', 'd', 'e']
>>> del letters[3]
>>> print letters
['a', 'b', 'c', 'e']
Tutaj usunęliśmy czwarty element (indeks 3), który był literą d.
Usuwanie za pomocą pop()
pop () usuwa ostatni element z listy i zwraca go z powrotem. Oznacza to, że możesz przypisać mu nazwę, taką jak ta:
>>> letters = ['a', 'b', 'c', 'd', 'e']
>>> lastLetter = letters.pop()
>>> print letters
['a', 'b', 'c', 'd']
>>> print lastLetter
e
Możesz także użyć pop () z indeksem, takim jak ten:
>>> letters = ['a', 'b', 'c', 'd', 'e']
>>> second = letters.pop(1)
>>> print second
b
>>> print letters
['a', 'c', 'd', 'e']
Tutaj pojawił się druga litera (indeks 1), którą było b. Pozycja, która wyskoczyła, została przypisana do drugiego i został również usunięty z liter. Z pustymi nawiasami, pop() daje ci ostatni element i usuwa go z listy. Jeśli umieścisz liczbę w nawiasach, pop(n) da ci n element w tym indeksie i usunie go z listy.
Wyszukiwanie na liście
Kiedy znajdziesz kilka pozycji na liście, jak je znajdziesz? Dwie rzeczy, które często musisz zrobić z listą, to
• Dowiedz się, czy element znajduje się na liście, czy nie
• Dowiedz się, gdzie element znajduje się na liście (jego indeks)
Słowo kluczowe in
Aby dowiedzieć się, czy coś znajduje się na liście, używasz słowa kluczowego in, jak poniżej:
if 'a' in letters:
print "found 'a' in letters"
else:
print "didn't find 'a' in letters"
Część "a" in letters to wyrażenie boolowskie lub logiczne. Zwróci wartość True, jeśli a znajduje się na liście, i False w przeciwnym razie Boolean to rodzaj arytmetyki, która używa tylko dwóch wartości: 1 i 0 lub true i false. Została wymyślona przez matematyka George′a Boole′a i jest używany przy łączeniu warunków prawdziwych i fałszywych (reprezentowanych przez 1 i 0) razem z and, or, i not, jak widzieliśmy w części 7.
Możesz spróbować tego w trybie interaktywnym:
>>> 'a' in letters
True
>>> 's' in letters
False
To mówi nam, że lista o nazwie litery ma element a, ale nie ma elementu s. Więc a jest na liście, a s nie ma na liście. Teraz możesz połączyć in i remove() i napisać coś, co nie spowoduje błędu, nawet jeśli wartość nie znajduje się na liście:
if 'a' in letters:
letters.remove('a')
Ten kod usuwa tylko wartość z listy, jeśli wartość znajduje się na liście.
Znajdowanie indeksu
Aby dowiedzieć się, gdzie na liście znajduje się element, używasz metody index(), takiej jak ta:
>>> letters = ['a', 'b', 'c', 'd', 'e']
>>> print letters.index('d')
3
Wiemy więc, że d ma indeks 3, co oznacza, że jest czwartym elementem na liście. Podobnie jak remove (), index() wyświetli błąd, jeśli wartość nie zostanie znaleziona na liście, więc dobrym pomysłem jest użycie jej w:
if 'd' in letters:
print letters.index('d')
Zapętlanie listy
Kiedy po raz pierwszy rozmawialiśmy o pętlach, widzieliście, że pętle przechodzą przez listę wartości. Dowiedziałeś się także o funkcji range() i użyłeś jej jako skrótu do generowania list liczb dla twoich pętli. Widziałeś, że range() daje listę liczb. Ale pętla może przechodzić przez dowolną listę - nie musi to być lista liczb. Powiedzmy, że chcieliśmy wydrukować naszą listę liter z jednym elementem w każdym wierszu. Moglibyśmy zrobić coś takiego:
>>> letters = ['a', 'b', 'c', 'd', 'e']
>>> for letter in letters:
print letter
a
b
c
d
e
Tym razem naszą zmienną pętli jest litera. (Wcześniej używaliśmy zmiennych pętlowych, takich jak looper lub i, j, i k.) Pętla iteruje (pętle) przez wszystkie wartości na liście, a za każdym razem bieżący element jest zapisywany w zmiennej pętli, litera, a następnie zostanie wyświetlony.
Listy sortowania
Listy są uporządkowanym typem kolekcji. Oznacza to, że elementy na liście mają określoną kolejność, a każda z nich ma miejsce (indeks). Gdy umieścisz elementy na liście w określonej kolejności, pozostają w tej kolejności, chyba że zmienisz listę za pomocą insert(), append(), remove() lub pop(). Ale to kolejność może nie być taka, jaką chcesz. Możesz chcieć posortować listę przed jej użyciem. Aby posortować listę, należy użyć metody sort ():
>>> letters = ['d', 'a', 'e', 'c', 'b']
>>> print letters
['d', 'a', 'e', 'c', 'b']
>>> letters.sort()
>>> print letters
['a', 'b', 'c', 'd', 'e']
sort() automatycznie sortuje ciągi alfabetycznie i liczbowo, od najmniejszego do największego. Ważne jest, aby wiedzieć, że sort () modyfikuje listę na miejscu. Oznacza to, że zmienia oryginalną listę, którą mu dajesz. Nie tworzy nowej, posortowanej listy. Oznacza to, że nie możesz tego zrobić:
>>> print letters.sort()
Jeśli to zrobisz, otrzymasz "Brak". Musisz to zrobić w dwóch krokach:
>>> letters.sort()
>>> print letters
Sortowanie w odwrotnej kolejności
Istnieją dwa sposoby sortowania listy w odwrotnej kolejności. Jednym z nich jest posortowanie listy w normalny sposób, a następnie odwrócenie posortowanej listy w następujący sposób:
>>> letters = ['d', 'a', 'e', 'c', 'b']
>>> letters.sort()
>>> print letters
['a', 'b', 'c', 'd', 'e']
>>> letters.reverse()
>>> print letters
['e', 'd', 'c', 'b', 'a']
Tutaj zobaczyłeś nową metodę listy o nazwie reverse(), która odwraca kolejność elementów na liście. Innym sposobem jest dodanie parametru do sort(), aby posortować go w porządku malejącym (od największego do najmniejszego):
>>> letters = ['d', 'a', 'e', 'c', 'b']
>>> letters.sort (reverse = True)
>>> print letters
['e', 'd', 'c', 'b', 'a']
Parametr nazywa się reverse i robi dokładnie to, czego można oczekiwać - powoduje sortowanie listy w odwrotnej kolejności. Pamiętaj, że wszystkie sortowania i cofania, o których właśnie mówiliśmy, modyfikują oryginalną listę. Oznacza to, że oryginalne zamówienie zostało utracone. Jeśli chcesz zachować oryginalną kolejność i posortować kopię listy, możesz użyć notacji plasterka, o której mówiliśmy wcześniej w tej części, aby kopia-inna lista była równa oryginałowi:
>>> original_list = ['Tomek', 'Jacek', 'Sara', 'Fredek']
>>> new_list = original_list[:]
>>> new_list.sort()
>>> print original_list
['Tomek', 'Jacek', 'Sara', 'Fredek']
>>> print new_list
['Tomek', 'Jacek', 'Sara', 'Fredek']
Jeśli pamiętasz sposób, w jaki mówiliśmy o nazwach i zmiennych, mówiliśmy, że kiedy robisz coś takiego jak nazwa1 = nazwa2, po prostu tworzysz nową nazwę tego samego. Pamiętasz?
Tak więc nadanie czemuś innej nazwy po prostu dodaje nowy znacznik do tej samej rzeczy. Na przykład obie listy new_list i original_list odnoszą się do tej samej listy. Możesz zmienić listę (na przykład, możesz ją sortować), używając dowolnej nazwy. Ale wciąż jest tylko jedna lista. To wygląda tak:
original = [5,2,3,1,4] original -> 5,2,3,4,1
new = original original-> 5,2,3,4,1
new -> 5,2,3,4,1
new_sort () original -> 1,2,3,4,5
new -> 1,2,3,4,5
Posortowaliśmy new, ale original też została posortowana, ponieważ new i originalto dwie różne nazwy dla tej samej listy. Nie ma dwóch różnych list
Możesz oczywiście przenieść tag new na zupełnie nową listę, taką jak ta:
original = [5,2,3,1,4] original -> 5,2,3,4,1
new = original original-> 5,2,3,4,1
new -> 5,2,3,4,1
new = [6,7,8,9,10] original -> 5,2,3,4,1
new -> 6,7,8,9,10
To samo robiliśmy z ciągami i liczbami w części 2.
Oznacza to, że jeśli naprawdę chcesz zrobić kopię listy, musisz zrobić coś innego niż nowy = oryginał. Najłatwiej to zrobić, używając notacji plasterków, tak jak powyżej:
new = original [:]. Oznacza to "skopiuj wszystko z listy, od pierwszego do ostatniego elementu". Otrzymasz to:
original = [5,2,3,1,4] original -> 5,2,3,4,1
new = original [:] new-> 5,2,3,4,1
Istnieją teraz dwie oddzielne listy. Zrobiliśmy kopię oryginału i nazwaliśmy go nowym. Jeśli teraz posortujemy jedną listę, druga nie zostanie posortowana.
Inny sposób sortowania - sorted()
Istnieje inny sposób uzyskania posortowanej kopii listy bez zmiany kolejności oryginalnej listy. W tym celu Python ma funkcję o nazwie sorted (). Działa tak:
>>> original = [5, 2, 3, 1, 4]
>>> newer = sorted(original)
>>> print original
[5, 2, 3, 1, 4]
>>> print newer
[1, 2, 3, 4, 5]
Funkcja soted() daje posortowaną kopię oryginalnej listy.
Zmienne i niezmienne
Jeśli pamiętasz z Części 2, powiedzieliśmy, że w rzeczywistości nie możesz zmienić liczby lub ciągu, możesz tylko zmienić numer lub łańcuch, do którego przypisano nazwę (innymi słowy, przesuń znacznik). Ale listy są jednym z typów w Pythonie, które można zmienić. Jak widziałeś, listy mogą zawierać elementy dodane lub usunięte, a elementy mogą być sortowane lub odwracane. Te dwa różne rodzaje zmiennych nazywane są zmiennymi i niezmiennymi. Mutable oznacza po prostu "zdolny do zmiany" lub "zmienny". Niezmienny oznacza "nie można zmienić" lub "niezmienny". W Pythonie liczby i łańcuchy są niezmienne (nie można ich zmienić), a listy są zmienne (można je zmienić ).
Krotka-niezmienna lista
Są chwile, kiedy nie chcesz, aby lista była zmienna. Czy w Pythonie istnieje niezmienny rodzaj listy? Odpowiedź brzmi tak. Istnieje typ zwany krotką, który jest dokładnie tą, niezmienną (niezmienną) listą. Robisz to w ten sposób:
my_tuple = ("czerwony", "zielony", "niebieski")
Używasz nawiasów okrągłych zamiast kwadratowych, które wymieniają użycie.
Ponieważ krotki są niezmienne, nie można robić takich rzeczy, jak sortowanie ich, dołączanie lub usuwanie elementów. Po utworzeniu krotki z zestawem przedmiotów pozostaje ona w ten sposób.
Listy list: tabele danych
Myśląc o tym, jak dane są przechowywane w programie, warto je wizualizować.
Zmienna ma jedną wartość. :
Lista jest jak rząd wartości połączonych razem. :
Czasami potrzebna jest tabela z wierszami i kolumnami.:
Jak zapisać tabelę danych? Wiesz już, że możesz stworzyć listę do przechowywania kilku przedmiotów. Możemy umieścić oceny każdego ucznia na liście w następujący sposób:
>>> janMarks = [55, 63, 77, 81]
>>> tomekMarks = [65, 61, 67, 72]
>>> beataMarks = [97, 95, 92, 88]
Lub moglibyśmy użyć listy dla każdego tematu, takiego jak ten:
>>> mathMarks = [55, 65, 97]
>>> scienceMarks = [63, 61, 95]
>>> readingMarks = [77, 67, 92]
>>> spellingMarks = [81, 72, 88]
Ale możesz zebrać wszystkie dane w jedną strukturę danych.
Struktura danych to sposób zbierania, przechowywania lub reprezentowania danych w programie. Struktury danych mogą zawierać zmienne, listy i inne rzeczy, o których jeszcze nie rozmawialiśmy. Termin struktura danych naprawdę odnosi się do sposobu zorganizowania danych w programie.
Aby stworzyć pojedynczą strukturę danych dla naszych znaków klas, moglibyśmy zrobić coś takiego:
>>> classMarks = [janMarks, tomekMarks, beataMarks]
>>> print classMarks
[[55, 63, 77, 81], [65, 61, 67, 72], [97, 95, 92, 88]]
Daje nam to listę przedmiotów, z których każdy jest listą. Stworzyliśmy listę list. Każdy z elementów na liście classMarks jest listą. Moglibyśmy także utworzyć bezpośrednio klasy klasy, bez wcześniejszego tworzenia janMarks, tomekMarks i beataMarks, w ten sposób:
>>> classMarks = [ [55,63,77,81], [65,61,67,72], [97,95,92,88] ]
>>> print classMarks
[[55, 63, 77, 81], [65, 61, 67, 72], [97, 95, 92, 88]]
Spróbujmy teraz wyświetlić naszą strukturę danych. classMarks ma trzy elementy, po jednym dla każdego ucznia. Możemy więc po prostu przejść przez używając in:
>>> for studentMarks in classMarks:
print studentMarks
[55, 63, 77, 81]
[65, 61, 67, 72]
[97, 95, 92, 88]
Tutaj zapętliliśmy listę o nazwie classMarks. Zmienna pętli to studentMarks. Za każdym razem w pętli drukujemy jedną pozycję na liście. Ten jeden przedmiot jest znakiem dla jednego ucznia, który sam jest listą. (Stworzyliśmy listę uczniów powyżej.) Zauważ, że wygląda to bardzo podobnie do tabeli na poprzedniej stronie. Dlatego stworzyliśmy strukturę danych, aby przechowywać wszystkie nasze dane w jednym miejscu.
Uzyskanie pojedynczej wartości z tabeli
Jak uzyskać dostęp do wartości w tej tabeli (nasza lista list)? Wiemy już, że pierwsze oceny uczniów (janMarks) znajdują się na liście, która jest pierwszą pozycją w klasach. Sprawdźmy, czy:
>>> print classMarks[0]
[55, 63, 77, 81]
classMarks[0] to lista ocen Joe z czterech przedmiotów. Teraz chcemy pojedynczej wartości z classMark[0]. Jak to zrobimy? Używamy drugiego indeksu. Jeśli chcemy trzeciego ze swoich znaków (znaku czytania), który ma indeks 2, zrobilibyśmy to:
>>> print classMarks[0][2]
77
Dało nam to pierwszy element w classMarks (indeks 0), który był listą znaków Joe, i trzeci element na tej liście (indeks 2), który był jego znakiem do czytania. Kiedy widzisz nazwę z dwoma zestawami nawiasów kwadratowych, jak classMarks [0] [2], zazwyczaj odnosi się to do listy list.
Lista classMarks tak naprawdę nie zna nazwisk Jan, Tomek i Beata ani tematów Matematyka, Nauka, Czytanie i Pisownia. Oznaczyliśmy je w ten sposób, ponieważ wiedzieliśmy, co zamierzamy przechowywać na liście. Ale w Pythonie są tylko numerowane miejsca na liście. To jest jak ponumerowane skrzynki pocztowe w urzędzie pocztowym. Nie mają na nich nazwisk, tylko liczby. Poczmistrz śledzi, co należy, a wiesz, które jest twoje. Bardziej dokładny sposób oznaczenia tabeli classMarks byłby następujący:
Teraz łatwiej jest zauważyć, że znak 77 jest przechowywany w classMarks [0] [2].
Gdybyśmy pisali program używający classMarks do przechowywania naszych danych, musielibyśmy śledzić, które dane były przechowywane w którym wierszu i kolumnie. Podobnie jak postmaster, mielibyśmy za zadanie śledzić, który slot należy do danego elementu danych.
Słowniki
Właśnie zobaczyłeś, że lista Pythona jest sposobem zbierania przedmiotów razem. Dość często w programowaniu chcesz zbierać rzeczy w sposób, który pozwala powiązać wartość z inną wartością. Jest to sposób, w jaki książka telefoniczna kojarzy nazwiska i numery telefonów lub sposób, w jaki słownik kojarzy słowa i ich definicje. Słownik Pythona to sposób na powiązanie dwóch rzeczy ze sobą. Te dwie rzeczy są nazywane kluczem i wartością. Każdy element lub wpis w słowniku ma klucz i wartość. Usłyszysz je jako pary klucz-wartość. Słownik to zbiór par klucz-wartość. Prostym przykładem jest lista numerów telefonów. Powiedzmy, że chcesz zachować listę numerów telefonów znajomych. Użyjesz ich imion do wyszukania liczb. (Mam nadzieję, że żaden z twoich przyjaciół nie ma tego samego imienia.) Nazwa będzie kluczem (rzecz, której będziesz używać do wyszukiwania informacji), a numer telefonu będzie wartością (rzecz, którą będziesz szukał) . Oto jeden ze sposobów utworzenia słownika Pythona do przechowywania nazw i numerów telefonów. Najpierw stwórzmy pusty słownik:
>>> phoneNumbers = {}
Wygląda to bardzo podobnie do sposobu tworzenia listy, z wyjątkiem użycia nawiasów klamrowych (zwanych również nawiasami klamrowymi, a czasem tylko nawiasów klamrowych) zamiast nawiasów kwadratowych używanych dla list. Następnie dodajmy wpis:
>>> phoneNumbers["Janek"] = "555-1234"
Jeśli następnie wyświetlimy nasz słownik, wygląda to tak:
>>> print phoneNumbers
{'Janek': '555-1234'}
Klucz jest wymieniony jako pierwszy, po którym następuje dwukropek, a następnie wartość. Cytaty są tam, ponieważ zarówno klucz, jak i wartość są w tym przypadku łańcuchami (nie muszą być). Innym sposobem na zrobienie tego samego jest
>>> phoneNumbers = {"Janek": "555-1234"}
Dodajmy więcej nazwisk. W przeciwieństwie do metody append() używanej dla list, słowniki nie mają metody dodawania nowych elementów. Wystarczy podać nowy klucz i wartość:
>>> phoneNumbers["Maryśka"] = "555-6789"
>>> phoneNumbers["Bolek"] = "444-4321"
>>> phoneNumbers["Jessika"] = "867-5309"
Spójrzmy na cały słownik:
>>> print phoneNumbers
{'Bob': '444-4321', 'Janek': '555-1234', 'Maryśka': '555-6789', 'Jessika': '867-5309'}
Cały powód, dla którego stworzyliśmy słownik, był taki, że moglibyśmy to wszystko sprawdzić. W tym przypadku chcemy poszukać czegoś po imieniu. Robisz to w ten sposób:
>>> print phoneNumbers["Maryśka"]
'555-6789'
Zauważ, że używasz nawiasów kwadratowych, aby określić, który klucz chcesz umieścić w słowniku. Ale słownik jako całość jest zamknięty w nawiasach klamrowych. Słownik jest nieco podobny do listy, ale istnieje kilka głównych różnic. Oba typy są kolekcjami; to znaczy są sposobem zbierania razem innych typów. Oto kilka podobieństw:
• Zarówno listy, jak i słowniki mogą zawierać dowolny typ (nawet listy i słowniki), dzięki czemu można mieć zbiory liczb, łańcuchów, obiektów, a nawet innych kolekcji.
• Zarówno listy, jak i słowniki umożliwiają znalezienie rzeczy w kolekcji.
Oto kilka różnic:
• Listy są uporządkowane. Jeśli umieścisz rzeczy na liście w określonej kolejności, pozostaną w tej kolejności. I możesz posortować listę. Słowniki są nieuporządkowane. Jeśli dodasz rzeczy do słownika, a następnie wyświetlisz zawartość, mogą być w innej kolejności niż je umieściłeś.
• Pozycje na liście są dostępne po ich indeksie. Dostęp do elementów w słowniku uzyskuje się za pomocą klucza:
>>> print myList[3]
'eggs'
>>> print myDictionary["Janek"]
'555-1234'
Jak wspomnieliśmy wcześniej, wiele rzeczy w Pythonie to obiekty, w tym listy i słowniki. Podobnie jak listy, słowniki mają kilka metod, których możesz użyć do pracy z nimi, używając notacji kropkowej, którą widziałeś wcześniej. Metoda keys() daje listę wszystkich kluczy słownikowych:
>>> phoneNumbers.values()
['444-4321', '555-1234', '555-6789', '867-5309']
Inne języki mają coś podobnego do słowników Pythona. Są one ogólnie nazywane tablicami asocjacyjnymi (ponieważ kojarzą klucze i wartości ze sobą). Innym terminem, o którym słyszysz, są tabele mieszania. Podobnie jak listy, elementy w słowniku mogą być dowolnego typu, w tym typy proste (int, float, string) lub kolekcje (listy lub słowniki) lub typy złożone (obiekty). Tak, możesz mieć słowniki zawierające inne słowniki, tak jak możesz mieć listy list. Właściwie to nie do końca prawda. Dotyczy to wartości w słowniku, ale klucze są bardziej ograniczone. Wcześniej rozmawialiśmy o typach zmiennych i niezmiennych. Cóż, klucze słownikowe mogą być tylko niezmiennymi typami (boolean, liczby całkowite, zmiennoprzecinkowe, łańcuchy i krotki). Nie możesz użyć listy lub słownika jako klucza, ponieważ są to typy zmienne. Wspomniałem powyżej, że jedną z rzeczy o słownikach różniących się od list jest to, że słowniki są nieuporządkowane. Zauważ, że chociaż numer Boba był trzecim, który dodaliśmy do słownika, był to pierwszy element, gdy wyświetlaliśmy zawartość słownik. Słowniki nie mają pojęcia porządku, więc sortowanie słownika nie ma sensu. Ale czasami chcesz wyświetlić zawartość słownika w jakimś porządku. Pamiętaj, że listy mogą być sortowane, więc po otrzymaniu listy kluczy możesz sortować i następnie wyświetl słownik w kolejności jego klawiszy. Możesz sortować listę kluczy za pomocą funkcji sorted (), tak jak poniżej:
>>> for key in sorted(phoneNumbers.keys()):
print key, phoneNumbers[key]
Bolek 444-4321
Jessika 867-5309
Jaek 555-1234
Maryśka 555-6789
To ta sama funkcja sorted(), którą widziałeś wcześniej dla list. Jeśli się nad tym zastanowić, ma to sens, ponieważ zbiór kluczy słownika jest listą. Co zrobić, jeśli chcesz wyświetlić elementy w kolejności wartości zamiast kluczy? W naszym przykładzie numerów telefonów oznaczałoby to sortowanie według numerów telefonów, od najniższego do najwyższego numeru. Słownik to naprawdę wyszukiwanie w jedną stronę. Ma na celu wyszukiwanie wartości za pomocą klawiszy, a nie odwrotnie. Więc trochę trudniej jest sortować według wartości. To możliwe - wymaga to trochę więcej pracy:
>>> for value in sorted(phoneNumbers.values()):
for key in phoneNumbers.keys():
if phoneNumbers[key] == value:
print key, phoneNumbers[key]
Bolek 444-4321
Janek 555-1234
Maryśka 555-6789
Jessika 867-5309
Tutaj, po otrzymaniu posortowanej listy wartości, wzięliśmy każdą wartość i znaleźliśmy jej klucz, przechodząc przez wszystkie klucze, aż znaleźliśmy ten, który był powiązany z tą wartością. Oto kilka innych rzeczy, które możesz zrobić ze słownikami:
• Usuń element za pomocą del:
>>> del phoneNumbers["Janek"]
>>> print phoneNumbers
{'Bolek': '444-4321', 'Maryśka': '555-6789', 'Jessika': '867-5309'}
• Usuń wszystkie elementy (wyczyść słownik), używając clear():
>>> phoneNumbers.clear ()
>>> print phoneNumbers
{}
• Dowiedz się, czy w słowniku istnieje klucz, używając:
>>> phoneNumbers = {'Bolek': '444-4321', 'Maryśka': '555-6789', 'Jessika': '867-5309'}
>>> "Bolek" in phoneNumbers
True
>>> "Barb" in phoneNumbers
False
Słowniki są używane w wielu kodach Pythona. Z pewnością nie jest to wyczerpujący przegląd słowników Pythona. Ale powinno ci to dać ogólny pomysł, dzięki któremu możesz zacząć używać ich w kodzie i rozpoznać je, gdy zobaczysz je w innym kodzie.
Czego się nauczyłeś?
• Jakie są listy
• Jak dodawać rzeczy do listy
• Jak usunąć rzeczy z listy
• Jak sprawdzić, czy lista zawiera określoną wartość
• Jak sortować listę
• Jak zrobić kopię listy
• O krotkach
• Informacje o listach list
• Informacje o słownikach Pythona
Sprawdź swoją wiedzę
1 Jakie są dwa sposoby dodania czegoś do listy?
2 Jakie są dwa sposoby usunięcia czegoś z listy?
3 Jakie są dwa sposoby uzyskania posortowanej kopii listy bez zmiany oryginalnej listy?
4 Jak dowiesz się, czy dana wartość znajduje się na liście?
5 Jak znaleźć lokalizację określonej wartości na liście?
6 Co to jest krotka?
7 Jak sporządzić listę list?
8 Jak uzyskać pojedynczą wartość z listy list?
9 Co to jest słownik?
10 Jak dodać element do słownika?
11 Jak odszukać przedmiot z jego klucza?
Wypróbuj to
1 Napisz program, aby zapytać użytkownika o pięć nazw. Program powinien przechowywać nazwy na liście i drukować je wszystkie na końcu. Powinien wyglądać mniej więcej tak:
Wprowadź 5 nazw:
Tomek
Paweł
Mikołaj
Michał
Kevin
Nazwy to Tomek Paweł Mikołaj Michał Kevin
2 Zmodyfikuj program z pytania nr 1, aby wydrukować zarówno oryginalną listę nazw, jak i posortowaną listę.
3 Zmodyfikuj program z pytania nr 1, aby wyświetlić tylko trzecią nazwę wpisaną przez użytkownika, taką jak ta:
Trzecia wprowadzona nazwa to: Mikołaj
4 Zmodyfikuj program z pytania nr 1, aby umożliwić użytkownikowi zastąpienie jednej z nazw. Powinna być w stanie wybrać nazwę, która ma zostać zastąpiona, a następnie wpisać nową nazwę. Na koniec wyświetl nową listę w następujący sposób:
Wprowadź 5 nazw:
Tomek
Paweł
Mikołaj
Michał
Kevin
Nazwy to Tomek Paweł Mikołaj Michał Kevin
Zastąp jedną nazwę. Który? (1-5): 4
Nowa nazwa: Piotr
Nazwy to Tomek Paweł Mikołaj Piotrł Kevin
5 Napisz program słownika, który pozwala użytkownikom wprowadzać określone słowa i definicje, a następnie przeglądać je później. Upewnij się, że wiesz, czy ich słowo nie znajduje się jeszcze w słowniku. Powinien wyglądać mniej więcej tak, gdy działa:
Dodaj lub wyszukaj słowo (a / l)? za
Wpisz słowo: komputer
Wpisz definicję: maszyna, która wykonuje bardzo szybką matematykę
Dodano słowo!
Dodaj lub wyszukaj słowo (a / l)? l
Wpisz słowo: komputer
Maszyna, która wykonuje bardzo szybką matematykę
Dodaj lub wyszukaj słowo (a / l)? l
Wpisz słowo: qwerty
Tego słowa nie ma jeszcze w słowniku.
Wkrótce nasze programy zaczną być coraz większe i bardziej skomplikowane. Potrzebujemy pewnych sposobów, aby zorganizować je w mniejsze kawałki, aby łatwiej było je pisać i śledzić. Istnieją trzy główne sposoby dzielenia programów na mniejsze części. Funkcje są jak elementy składowe kodu, które można używać wielokrotnie. Obiekty są sposobem opisywania elementów twojego programu jako samodzielnych jednostek. Moduły są tylko oddzielnymi plikami, które zawierają części twojego programu. W tej części dowiemy się o funkcjach, a w kolejnych dwóch częściach poznamy obiekty i moduły. Wtedy będziemy mieli wszystkie podstawowe narzędzia, których potrzebujemy, aby zacząć używać grafiki i dźwięków oraz tworzyć gry.
Funkcje - bloki konstrukcyjne
W najprostszym ujęciu funkcja jest fragmentem kodu, który coś robi. To mały kawałek, którego możesz użyć do zbudowania większego programu. Możesz położyć kawałek razem z innymi kawałkami, tak jak budowanie czegoś za pomocą zabawkowych klocków. Tworzysz lub definiujesz funkcję ze słowem kluczowym def Pythona. Następnie używasz lub wywołujesz funkcję, używając jej nazwy. Zacznijmy od prostego przykładu. Tworzenie funkcji Kod z poniższej listy definiuje funkcję, a następnie jej używa. Ta funkcja drukuje adres pocztowy na ekranie.
Listing 14.1 Tworzenie i używanie funkcji
def printMyAddress():
print "Warren Sande"
print "123 Main Street"
print "Ottawa, Ontario, Canada"
print "K2M 2E9"
print
printMyAddress() <- Wywołanie (użycie) funkcji
W linii 1 definiujemy funkcję, używając słowa kluczowego def. Podajemy nazwę funkcji, następnie nawiasy (), a następnie dwukropek:
def printMyAddress ():
Wyjaśnię, do czego nawiasy są wkrótce. Dwukropek mówi Pythonowi, że nadchodzi blok kodu (podobnie jak dla pętli, pętli while i instrukcji if). Następnie mamy kod, który tworzy funkcję. W ostatnim wierszu listy 14.1 mamy program główny: wywołujemy tę funkcję, podając jej nazwę w nawiasach. Tutaj zaczyna się program. Ta jedna linia powoduje, że program uruchamia kod w zdefiniowanej właśnie funkcji. Gdy program główny wywołuje funkcję, funkcja ta pomaga głównemu programowi wykonać zadanie. Kod wewnątrz bloku def nie jest częścią programu głównego, więc po uruchomieniu programu przeskakuje nad tą częścią i zaczyna się od pierwszej linii, która nie znajduje się w bloku def. Następny rysunek pokazuje, co się dzieje, gdy wywołujesz funkcję. Dodałem jedną dodatkową linię na końcu programu, który drukuje komunikat po zakończeniu funkcji.
Oto kroki z poprzedniej figury:
1 Zacznij tutaj. To jest początek programu głównego.
2 Kiedy wywołujemy funkcję, przechodzimy do pierwszej linii kodu w funkcji.
3 Wykonaj każdą linię funkcji.
4 Po zakończeniu funkcji kontynuujemy pracę w programie głównym.
Wywoływanie funkcji
Wywołanie funkcji oznacza uruchomienie kodu wewnątrz funkcji. Jeśli zdefiniujesz funkcję, ale nigdy jej nie nazwiesz, kod ten nigdy nie zostanie uruchomiony. Wywołujesz funkcję, używając jej nazwy i zestawu nawiasów. Czasami jest coś w nawiasach, a czasami nie.
Spróbuj uruchomić program w liście 14.1 i zobacz, co się stanie. Powinieneś zobaczyć coś takiego:
>>> =================== RESTART ===================
>>>
Jan Bond "
"Błotna 8
Kostomłoty, Polska
11-111
>>>
Teraz jest to dokładnie ten sam wynik, który uzyskaliśmy z prostszego programu, który wygląda tak:
print "Jan Bond"
print "Błotna 8"
print "Kostomłoty, Polska"
print "11-111"
print
Dlaczego więc zadaliśmy sobie trud, aby uczynić rzeczy bardziej złożonymi i korzystać z funkcji w listingu 14.1? Głównym powodem używania funkcji jest to, że po ich zdefiniowaniu można ich używać wielokrotnie, wywołując je. Gdybyśmy chcieli wydrukować adres pięć razy, moglibyśmy to zrobić:
printMyAddress ()
printMyAddress ()
printMyAddress ()
printMyAddress ()
printMyAddress ()
A wyjście byłoby
Jan Bond
Błotna 8
Kostomłoty, Polska
11-111
Jan Bond
Błotna 8
Kostomłoty, Polska
11-111
Jan Bond
Błotna 8
Kostomłoty, Polska
11-111
Jan Bond
Błotna 8
Kostomłoty, Polska
11-111
Jan Bond
Błotna 8
Kostomłoty, Polska
11-111
Można powiedzieć, że można zrobić to samo za pomocą pętli zamiast funkcji. W tym przypadku możesz zrobić to samo z pętlą. Ale jeśli chcesz wydrukować adres w różnych miejscach programu zamiast wszystkich naraz, pętla nie zadziała. Innym powodem użycia funkcji jest to, że można ją zachowywać inaczej przy każdym uruchomieniu.
Przekazywanie argumentów do funkcji
Teraz nadszedł czas, aby zobaczyć, czego dotyczą nawiasy: argumenty! W programowaniu termin argument oznacza informację przekazaną funkcji. Mówimy, że przekazujesz argument do funkcji. Wyobraź sobie, że chciałeś móc korzystać z funkcji drukowania adresów dla każdego członka rodziny. Adres byłby taki sam dla wszystkich, ale nazwa byłaby za każdym razem inna. Zamiast mieć w funkcji nazwę zakodowaną na stałe jako "Jan Bond", możesz uczynić ją zmienną. Zmienna jest przekazywana do funkcji, gdy ją wywołujesz. Przykład jest najprostszym sposobem sprawdzenia, jak to działa. W listing 14.2 zmodyfikowałem funkcję addressprinting, aby użyć jednego argumentu dla nazwy. Argumenty są nazywane, podobnie jak inne zmienne. Nazwę tę zmienną myName. Po uruchomieniu funkcji zmienna myName zostaje wypełniona dowolnym argumentem przekazanym do funkcji, gdy ją wywołamy. Przekazujemy argument funkcji, umieszczając ją w nawiasach, gdy wywołujemy tę funkcję. Tak więc w listingu 13.2 do argumentu myName jest przypisywana wartość "Maria Bond".
Listing 14.2 Przekazywanie argumentu funkcji
def printMyAddress(myName): <- Przekazuje argument myName do funkcji
print myName <- Wyświetla nazwę
print "Błotna 8"
print "Kostomłoty , Polska"
print "11-111"
print
printMyAddress("Maria Bond") <-Przekazuje "Maria Bond" jako argument funkcji; zmienna myName wewnątrz funkcji będzie miała wartość "Maria Bond"
Jeśli uruchomimy kod z listingu 14.2, otrzymamy dokładnie to, czego można oczekiwać:
Maria Bond
Błotna 8
Kostomłoty, Polska
11-111
Wygląda to tak samo, jak wynik uzyskany z pierwszego programu, gdy nie używaliśmy argumentów. Ale teraz możemy za każdym razem drukować adres inaczej:
printMyAddress ("Jan Bond")
printMyAddress ("Chaime Bond")
printMyAddress ("Kasia Bond")
printMyAddress ("Patrycja Bond")
A teraz wyjście jest różne za każdym razem, gdy wywoływana jest funkcja. Nazwa się zmienia, ponieważ za każdym razem przekazujemy tę funkcję inną nazwę:
Jan Bond
Błotna 8
Kostomłoty, Polska
11-111
Chaime Bond
Błotna 8
Kostomłoty, Polska
11-111
Kasia Bond
Błotna 8
Kostomłoty, Polska
11-111
Patrycja Bond
Błotna 8
Kostomłoty, Polska
11-111
A teraz wyjście jest różne za każdym razem, gdy wywoływana jest funkcja. Nazwa się zmienia, ponieważ za każdym razem przekazujemy tę funkcję inną nazwę:
>>> ========================== RESTART ==================== ======
>>>
Jan Bond
Błotna 8
Kostomłoty, Polska
11-111
Chaime Bond
Błotna 8
Kostomłoty, Polska
11-111
Kasia Bond
Błotna 8
Kostomłoty, Polska
11-111
Patrycja Bond
Błotna 8
Kostomłoty, Polska
11-111
Zauważ, że każda wartość przekazana do funkcji została użyta wewnątrz funkcji i została wydrukowana jako część nazwy adresu. Jeśli jest więcej niż jedna pozycja, która jest inna przy każdym uruchomieniu funkcji, potrzebujesz więcej niż jednego argumentu. Właśnie o tym będziemy rozmawiać dalej.
Funkcje z więcej niż jednym argumentem
W listingu 14.2 nasza funkcja miała pojedynczy argument. Ale funkcje mogą mieć więcej niż jeden argument. W rzeczywistości mogą mieć tyle, ile potrzebujesz. Wypróbujmy przykład z dwoma argumentami i myślę, że wpadniesz na pomysł. Następnie możesz dodawać tyle argumentów, ile potrzebujesz funkcji w swoich programach.
Jest jeszcze jeden termin, który usłyszysz, gdy mówisz o przekazywaniu rzeczy do funkcji: parametry. Niektórzy mówią, że argument i parametr są wymienne. Można więc powiedzieć: "Przekazałem dwa parametry do tej funkcji" lub "Przekazałem dwa argumenty do tej funkcji". Niektórzy mówią, że powinieneś użyć argumentu, gdy mówisz o części przechodzącej (gdy wywołujesz funkcję) i parametru gdy mówimy o części odbierającej (co znajduje się wewnątrz funkcji). Dopóki używasz argumentu lub parametru do mówienia o przekazywaniu wartości do funkcji, programiści będą wiedzieć, co masz na myśli.
Nasza funkcja wyświetlania adresów będzie potrzebować dwóch argumentów: jednego dla nazwy i jednego dla numeru domu. Następny listing pokazuje, jak to wyglądałoby.
Listing 14.3 Funkcja z dwoma argumentami
def printMyAddress(someName, houseNum): <- Używa dwóch zmiennych dla dwóch argumentów
print someName zostaną wyświetlone
print houseNum, <-Przecinek sprawia, że numer domu i ulica są w tej samej linii
print "Błotna 8"
print "Kostomłoty, Polska"
print "11-111"
print
printMyAddress("Jan Blond", "45")
printMyAddress("Jacek Czarny", "64")
printMyAddress("Tomek Zielony", "22")
printMyAddress("Edek Biały", "36")
Kiedy używasz wielu argumentów (lub parametrów), oddzielasz je przecinkiem, tak jak elementy na liście, co prowadzi nas do następnego tematu.
Ile to za dużo?
Powiedziałem wcześniej, że możesz przekazać dowolną liczbę argumentów funkcji. To prawda, ale jeśli twoja funkcja ma więcej niż pięć lub sześć argumentów, nadszedł czas, aby pomyśleć o robieniu innych rzeczy. Jedna rzecz, którą możesz zrobić, to zebrać wszystkie argumenty z listy, a następnie przejść listę funkcji. W ten sposób przekazujesz pojedynczą zmienną (zmienną listy), która po prostu zawiera kilka wartości. Może to ułatwić czytanie kodu.
Funkcje zwracające wartość
Jak dotąd nasze funkcje właśnie to dla nas robią. Ale bardzo przydatną rzeczą w funkcjach jest to, że mogą ci także coś wysłać. Widziałeś, że możesz wysyłać informacje (argumenty) do funkcji, ale funkcje mogą również wysyłać informacje z powrotem do wywołującego. Wartość, która wraca z funkcji, nazywana jest wartością wyniku lub powrotu.
Zwracanie wartości
Sposób, w jaki funkcja zwraca wartość, to użycie słowa kluczowego return Python wewnątrz funkcji. Oto przykład:
def calculateTax(price, tax_rate):
taxTotal = price + (price * tax_rate)
return taxTotal
Spowoduje to wysłanie wartości taxTotal z powrotem do części programu, która wywołała tę funkcję. Ale kiedy jest odesłany, dokąd to idzie? Zwracane wartości wracają do dowolnego kodu zwanego funkcją. Oto przykład:
totalPrice = calculateTax(7.99, 0.06)
Funkcja calculTax zwróci wartość 8.4694, a ta wartość zostanie przypisana do totalPrice. Możesz użyć funkcji do zwracania wartości w dowolnym miejscu, w którym użyjesz wyrażenia. Możesz przypisać wartość zwracaną do zmiennej (tak jak właśnie to zrobiliśmy), użyć jej w innym wyrażeniu lub wydrukować, w ten sposób:
>>> print calculateTax(7.99, 0.06)
8.4694
>>> total = calculateTax(7.99, 0.06) + calculateTax(6.59, 0.08)
Nie możesz też nic zrobić ze zwróconą wartością, taką jak ta:
>>> calculateTax(7.49, 0.07)
W ostatnim przykładzie funkcja uruchomiła i obliczyła sumę z podatkiem, ale nie wykorzystaliśmy wyniku. Zróbmy program z funkcją, która zwraca wartość. W listingu 14.4 funkcja calculTax () zwraca wartość. Dajemy jej cenę przed opodatkowaniem i stawkę podatku i zwraca cenę po opodatkowaniu. Przydzielimy tę wartość zmiennej. Więc zamiast używać nazwy funkcji tak jak poprzednio, potrzebujemy zmiennej, znaku równości (=), a następnie nazwy funkcji. Zmiennej zostanie przypisany wynik, który zwraca funkcja calculTax().
Listing 14.4 Tworzenie i używanie funkcji, która zwraca wartość
def calculateTax(price, tax_rate):
total = price + (price * tax_rate)
return total <- Wysyła wynik z powrotem do programu głównego
my_price = float(raw_input ("Enter a price: "))
totalPrice = calculateTax(my_price, 0.06) <- Wywołuje funkcję i zapisuje wynik w totalPrice
print "price = ", my_price, " Total price = ", totalPrice
Spróbuj wpisać, zapisać i uruchomić program na listingu 14.4. Zwróć uwagę, że stawka podatku jest ustalona w kodzie na 0,06 (co odpowiada 6% podatku). Jeśli program musiał obsługiwać różne stawki podatkowe, użytkownik może wprowadzić stawkę podatku oraz cenę.
Zmienny zakres
Być może zauważyłeś, że mamy zmienne poza funkcją, takie jak totalPrice, jak również zmienne wewnątrz funkcji, takie jak total. To tylko dwie nazwy tego samego. Przypomina to Część drugą, kiedy mieliśmy YourTeacher = MyTeacher. W naszym przykładzie calculTax, totalPrice i total są dwoma znacznikami dołączonymi do tej samej rzeczy. Dzięki funkcjom nazwy wewnątrz funkcji są tworzone tylko wtedy, gdy funkcja jest uruchomiona. Nie istnieją nawet przed uruchomieniem funkcji lub po jej zakończeniu. Python ma coś zwanego zarządzaniem pamięcią, które robi to automatycznie. Python tworzy nowe nazwy, które będą używane wewnątrz funkcji podczas jej uruchamiania, a następnie usuwa je po zakończeniu funkcji. Ta ostatnia część jest ważna: kiedy funkcja jest zakończona, wszystkie nazwy w niej przestają istnieć. Gdy funkcja jest uruchomiona, nazwy spoza funkcji są jakby wstrzymane - nie są używane. Używane są tylko nazwy wewnątrz funkcji. Część programu, w której używana jest zmienna (lub dostępna do użycia), nazywa się jej zakresem.
Zmienne lokalne
W listing 14.4 zmienne cena i suma były używane tylko w ramach funkcji. Mówimy, że cena, suma i stopa_pdatku są w zakresie funkcji calculTax (). Inny używany termin to lokalny. Zmienne ceny, sumy i współczynnika podatkowego są zmiennymi lokalnymi w funkcji calculTax (). Jednym ze sposobów, aby zobaczyć, co to oznacza, jest dodanie linii do programu na listing 14.4, która próbuje wydrukować wartość ceny gdzieś poza funkcją. Następująca lista robi to.
Listing 14.5 Próba wydrukowania zmiennej lokalnej
def calculateTax(price, tax_rate):
total = price + (price * tax_rate)
return total
my_price = float(raw_input ("Enter a price: "))
totalPrice = calculateTax(my_price, 0.06) <- Wywołuje funkcję i zapisuje i wyświetla wynik
print "price = ", my_price, " Total price = ", totalPrice
print price <- Próbuje wyświetlić cenę
Jeśli to uruchomisz, pojawi się błąd, który wygląda tak:
Traceback (most recent call last):
File "C:/.../Listing_13-5.py", line 9, in
print price
NameError: name 'price' is not defined <- Linia wyjaśniająca błąd
Ostatni wiersz komunikatu o błędzie mówi historię: gdy nie jesteśmy wewnątrz funkcji calculateTax(),zmienna price nie jest zdefiniowana. Istnieje tylko wtedy, gdy funkcja jest uruchomiona. Gdy próbowaliśmy wydrukować wartość price spoza funkcji (gdy funkcja nie była uruchomiona), wystąpił błąd.
Zmienne globalne
W przeciwieństwie do zmiennej lokalnej price, zmienne my_price i totalPrice w listingu 14.5 są zdefiniowane poza funkcją w głównej części programu. Używamy terminu globalny dla zmiennej, która ma szerszy zakres. W tym przypadku szerszy oznacza główną część programu, a nie to, co jest wewnątrz funkcji. Gdybyśmy rozszerzyli program na listingu 14.5, moglibyśmy użyć zmiennych my_price i totalPrice w innym miejscu w programie, a one nadal miałyby wartości, które daliśmy im wcześniej. Nadal byłyby w zasięgu. Ponieważ możemy ich używać w dowolnym miejscu programu, mówimy, że są to zmienne globalne. W listingu 14.5, kiedy byliśmy poza funkcją i próbowaliśmy wydrukować zmienną, która była wewnątrz funkcji, wystąpił błąd. Zmienna nie istniała; to było poza zakresem. Jak myślisz, co się stanie, jeśli zrobimy coś przeciwnego: spróbuj wydrukować zmienną globalną z wnętrza funkcji? Następna lista próbuje wydrukować zmienną my_price z wnętrza funkcji calculTax (). Wypróbuj i zobacz, co się stanie
Listing 14.6 Używanie zmiennej globalnej wewnątrz funkcji
def calculateTax(price, tax_rate):
total = price + (price * tax_rate)
print my_price <- Próbujemy wyświetlić my_price
return total
my_price = float(raw_input ("Wpisz cenę: "))
totalPrice = calculateTax(my_price, 0.06)
print "price = ", my_price, " Total price = ", totalPrice
Zadziałało? Tak! Ale dlaczego?
Kiedy zaczęliśmy mówić o zmiennym zakresie, powiedziałem ci, że Python używa zarządzania pamięcią do automatycznego tworzenia zmiennych lokalnych, gdy funkcja działa. Menedżer pamięci także robi inne rzeczy. W funkcji, jeśli używasz nazwy zmiennej, która została zdefiniowana w głównym programie, Python pozwoli ci używać zmiennej globalnej, dopóki nie spróbujesz jej zmienić. Więc możesz to zrobić
print my_price
albo to
your_price = my_price
ponieważ żadna z tych zmian nie zmienia mojej ceny. Jeśli jakakolwiek część funkcji próbuje zmienić zmienną, Python tworzy nową zmienną lokalną. Więc jeśli to zrobisz
my_price = my_price + 10
następnie my_price jest nową lokalną zmienną tworzoną przez Pythona podczas działania funkcji. W przykładzie na listingu 14.6 wydrukowaną wartością była zmienna globalna my_price, ponieważ funkcja nie zmieniła jej. Program w listingu 14.7 pokazuje, że jeśli spróbujesz zmienić zmienną globalną wewnątrz funkcji, otrzymasz nową zmienną lokalną. Spróbuj go uruchomić i zobaczyć.
Listing 14.7 Próba zmodyfikowania zmiennej globalnej wewnątrz funkcji
def calculateTax(price, tax_rate):
total = price + (price * tax_rate)
my_price = 10000 <- Modyfikuje my_price wewnątrz funkcji
print "my_price (inside function) = ", my_price <-Wyświetla lokalną wersję my_price
return total
my_price = float(raw_input ("Enter a price: ")) <- Zmienna my_price tutaj jest innym kawałkiem pamięci niż my_price tutaj
totalPrice = calculateTax(my_price, 0.06)
print "price = ", my_price, " Total price = ", totalPrice
print "my_price (outside function) = ", my_price // Wyświetla globalną wersję my_price
Jeśli uruchomisz kod w listingu 14.7, wynik będzie wyglądał następująco:
>>> ========================== RESTART ==========================
>>>
Wpisz cenę: 7.99
my_price (inside function) = 10000 <- Wyświetla my_price wewnątrz funkcji
price = 7.99 Total price = 8.4694
my_price (outside function) = 7.99 <- Wyświetla my_price spoza funkcji
Jak widać, istnieją teraz dwie różne zmienne o nazwie my_price, o różnych wartościach. Jedna to lokalna zmienna wewnątrz funkcji calculTax (), którą ustawiliśmy na 10 000. Druga to zmienna globalna, którą zdefiniowaliśmy w głównym programie, aby przechwycić dane wejściowe użytkownika, która wynosiła 7,99.
Wymuszanie globalne
W ostatniej sekcji zobaczyłeś, że jeśli spróbujesz zmienić wartość zmiennej globalnej z wnętrza funkcji, Python tworzy nową zmienną lokalną. Ma to na celu zapobieganie przypadkowym zmianom zmiennych globalnych przez funkcje. Jednak zdarzają się sytuacje, w których chcesz zmienić zmienną globalną z wnętrza funkcji. Więc jak to robisz? Python ma słowo kluczowe, global, które pozwala to zrobić. Używasz go w ten sposób:
def calculateTax(price, tax_rate):
global my_price <- Mówi Pythonowi, że chcesz użyć globalnej wersji my_price
Jeśli użyjesz globalnego słowa kluczowego, Python nie utworzy nowej zmiennej lokalnej o nazwie my_price. Użyje zmiennej globalnej my_price. Jeśli nie ma globalnej zmiennej o nazwie my_price, utworzy ją.
Trochę porad na temat nazywania zmiennych
W poprzednich sekcjach widziałeś, że możesz używać tych samych nazw dla zmiennych globalnych i zmiennych lokalnych. Python automatycznie utworzy nowe zmienne lokalne, gdy zajdzie taka potrzeba, lub możesz zapobiec temu za pomocą globalnego słowa kluczowego. Zdecydowanie zalecam jednak, aby nie używać ponownie nazw. Jak można zauważyć na podstawie niektórych przykładów, trudno jest stwierdzić, czy zmienna jest wersją lokalną, czy globalną. To sprawia, że kod jest bardziej mylący, ponieważ masz różne zmienne o tej samej nazwie. I wszędzie tam, gdzie pojawia się zamieszanie, błędy uwielbiają wkradać się. Dlatego na razie zalecam używanie różnych nazw zmiennych lokalnych i zmiennych globalnych. W ten sposób nie ma zamieszania, a błędy zostaną zachowane.
Czego się nauczyłeś?
• Czym jest funkcja
• Jakie są argumenty (lub parametry)
• Jak przekazać argument do funkcji
• Jak przekazać wiele argumentów do funkcji
• Jak sprawić, aby funkcja zwracała wartość do dzwoniącego
• Jaki jest zakres zmiennych i jakie są zmienne lokalne i globalne
• Jak używać zmiennych globalnych w funkcji
Sprawdź swoją wiedzę
1 Jakiego słowa kluczowego używasz do utworzenia funkcji?
2 Jak nazywasz funkcję?
3 Jak przekazać informacje (argumenty) do funkcji?
4 Jaka jest maksymalna liczba argumentów, jaką może mieć funkcja?
5 Jak odzyskać informacje z funkcji?
6 Co dzieje się ze zmiennymi lokalnymi w funkcji po zakończeniu działania funkcji?
Wypróbuj to
1 Utwórz funkcję, która pozwoli Ci wydrukować dowolną nazwę, adres, ulicę, miasto, stan lub prowincję, kod pocztowy lub kod pocztowy oraz kraj na świecie. (Podpowiedź: Wymaga siedmiu argumentów. Możesz przekazać je jako indywidualne argumenty lub jako listę).
2 Stwórz funkcję, która pozwoli Ci wydrukować dowolną nazwę, adres, ulicę, miasto, stan lub prowincję, kod pocztowy lub kod pocztowy oraz kraj na świecie. (Podpowiedź: Wymaga siedmiu argumentów. Możesz przekazać je jako indywidualne argumenty lub jako listę).
3 Spróbuj użyć przykładu z listy 13.7, ale uczyń my_price globalnym, aby zobaczyć różnicę w wynikowym wyniku.
4 Napisz funkcję obliczającą całkowitą wartość niektórych zmian - ćwiartki, dziesięciocentówki, nikle i grosze. Funkcja powinna zwracać całkowitą wartość monet. Następnie napisz program, który wywołuje tę funkcję.
Wynik powinien wyglądać następująco:
dwudziestopięciocentówka: 3
dziesięciocentówki: 6
pięciocentówka: 7
pensy: 2
suma wynosi 1,72 $
W ostatnich kilku częściach szukaliśmy różnych sposobów organizowania danych i programów oraz zbierania rzeczy razem. Widzieliśmy, że listy są sposobem na gromadzenie zmiennych (danych) razem, a funkcje są sposobem na zebranie kodu razem w jednostce, którą można używać wielokrotnie. Obiekty przesuwają pomysł zbierania rzeczy o jeden krok dalej. Obiekty to sposób na zbieranie funkcji i danych razem. Jest to bardzo przydatny pomysł w programowaniu i jest używany w wielu, wielu programach. W rzeczywistości, jeśli spojrzysz pod maskę w Pythonie, prawie wszystko jest obiektem. W kategoriach programowania mówimy, że Python jest zorientowany obiektowo. Oznacza to, że możliwe jest (w rzeczywistości całkiem łatwe) użycie obiektów w Pythonie. Tworzenie własnych obiektów nie jest konieczne, ale ułatwia to wiele rzeczy. Tu dowiesz się, czym są obiekty i jak je tworzyć i używać. W kolejnych rozdziałach, kiedy zaczniesz robić grafikę, będziesz dużo używać obiektów.
Obiekty w świecie rzeczywistym
Co to jest obiekt? To dobry początek przy definiowaniu tego, czym jest obiekt w Pythonie. Weźmy na przykład piłkę. Możesz robić rzeczy z piłką, np. podnosić, rzucać, kopać lub nadmuchiwać (dla niektórych piłek). Nazywamy te działania. Możesz także opisać piłkę, podając mi jej kolor, rozmiar i wagę. To są atrybuty piłki.
Możesz opisać obiekt, opisując jego cechy lub atrybuty. Jednym z atrybutów piłki jest jej kształt. Większość piłek ma okrągły kształt. Inne przykłady atrybutów to kolor, rozmiar, waga i koszt. Innym słowem określającym atrybuty są właściwości. Rzeczywiste obiekty w świecie rzeczywistym mają
• Rzeczy, które możesz im zrobić (działania)
• Rzeczy, które je opisują (atrybuty lub właściwości)
W programowaniu mamy takie same rzeczy.
Obiekty w Pythonie
W Pythonie cechy lub "rzeczy, które znasz" na temat obiektu, nazywane są również atrybutami, więc powinny być łatwe do zapamiętania. W Pythonie akcje lub "rzeczy, które możesz zrobić" obiektowi, nazywane są metodami. Gdybyś miał stworzyć wersję lub model piłki w Pythonie, piłka byłaby obiektem i miałaby atrybuty i metody. Atrybuty piłki wyglądałyby tak:
ball.color
ball.size
ball.weight
To wszystko, co możesz opisać na temat piłki. Metody piłek wyglądałyby tak:
ball.kick()
ball.throw()
ball.inflate()
To wszystko, co możesz zrobić z piłką.
Czym są atrybuty?
Atrybuty to wszystko, co wiesz (lub możesz dowiedzieć się) o piłce. Atrybuty piłki to fragmenty informacji - liczby, łańcuchy itd. Brzmi znajomo? Tak, są zmienne. Są to tylko zmienne zawarte w obiekcie. Możesz je wyświetlić:
print ball.size
Możesz przypisać im wartości:
ball.color = "zielony"
Możesz przypisać je do zwykłych zmiennych innych niż obiekty
myColor = ball.color
Możesz także przypisać je do atrybutów w innych obiektach:
myBall.color = yourBall.color
Czym są metody?
Metody to rzeczy, które możesz zrobić z obiektem. Są fragmentami kodu, które możesz wywołać, aby coś zrobić. Brzmi znajomo? Tak, metody są funkcjami zawartymi w obiekcie. Możesz zrobić wszystko za pomocą metod, które możesz zrobić z dowolną inną funkcją, w tym przekazując argumenty i zwracając wartości.
Obiekt = atrybuty + metody
Obiekty są więc sposobem przeniesienia atrybutów i metod (rzeczy, które znasz i rzeczy, które możesz zrobić) na daną rzecz. Atrybuty to informacje, a metody to działania.
Co to jest kropka?
W naszych poprzednich przykładach piłki prawdopodobnie zauważyłeś kropkę między nazwą obiektu a nazwą atrybutu lub metody. To jest tylko notacja Pythona do używania atrybutów i metod obiektu: object.attribute lub object.method(). Proste. Nazywa się notacją kropkową i jest używana w wielu językach programowania. Teraz masz duży obraz obiektów. Zacznijmy robić trochę!
Tworzenie obiektów
Istnieją dwa kroki do utworzenia obiektu w Pythonie. Pierwszym krokiem jest określenie, jak obiekt będzie wyglądał i jak się zachowywać - jego atrybuty i metody. Ale utworzenie tego opisu w rzeczywistości nie tworzy obiektu. To trochę jak plany domu. Plany powiedzą dokładnie, jak będzie wyglądał dom, ale projekt nie jest domem. Nie możesz żyć na planie. Możesz go użyć do zbudowania prawdziwego domu. W rzeczywistości możesz użyć planu do stworzenia wielu domów.
W Pythonie opis lub plan obiektu nazywany jest klasą. Drugim krokiem jest użycie klasy do stworzenia rzeczywistego obiektu. Obiekt nazywany jest instancją tej klasy. Spójrzmy na przykład tworzenia klasy i instancji. Poniższa lista przedstawia definicję klasy dla prostej klasy Ball.
Listing 15.1 Tworzenie prostej klasy Ball
class Ball: <- Mówi Pythonowi , ze tworzymy klasę
def bounce(self):
if self.direction == "down":
self.direction = "up"
W listingu 15.1 mamy definicję klasy dla piłki za pomocą jednej metody: bounce(). Ale co z atrybutami? Cóż, atrybuty tak naprawdę nie należą do klasy, należą do każdej instancji. To dlatego, że każda instancja może mieć różne atrybuty. Istnieje kilka sposobów ustawiania atrybutów instancji. Zobaczysz oba sposoby w następnych sekcjach
Tworzenie instancji obiektu
Jak wspomnieliśmy wcześniej, definicja klasy nie jest obiektem. To tylko plany. Teraz zbudujmy dom. Jeśli chcemy utworzyć instancję Ball, robimy to w następujący sposób:
myBall = Ball()
Nasza piłka nie ma jeszcze żadnych atrybutów, więc dajmy jej trochę:
myBall.direction = "down"
myBall.color = "green"
myBall.size = "small"
Jest to jeden ze sposobów definiowania atrybutów obiektu. Zobaczysz inną drogę w następnej sekcji. Wypróbujmy jedną z metod. Oto, jak używamy metody bounce():
myBall.bounce ()
Połączmy to wszystko w program z kilkoma drukowanymi instrukcjami, aby zobaczyć, co się dzieje.
Listing 15.2 Korzystanie z klas Ball
class Ball:
def bounce(self):
if self.direction == "down":
self.direction = "up"
myBall = Ball() <- Tworzy instancję naszej klasy
myBall.direction = "down"
myBall.color = "red"
myBall.size = "small"
print "Stworzyłem piłkę."
print "Moja piłka jest", myBall.size
print "Moja piłka jest", myBall.color
print "Moja piłka ma kierunek ", myBall.direction
print "Teraz odbijam piłkę ll"
print
myBall.bounce() <- Używamy metody
print "Teraz kierunek piłki jest", myBall.direction
Jeśli uruchomisz program z listingu 15.2, powinieneś zobaczyć to:
>>> ========================== RESTART ====================
>>>
Stworzyłem piłkę.
Moja piłka jest mała
Moja piłka jest czerwona
Moja piłka pada na dół
Teraz odbijam piłkę <- Teraz piłka korzysta z bounce()
Teraz kierunek piłki w górę <- Piłka zmieniła kierunek, z dołu na górę
Zauważ, że po wywołaniu metody bounce() kierunek piłki zmienił się z dołu na górę, co dokładnie ma zrobić kod w metodzie bounce().
Inicjowanie obiektu
Kiedy stworzyliśmy nasz obiekt kulkowy, nie miał on nic wypełnionego dla rozmiaru, koloru lub kierunku. Musieliśmy je wypełnić po utworzeniu obiektu. Ale istnieje sposób na ustawienie właściwości obiektu podczas jego tworzenia. Nazywa się to inicjalizacją obiektu.
Inicjalizacja oznacza "uzyskanie czegoś gotowego na początku". Kiedy inicjalizujemy coś w oprogramowaniu, przygotowujemy go do użycia, wprowadzając go do stanu lub stanu, który chcemy.
Kiedy tworzysz definicję klasy, możesz zdefiniować specjalną metodę o nazwie __init __ (), która będzie uruchamiana za każdym razem, gdy zostanie utworzona nowa instancja klasy. Możesz przekazać argumenty do metody __init __ (), aby utworzyć instancję z ustawionymi własnymi właściwościami. Oto jak to działa.
Listing 15.3 Dodawanie metody __init __ ()
class Ball:
def __init__(self, color, size, direction):
self.color = color
self.size = size
self.direction = direction
def bounce(self):
if self.direction == "down":
self.direction = "up"
myBall = Ball("red", "small", "down") <- Atrybuty są przekazywane jako argumenty __init __ ()
print "Stworzyłem pilkę."
print "Moja piłka jest", myBall.size
print "Moja piłka jest", myBall.color
print "Moja piłka ma kierunek ", myBall.direction
print " Teraz odbijam piłkę "
print
myBall.bounce()
print "Teraz kierunek piłki to", myBall.direction
Jeśli uruchomisz program z listingu 15.3, powinieneś otrzymać ten sam wynik, który otrzymałeś z aukcji 15.2. Różnica polega na tym, że listing 15.3 używa metody __init __ () do ustawiania atrybutów
"Magiczna" metoda: __str __ ()
Obiekty w Pythonie mają pewne "magiczne" metody. Oczywiście nie są naprawdę magiczne! Są to tylko niektóre metody, które Python automatycznie włącza podczas tworzenia dowolnej klasy. Programiści Pythona zwykle nazywają je specjalnymi metodami. Widziałeś już metodę __init __ (), która inicjuje obiekt podczas jego tworzenia. Każdy obiekt ma wbudowaną metodę __init __ (). Jeśli nie umieścisz żadnej z nich w definicji klasy, wbudowana przejmuje tę funkcję, a wszystko to tworzy obiekt. Inną specjalną metodą jest __str __ (), która mówi Pythonowi, co wyświetlać podczas drukowania obiektu. Domyślnie Python ci to mówi
• Gdzie zdefiniowano instancję (__main__, który jest główną częścią programu)
• Nazwa klasy (piłka)
• Miejsce w pamięci, w którym przechowywana jest instancja (jest to część 0x00BB83A0)
Ale jeśli chcesz, aby wydruk pokazywał coś innego dla twojego obiektu, możesz zdefiniować swój własny __str__ (), który zastąpi wbudowany. Następna lista pokazuje przykład
Listing 15.4 Używanie __str __ () do zmiany sposobu wyświetlania obiektu
class Ball:
def __init__(self, color, size, direction):
self.color = color
self.size = size
self.direction = direction
def __str__(self):
msg = "Hi, jestem " + self.size + " " + self.color + " piłkąl!"
return msg
myBall = Ball("red", "small", "down")
print myBall
Teraz, jeśli uruchomimy program na liście 14.4, oto co otrzymujemy:
>>> ================= RESTART =================
>>>
Hi, jestem małą, czerwoną piłką!
To wygląda o wiele bardziej przyjaźnie niż < __ main __. Instancja Ball pod 0x00BB83A0 >, nie myślisz? Wszystkie metody "magiczne" używają dwóch podkreśleń przed i dwóch podkreśleń po nazwie metody.
Co to jest self?
Być może zauważyłeś, że termin "self" pojawia się w kilku miejscach w atrybutach klas i definicjach metod, takich jak ten:
def bounce (self):
Co oznacza "self"? Cóż, pamiętajcie, że powiedzieliśmy, że można użyć planów do zbudowania więcej niż jednego domu? Możesz także użyć klasy, aby utworzyć więcej niż jedną instancję obiektu, taką jak ta:
cartersBall = Ball("red", "small", "down")
warrensBall = Ball("green", "medium", "up")
Kiedy nazywamy metodę dla jednego z takich przypadków, jak ta,
warrensBall.bounce ()
metoda musi wiedzieć, która instancja ją nazywała. Czy to cartersBall musi odbijać, czy warrensBall? Argument self określa metodę, która go nazywała. Nazywa się odwołaniem do instancji. Ale chwileczkę! Kiedy nazwaliśmy metodę, nie było argumentu w nawiasach warrensBall.bounce(), ale w metodzie istnieje argument self. Skąd się wzięła ta argumentacja, jeśli niczego nie przekazaliśmy? To kolejna odrobina "magii", którą Python robi z obiektami. Gdy wywołujesz metodę klasy, informacje o wywołanej instancji - odwołanie do instancji - są automatycznie przekazywane do metody. To tak jak pisząc to:
Ball.bounce (warrensBall)
W tym przypadku wywołaliśmy metodę bounce(), którą piłkę odbijamy. W rzeczywistości ten kod również będzie działał, ponieważ dokładnie to robi Python za kulisami podczas pisania
warrensBall.bounce()
Nawiasem mówiąc, sama nazwa nie ma specjalnego znaczenia w Pythonie. To jest nazwa, której wszyscy używają do odwołania do instancji. To kolejna z tych konwencji, która ułatwia czytanie kodu. Możesz nazwać zmienną instancji, jak chcesz, ale zdecydowanie sugeruję, abyś stosował się do konwencji i używał samego siebie - to sprawi, że rzeczy będą mniej mylące
Przykładowa klasa - HotDog
W tym przykładzie założymy, że hot dogi zawsze mają bułkę. (W przeciwnym razie jest zbyt niechlujny.) Damy naszemu hot dogowi pewne atrybuty i niektóre metody. To są atrybuty:
• cooked_level - Liczba, która informuje nas, jak długo hot-dog został gotowany. Użyjemy 0-3 dla surowego, ponad 3 dla średniego i ponad 5 dla dobrze zrobionego, a wszystko ponad 8 będzie węglem! Nasze hot-dogi zaczną się na surowo.
• cooked_string - ciąg opisujący, jak dobrze zrobiony jest hot dog.
• condiments - lista tego, co znajduje się na hot-dogu, jak ketchup, musztarda i tak dalej.
Oto metody:
• cook() - Gotuje hot doga przez pewien czas. Sprawi to, że hot dog będzie lepiej wykonany.
• add_condiment () - Dodaje przyprawy do hot doga.
• __init __ () - Tworzy naszą instancję i ustawia domyślne właściwości.
• __str __ () - Sprawia, że druk wygląda ładniej.
Po pierwsze, musimy zdefiniować klasę. Zacznijmy od metody __init __ () , która ustawi domyślne atrybuty hot doga:
class HotDog:
def __init__(self):
self.cooked_level = 0
self.cooked_string = "Surowy"
self.condiments = []
Zaczynamy od surowego hot doga i żadnych przypraw. Zróbmy teraz metodę gotowania naszego hot doga:
def cook(self, time):
self.cooked_level = self.cooked_level + time <- Zwiększa poziom gotowania o ilość czasu
if self.cooked_level > 8:
self.cooked_string = "Charcoal"
elif self.cooked_level > 5:
self.cooked_string = "Well-done" ,-
elif self.cooked_level > 3:
self.cooked_string = "Medium"
else:
self.cooked_string = "Raw
Zanim przejdziemy dalej, przetestujmy tę część. Najpierw musimy utworzyć instancję hot doga, a my też sprawdzimy atrybuty:
myDog = HotDog()
print myDog.cooked_level
print myDog.cooked_string
print myDog.condiments
Połączmy to razem w program i uruchomimy. Oto kompletny program (do tej pory).
Listing 15.5 Rozpoczęcie naszego programu Hot Dog
class HotDog:
def __init__(self):
self.cooked_level = 0
self.cooked_string = "Raw"
self.condiments = []
def cook(self, time):
self.cooked_level = self.cooked_level + time
if self.cooked_level > 8:
self.cooked_string = "Charcoal"
elif self.cooked_level > 5:
self.cooked_string = "Well-done"
elif self.cooked_level > 3:
self.cooked_string = "Medium"
else:
self.cooked_string = "Raw"
myDog = HotDog()
print myDog.cooked_level
print myDog.cooked_string
print myDog.condiments
Myślenie jak programista (Python)
Inną konwencją w Pythonie jest to, że nazwa klasy zawsze zaczyna się od dużej litery. Jak dotąd widzieliśmy Ball i HotDog, więc przestrzegaliśmy konwencji. Teraz uruchom kod z listingu 15.5 i zobacz, co otrzymasz. To powinno wyglądać tak
>>>
0 <- cooked_level
Raw <- cooked_string
[] <- przyprawy
Widzimy, że atrybuty to cooked_level = 0, cooked_string = "Raw", a przyprawy są puste. Przetestujmy teraz metodę cook (). Dodaj poniższe linie do kodu z istingu 15.5:
print "Teraz zamierzam ugotować hot doga"
myDog.cook(4) <- Gotuje hot doga przez 4 minuty
print myDog.cooked_level
print myDog.cooked_string
Uruchom program ponownie. Teraz wynik powinien wyglądać następująco:
>>>
0
Surowy
[]
Teraz zamierzam ugotować hot doga
4
Średni
Więc nasza metoda cook() wydaje się działać. Poziom cooked_level zmienił się z 0 na 4, a ciąg znaków również został zaktualizowany (z Raw na Medium)
Spróbujmy dodać kilka dodatków. Potrzebujemy do tego nowej metody. Możemy również dodać naszą funkcję __str __ (), aby łatwiej było wydrukować obiekt. Edytuj program, aby wyglądał tak
Listing 14.6 Klasa HotDog z cook (), add_condiments () i __str __ ()
class HotDog:
def __init__(self):
self.cooked_level = 0
self.cooked_string = "Raw"
self.condiments = []
def __str__(self):
msg = "hot dog"
if len(self.condiments) > 0:
msg = msg + " with "
for i in self.condiments:
msg = msg+i+", "
msg = msg.strip(", ")
msg = self.cooked_string + " " + msg + "."
return msg
def cook(self, time):
self.cooked_level=self.cooked_level+time
if self.cooked_level > 8:
self.cooked_string = "Charcoal"
elif self.cooked_level > 5:
self.cooked_string = "Well-done"
elif self.cooked_level > 3:
self.cooked_string = "Medium"
else:
self.cooked_string = "Raw"
def addCondiment(self, condiment): <-Definiuje nową metodę
add_condiments ()
self.condiments.append(condiment)
myDog = HotDog() <- Tworzy instancję
print myDog
print " Gotowanie hot doga przez 4 minuty …"
myDog.cook(4)
print myDog
print " Gotowanie hot doga przez kolejne 3 minuty …"
myDog.cook(3)
print myDog
print " Co się stanie, jeśli ugotuję go na 10 minut?
myDog.cook(10)
print myDog
print " Teraz dodam kilka rzeczy do mojego hot doga"
myDog.addCondiment("ketchup")
myDog.addCondiment("mustard")
print myDog
Ta lista kodów jest nieco długa, ale nadal zachęcam do wpisywania jej w całości. Uruchom program i zobacz, co otrzymasz. To powinno wyglądać tak:
>>> ================================ RESTART ==============
>>>
Surowy hot dog.
Gotowanie hot doga przez 4 minuty …
Średni hot dog.
Gotowanie hot doga przez kolejne 3 minuty …
Dobrze zrobiony hot dog.
Co się stanie, jeśli ugotuję go na 10 minut?
Węgierski hot dog.
Teraz dodam kilka rzeczy do mojego hot doga
Węgierski hot dog z ketchupem, musztardą
Pierwsza część programu tworzy klasę. Druga część testuje metody gotowania naszego wirtualnego hot doga i dodawania przypraw. Ale sądząc po tej ostatniej linii, myślę, że ugotowaliśmy tu za dużo. Co za strata ketchupu i musztardy!
Ukrywanie danych
Być może zdałeś sobie sprawę, że istnieją dwa sposoby wyświetlania lub zmieniania danych (atrybutów) wewnątrz obiektu. Możesz uzyskać dostęp do atrybutu bezpośrednio, tak
myDog.cooked_level = 5
lub możesz użyć metody, która modyfikuje atrybut, tak jak poniżej:
myDog.cook (5)
Gdyby hot-dog zaczynał od surowego (cooked_level = 0), to self zrobiłoby to samo. Ustawiliśmy poziom gotowania_poziomu na 5. Więc po co zawracaliśmy sobie głowę tym, żeby to zrobić? Dlaczego nie zrobić tego bezpośrednio?
Mogę wymyślić co najmniej dwa powody:
• Gdybyśmy mieli bezpośredni dostęp do atrybutów, gotowanie hot doga wymagałoby co najmniej dwóch części: zmiany poziomu gotowania i zmiany łańcucha gotowanego. Dzięki metodzie po prostu wykonujemy jedno wywołanie metody i robi wszystko, czego potrzebujemy.
• Gdybyśmy mieli bezpośredni dostęp do atrybutów, moglibyśmy zrobić coś takiego:
cooked_level = cooked_level- 2
To sprawiłoby, że hot dog byłby mniej gotowany niż wcześniej. Ale nie możesz rozpakować hot doga! Więc to nie ma sensu. Korzystając z metody, możemy się upewnić, że poziom "gotowane" wzrasta i nigdy nie maleje
W kategoriach programowania ograniczenie dostępu do danych obiektu, aby można było je uzyskać lub zmienić za pomocą metod, nazywane jest ukrywaniem danych. Python nie ma żadnego sposobu na wymuszenie ukrywania danych, ale możesz napisać kod zgodny z tą zasadą, jeśli chcesz
Jak dotąd widziałeś, że obiekty mają atrybuty i metody. Widziałeś, jak tworzyć obiekty i jak je inicjować specjalną metodą o nazwie __init __ (). Widziałeś także inną specjalną metodę o nazwie __str __ (), która sprawia, że obiekty są ładniej drukowane.
Polimorfizm i dziedziczenie
Następnie przyjrzymy się dwóm aspektom obiektów, które są prawdopodobnie najważniejsze: polimorfizmowi i dziedziczeniu. Są to dwa duże długie słowa, ale sprawiają, że obiekty są bardzo przydatne. Wyjaśnię, co znaczą w następnych sekcjach.
Polimorfizm - ta sama metoda, inne zachowanie
Po prostu, polimorfizm oznacza, że możesz mieć dwie (lub więcej) metody o tej samej nazwie dla różnych klas. Metody te mogą zachowywać się inaczej, w zależności od klasy, do której są stosowane.
Załóżmy na przykład, że tworzyłeś program do ćwiczenia geometrii i musiałeś obliczyć obszar różnych kształtów, takich jak trójkąty i kwadraty. Możesz utworzyć dwie klasy, takie jak ta:
class Triangle:
def __init__(self, width, height):
self.width = width
self.height = height
def getArea(self):
area = self.width * self.height / 2.0
return area
Obie mają metodę o nazwie getArea ()
class Square:
def __init__(self, size):
self.size = size
def getArea(self):
area = self.size * self.size
return area
Zarówno klasa Triangle, jak i klasa Square mają metodę o nazwie getArea(). Więc jeśli mieliśmy instancję każdej klasy, taką jak ta
>>> myTriangle = Triangle(4, 5)
>>> mySquare = Square(7)
wtedy możemy obliczyć obszar jednego z nich za pomocą getArea ():
>>> myTriangle.getArea()
10.0
>>> mySquare.getArea()
49
Użyliśmy metody getArea () dla obu kształtów, ale metoda zrobiła coś innego dla każdego kształtu. Jest to przykład polimorfizmu.
Dziedziczenie - uczenie się od rodziców
W świecie rzeczywistym (nieprogramującym) ludzie mogą odziedziczyć rzeczy po swoich rodzicach lub innych krewnych. Możesz dziedziczyć cechy, takie jak rude włosy, lub dziedziczyć rzeczy, takie jak pieniądze lub własność. W programowaniu obiektowym klasy mogą dziedziczyć atrybuty i metody z innych klas. Pozwala to na posiadanie całych "rodzin" klas, które mają wspólne atrybuty i metody. W ten sposób nie musisz zaczynać od zera za każdym razem, gdy chcesz dodać członka do rodziny.
Klasa dziedzicząca atrybuty lub metody z innej klasy nazywana jest klasą pochodną lub podklasą. Przykład pomoże to wyjaśnić. Wyobraź sobie, że tworzymy grę, w której gracz może podchodzić do różnych rzeczy, takich jak jedzenie, pieniądze lub ubrania. Możemy stworzyć klasę o nazwie GameObject. Klasa GameObject miałaby atrybuty takie jak nazwa (na przykład "moneta", "jabłko" lub "kapelusz") oraz metody takie jak pickUp() (które dodawałyby obiekt do kolekcji obiektów gracza). Wszystkie obiekty gry miałyby te wspólne metody i atrybuty. Następnie moglibyśmy stworzyć podklasę monet. Klasa Coin wywodzi się z GameObject. Odziedziczyłby atrybuty i metody GameObject, a więc klasa Coin automatycznie mają atrybut name i metodę pickUp(). Klasa Coin potrzebowałaby również atrybutu wartości (ile jest warta moneta) i metody spend () (aby można było użyć monety do kupienia czegoś). Zobaczmy, jak może wyglądać kod dla tych klas:
class GameObject:
def __init__(self, name):
self.name = name
def pickUp(self, player):
# umieść tutaj kod, aby dodać obiekt
# do kolekcji gracza
class Coin(GameObject): <- Coin jest podklasą GameObject
def __init__(self, value):
GameObject.__init__(self, "coin") <-W __init __ () dziedzicz inicjację GameObject i dodawaj do niej elementy
self.value = value
def spend(self, buyer, seller):
# put code here to remove the coin
# from the buyer's money and
# add it to the seller's money
Patrzeć w przyszłość
W ostatnim przykładzie nie umieściliśmy żadnego kodu w metodach, tylko kilka komentarzy wyjaśniających, co te metody zrobią. To sposób planowania lub myślenia przed tym, co dodasz później. Rzeczywisty kod zależy od sposobu działania gry. Programiści często robią to, aby uporządkować swoje myśli, pisząc bardziej złożony kod. "Puste" funkcje lub metody nazywane są kodami kodu. Jeśli próbowałeś uruchomić poprzedni przykład, wystąpił błąd, ponieważ definicja funkcji nie może być pusta. Słowo kluczowe pass Python jest używane jako symbol zastępczy, gdy chcesz utworzyć kod pośredniczący. Kod powinien więc wyglądać tak:
class Game_object:
def __init__(self, name):
self.name = name
def pickUp(self):
pass <- Dodaj słowo kluczowe pass
# umieść tutaj kod, aby dodać
# obiekt do kolekcji gracza
class Coin(Game_object):
def __init__(self, value):
GameObject.__init__(self, "coin")
self.value = value
def spend(self, buyer, seller):
pass <- Dodaj słowo kluczowe pass
# wprowadź kod, aby usunąć monetę
# z pieniędzy kupującego
# dodaj go do pieniędzy sprzedającego
W tej części nie podam bardziej szczegółowych przykładów wykorzystujących obiekty, polimorfizm i dziedziczenie. Zobaczysz wiele przykładów obiektów i sposób ich wykorzystania podczas przeglądania pozostałej części tego tekstu. Zrozumiesz, jak używać obiektów, gdy używasz ich w prawdziwych programach, takich jak gry.
Czego się nauczyłeś?
• Jakie są obiekty
• Atrybuty i metody
• Czym jest klasa
• Tworzenie instancji klasy
• Metody specjalne: __init __ () i __str __ ()
• Polimorfizm
• Dziedziczenie
• Fragmenty kodu
Sprawdź swoją wiedzę
1 Jakie słowa kluczowe używasz do zdefiniowania nowego typu obiektu?
2 Czym są atrybuty?
3 Czym są metody?
4 Jaka jest różnica między klasą a instancją?
5 Jaka nazwa jest zwykle używana dla odwołania do instancji w metodzie?
6 Co to jest polimorfizm?
7 Co jest dziedziczone?
Wypróbuj to
1 Utwórz definicję klasy dla konta bankowego. Powinien mieć atrybuty nazwy (łańcucha), numeru konta (ciąg lub liczba całkowita) i równowagi (zmiennoprzecinkowy). Powinien mieć metody wyświetlania salda, dokonywania wpłat i dokonywania wypłat.
2 Zrób klasę o nazwie InterestAccount, która procentuje. Powinien być podklasą konta bankowego (dziedziczy więc atrybuty i metody). Powinien mieć także atrybut stopy procentowej i metodę dodawania odsetek. Aby zachować prostotę, załóżmy, że metoda addInterest () będzie wywoływana raz w roku, aby obliczyć odsetki i zaktualizować saldo.
To ostatnia część, który mówi o sposobach zbierania rzeczy razem. Dowiedzieliśmy się już o listach, funkcjach i obiektach. W tym rozdziale poznamy moduły. W następnej części użyjemy modułu o nazwie Pygame, aby rozpocząć rysowanie grafiki.
Co to jest moduł?
Moduł jest częścią lub częścią czegoś. Mówimy, że coś jest modularne jeśli jest w kawałkach lub można to łatwo rozdzielić na kawałki. Bloki LEGO mogą być doskonałym przykładem czegoś modułowego.
Możesz wziąć kilka różnych elementów i zbudować z nimi wiele różnych rzeczy. W Pythonie moduły są mniejszymi kawałkami większego programu. Każdy moduł lub element jest osobnym plikiem na dysku twardym. Możesz wziąć duży program i podzielić go na więcej niż jeden moduł lub plik. Albo możesz pójść w drugą stronę - zacznij od jednego małego modułu i dodawaj elementy, aby stworzyć duży program.
Po co używać modułów?
Po co więc zadawać sobie trud, aby podzielić program na mniejsze części, kiedy będziesz potrzebował ich wszystkich, aby program działał? Dlaczego nie zostawić wszystkiego w jednym dużym pliku? Jest kilka powodów:
• Sprawia, że pliki są mniejsze, co ułatwia znajdowanie rzeczy w kodzie.
• Po utworzeniu modułu można go używać w wielu programach. Dzięki temu nie będziesz musiał zaczynać od nowa, gdy będziesz potrzebować tych samych funkcji.
• Nie zawsze musisz używać wszystkich modułów razem. Bycie modułowym oznacza, że możesz użyć różnych kombinacji części, aby wykonać różne zadania, tak jak możesz zrobić wiele różnych rzeczy z tego samego zestawu klocków LEGO.
Wiadra bloków
W części dotyczącej funkcji powiedzieliśmy, że funkcje są jak bloki konstrukcyjne. Możesz myśleć o module jako wiadrze bloków konstrukcyjnych. Możesz mieć tak mało lub tyle bloków w wiadrze, ile chcesz, i możesz mieć wiele różnych wiader. Może masz jedno wiadro na wszystkie kwadratowe bloki, jedno na płaskie kawałki i jedno na wszystkie dziwne bloki. Zazwyczaj tak programiści używają modułów - zbierają podobne rodzaje funkcji w module. Lub mogą zebrać wszystkie funkcje potrzebne do projektu razem w module, tak jak zebrałbyś wszystkie bloki potrzebne do zamku razem w jednym wiadrze.
Jak tworzymy moduły?
Stwórzmy moduł. Moduł jest po prostu plikiem Pythona, takim jak ten na listingu 16.1. Wpisz kod z listy w oknie edytora IDLE i zapisz go jako my_module.py.
Listing 16.1 Tworzenie modułu
# to jest plik "my_module.py"
# użyjemy go w innym programie
def c_to_f (celsius):
fahrenheit = Celsjusza * 9,0 / 5 + 32
return Fahrenheit
To jest to! Właśnie utworzyłeś moduł! Twój moduł ma jedną funkcję, funkcję c_to_f (), która konwertuje temperaturę z Celsjusza na Fahrenheita. Następnie użyjemy my_module.py w innym programie.
Jak używamy modułów?
Aby użyć czegoś, co znajduje się w module, musisz najpierw powiedzieć Pythonowi, których modułów chcesz użyć. import to jest słowo kluczowe Python, które umożliwia dołączenie innych modułów do programu. Używasz tego w następujący sposób:
import my-module
Napiszmy program, który używa modułu, który właśnie napisaliśmy. Użyjemy funkcji c_to_f () do przeprowadzenia konwersji temperatury.
Widziałeś już, jak używać funkcji i przekazywać jej parametry (lub argumenty). Jedyną różnicą jest to, że funkcja będzie w oddzielnym pliku z naszego głównego programu, więc będziemy musieli użyć importu. Program na następnej liście używa modułu, który właśnie napisaliśmy, my_module.py.
Listing 16.2 Korzystanie z modułu
import my_module <- my_module zawiera funkcję c_to_f ()
celsius = float(raw_input ("Wpisz temperaturę w Celsjuszach: "))
fahrenheit = c_to_f(celsius)
print "To jest ", Fahrenheit
Utwórz nowe okno edytora IDLE i wpisz ten program. Zapisz go jako modular.py, a następnie uruchom go, aby zobaczyć, co się stanie. Będziesz musiał zapisać go w tym samym folderze (lub katalogu) co mój_module.py. Zadziałało? Powinieneś zobaczyć coś takiego:
>>> ========================= RESTART =====================
>>>
Wprowadź temperaturę w stopniach Celsjusza: 34
Śledzenie (ostatnie połączenie):
Plik "C: /MyPythonPrograms/modular.py", wiersz 4, w
fahrenheit = c_to_f (Celsjusza)
NameError: nazwa "c_to_f" nie jest zdefiniowana
To nie zadziałało! Co się stało? Komunikat o błędzie mówi, że funkcja c_to_f () nie jest zdefiniowana. Ale wiemy, że jest zdefiniowana w my_module, a my zaimportowaliśmy ten moduł. Odpowiedź jest taka, że musimy dokładniej powiedzieć Pythonowi o funkcjach zdefiniowanych w innych modułach. Jednym ze sposobów rozwiązania problemu jest zmiana linii
fahrenheit = c_to_f (Celsjusza)
na
fahrenheit = my_module.c_to_f (celsius)
Teraz mówimy Pythonowi, że funkcja c_to_f () znajduje się w module my_module. Wypróbuj program z tą zmianą i sprawdź, czy działa.
Przestrzenie nazw
Co to jest przestrzeń nazw?
Wyobraź sobie, że jesteś w klasie pana Kowalskiego w szkole, a w twojej klasie jest ktoś o imieniu Stach. Teraz wyobraź sobie, że w innej klasie w twojej szkole, prowadzonej przez panią Waluś, jest inny Stach. Jeśli jesteś w swojej klasie i mówisz: "Stach ma nowy plecak", wszyscy w twojej klasie będą wiedzieć (lub przynajmniej będą zakładać), że masz na myśli Stacha w swojej klasie. Jeśli miałeś na myśli tego drugiego, powiedziałbyś: "Stach w klasie pani Waluś" lub "drugi Stach" lub coś w tym stylu. W twojej klasie jest tylko jeden Stach, więc kiedy mówisz "Stach", twoi koledzy z klasy wiedzą, o kim mówisz. Innymi słowy, w przestrzeni twojej klasy istnieje tylko jedna nazwa "Stach". Twoja klasa jest przestrzenią nazw, a w tej przestrzeni nazw jest tylko jeden Stach więc nie ma zamieszania. Teraz, jeśli dyrektor musi zadzwonić do Stacha do biura za pośrednictwem systemu nagłośnieniowego, nie może po prostu powiedzieć: "Czy Stach przyjdzie do biura". Jeśli to zrobi, obaj Stachowie pojawią się w biurze. Dla głównego użytkownika korzystającego z systemu adresów publicznych obszarem nazw jest cała szkoła. Oznacza to, że wszyscy w szkole słuchają nazwy, a nie tylko jednej klasy. Musi więc bardziej szczegółowo określić, jakiego Stacha ma na myśli. Musiałaby powiedzieć coś w stylu: "Czy Stach z klasy pana Kowalskiego przyjdzie do biura." Innym sposobem, w jaki dyrektor mógłby uzyskać prawidłowy Stacha, jest pójście do drzwi twojej klasy i powiedzieć: "Stach, czy mógłbyś? proszę, chodź ze mną. "Będzie tylko jeden Stach słuchający, a on dostanie właściwą. W takim przypadku przestrzeń nazw byłaby tylko jedną klasą, a nie całą szkołą. Ogólnie rzecz biorąc, programiści odnoszą się do mniejszych przestrzeni nazw (takich jak klasa) jako lokalne przestrzenie nazw i większe (jak cała szkoła) jako globalne przestrzenie nazw.
Importowanie przestrzeni nazw
Załóżmy, że w twojej szkole John Young School nie ma nikogo o imieniu Fred. Jeśli dyrektor uda się do systemu adresów publicznych i poprosi o Freda, nie dostanie nikogo. Teraz wyobraź sobie, że kolejna szkoła, Stephen Leacock School, wykonuje kilka napraw, więc jedna z ich klas przenosi się do przenośnej szkoły. W tej klasie jest uczeń o imieniu Fred. Ale to urządzenie przenośne nie jest jeszcze połączone z systemem adresów publicznych. Jeśli dyrektor wzywa Freda, nikogo nie dostanie. Ale jeśli połączy nowe urządzenie przenośne z systemem adresów publicznych , a następnie wezwie Freda, dostanie Freda ze szkoły Stephena Leacocka. Łączenie szkoły przenośnej z inną szkołą jest jak importowanie modułu w Pythonie. Kiedy importujesz moduł, masz dostęp do wszystkich nazw w tym module: wszystkie zmienne, wszystkie funkcje i wszystkie obiekty. Importowanie modułu oznacza to samo, co importowanie przestrzeni nazw. Kiedy importujesz moduł, importujesz przestrzeń nazw. Istnieją dwa sposoby importowania przestrzeni nazw (lub modułu). Możesz to zrobić w ten sposób:
import StephenLeacock
Jeśli zrobisz to w ten sposób, StephenLeacock jest nadal oddzielną przestrzenią nazw. Masz dostęp do przestrzeni nazw, ale musisz określić, którą przestrzeń nazw chcesz użyć przed jej użyciem. Więc dyrektor musiałby zrobić coś takiego:
call_to_office (StephenLeacock.Fred)
Nadal musiał podać przestrzeń nazw (StephenLeacock), a także imię (Fred), gdyby chciaładotrzeć do Freda. Właśnie tak zrobiliśmy kilka stron temu dzięki naszemu programowi konwersji temperatury. Aby to działało, napisaliśmy to:
fahrenheit = my_module.c_to_f (celsius)
Określiliśmy przestrzeń nazw (my_module), a także nazwę funkcji (c_to_f)
Importowanie za pomocą from
Inny sposób importowania przestrzeni nazw jest następujący:
from StephenLeacock import Fred
Jeśli główny wykonawca robi to w ten sposób, imię Fred z StephenLeacock zostaje dołączone do jej przestrzeni nazw i może dotrzeć do Freda w ten sposób:
call_to_office (Fred)
Ponieważ Fred jest teraz w swojej przestrzeni nazw, nie musimy przechodzić do przestrzeni nazw StephenLeacock, aby uzyskać Freda. W tym przykładzie zleceniodawca zaimportował tylko jedną nazwę, Fred, z StephenLeacock do swojej lokalnej przestrzeni nazw. Gdyby chciał zaimportować wszystkich, mógłby to zrobić:
from import StephenLeacock *
Tutaj gwiazdka (*) oznacza wszystko. Ale musi być ostrożny. Jeśli są uczniowie o takich samych nazwiskach ze Stephen Leacock School, jak z John Young School, będzie zamieszanie.
Łał!
W tym momencie cała przestrzeń nazw może nadal być trochę niewyraźna. Nie martw się! Stanie się jasne, jak zrobisz przykłady w kolejnych częściach. Zawsze, gdy musisz zaimportować moduły, wyjaśnię dokładnie, co robisz.
Standardowe moduły
Skoro już wiesz, jak tworzyć i używać modułów, czy zawsze musisz pisać własne moduły? Nie! To jedna z największych zalet Pythona. Python jest wyposażony w szereg standardowych modułów, które umożliwiają między innymi wyszukiwanie plików, określanie czasu (lub liczenie czasu) lub generowanie liczb losowych. Czasami ludzie mówią, że Python ma "baterie w komplecie" i o tym mówią - wszystkie standardowe moduły Pythona. Jest to znane jako standardowa biblioteka Pythona. Dlaczego te rzeczy muszą być w oddzielnych modułach? Cóż, nie muszą być, ale ludzie, którzy zaprojektowali Pythona, uznali, że będzie bardziej wydajny. W przeciwnym razie każdy program w Pythonie musiałby zawierać wszystkie możliwe funkcje. W ten sposób włączasz tylko te, których potrzebujesz. Oczywiście niektóre rzeczy (takie jak print, for i if-else) są podstawowymi poleceniami w Pythonie, więc nie potrzebujesz dla nich osobnego modułu - znajdują się w głównej części Pythona. Jeśli Python nie ma modułu do czegoś, co chcesz zrobić (np. zrobić grafikę, grę), istnieją inne moduły dodatkowe, które można pobrać, zazwyczaj za darmo!
Time
Moduł time pozwala uzyskać informacje z zegara komputera, takie jak data i godzina. Umożliwia także dodawanie opóźnień do programów. (Czasami komputer robi coś zbyt szybko i musisz go spowolnić.) Funkcja sleep() w module time służy do dodawania opóźnienia, to znaczy, aby program czekał i nic nie robił przez chwilę. To tak, jakbyś uśpił swój program, dlatego ta funkcja nazywa się sleep(). Mówisz, ile sekund chcesz spać. Program na poniższym listingu pokazuje, jak działa funkcja sleep(). Spróbuj wpisać, zapisać i uruchomić, i zobacz, co się stanie.
Listing 16.3 Uśpienie programu
import time
print "How",
time.sleep(2)
print "are",
time.sleep(2)
print "you",
time.sleep(2)
print "today?"
Zauważ, że kiedy wywołaliśmy funkcję sleep(), musieliśmy umieścić czas. Przed tym. Dzieje się tak, ponieważ mimo że importowaliśmy czas, nie utworzyliśmy go w przestrzeni nazw programu głównego. Więc za każdym razem, gdy chcemy użyć funkcji sleep(), musimy wywołać time.sleep(). Jeśli spróbowaliśmy czegoś takiego,
import time
sleep(5)
to nie zadziała, ponieważ sleep() nie znajduje się w naszej przestrzeni nazw. Otrzymamy następujący komunikat o błędzie:
NameError: name 'sleep' is not defined
Ale jeśli tak to importujesz,
from time import sleep
to mówi Pythonowi: "Poszukaj zmiennej (lub funkcji lub obiektu) o nazwie sleep w module time i włącz ją do mojej przestrzeni nazw." Teraz możemy użyć funkcji sleep() bez wprowadzania czasu. Przed tym:
from time import sleep
print 'Cześć, przemówiędo ciebie za 5 sekund…'
sleep(5)
print 'Cześć ponownie'
Jeśli chcesz wygodnie importować nazwy do lokalnej przestrzeni nazw (nie musisz za każdym razem określać nazwy modułu), ale nie wiesz, których nazw w module będziesz potrzebować, możesz użyć gwiazdki (*) aby zaimportować wszystkie nazwy do przestrzeni nazw
from time import *
* oznacza wszystko, więc importuje wszystkie dostępne nazwy z modułu. Musisz być ostrożny z tym. Jeśli utworzysz nazwę w swoim programie, która jest taka sama jak w module time, wystąpi konflikt. Importowanie za pomocą * nie jest najlepszym sposobem, aby to zrobić. Lepiej importować tylko potrzebne części. .
Losowe liczby
Moduł random służy do generowania liczb losowych. Jest to bardzo przydatne w grach i symulacjach. Spróbujmy użyć modułu losowego w trybie interaktywnym:
>>> import random
>>> print random.randint(0, 100)
4
>>> print random.randint(0, 100)
72
Za każdym razem, gdy używasz random.randint(), otrzymujesz nową, losową liczbę całkowitą. Ponieważ przekazaliśmy do niego argumenty 0 i 100, liczba całkowita będzie między 0 a 100. Użyliśmy random.randint() w programie zgadywania liczb w rozdziale 1, aby utworzyć tajny numer. Jeśli chcesz losową liczbę dziesiętną, użyj random.random(). Nie musisz niczego umieszczać między nawiasami, ponieważ random.random () zawsze podaje liczbę od 0 do 1:
>>> print random.random()
0.270985467261
>>> print random.random()
0.569236541309
Jeśli chcesz losową liczbę od, powiedzmy, 0 do 10, możesz pomnożyć wynik przez 10:
>>> print random.random() * 10
3.61204895736
>>> print random.random() * 10
8.10985427783
Czego się nauczyłeś?
• Czym jest moduł
• Jak utworzyć moduł
• Jak używać modułu w innym programie
• Co to są przestrzenie nazw
• Co oznaczają lokalne i globalne przestrzenie nazw i zmienne
• Jak wprowadzać nazwy z innych modułów do przestrzeni nazw
• Widziałeś również kilka przykładów standardowych modułów Pythona.
Sprawdź swoją wiedzę
1 Jakie są zalety korzystania z modułów?
2 Jak utworzyć moduł?
3 Jakiego słowa kluczowego Python używasz, gdy chcesz użyć modułu?
4 Importowanie modułu jest takie samo jak importowanie __________.
5 Jakie są dwa sposoby importowania modułu czasowego, aby mieć dostęp do wszystkich nazw (czyli wszystkich zmiennych, funkcji i obiektów) w tym module?
Wypróbuj to
1 Napisz moduł, który ma funkcję "drukuj swoje imię dużymi literami" z sekcji "Wypróbuj" w części 13. Następnie napisz program, który importuje moduł i wywołuje funkcję.
2 Zmodyfikuj kod w listingu 15.2, aby wprowadzić c_to_f () do przestrzeni nazw głównego programu. To znaczy, zmień to, abyś mógł pisać
fahrenheit = c_to_f (Celsjusza)
zamiast
fahrenheit = my_module.c_to_f (celsius)
3 Napisz krótki program, aby wygenerować listę pięciu losowych liczb całkowitych od 1 do 20 i wydrukuj je.
4 Napisz krótki program, który drukuje losową liczbę dziesiętną co 3 sekundy przez 30 sekund.
Poznałeś wiele podstawowych elementów programowania komputerowego: dane wejściowe i wyjściowe, zmienne, decyzje, pętle, listy, funkcje, obiekty i moduły. Mam nadzieję, że spodobało ci się wypełnienie mózgu wszystkimi tymi rzeczami! Teraz nadszedł czas, aby zacząć mieć trochę więcej zabawy z programowaniem i Pythonem. W tej części nauczysz się rysować rzeczy na ekranie, takie jak linie, kształty, kolory, a nawet odrobinę animacji. Pomoże nam to w tworzeniu niektórych gier i innych programów w następnych kilku częściach.
Uzyskiwanie pomocy - Pygame
Uzyskanie grafiki (i dźwięku) do pracy na komputerze może być trochę skomplikowane. Dotyczy to systemu operacyjnego, karty graficznej i wielu kodów niskiego poziomu, na które tak naprawdę nie chcemy się teraz martwić. Dlatego będziemy używać modułu Pythona o nazwie Pygame, aby ułatwić trochę rzeczy. Pygame pozwala tworzyć grafikę i inne rzeczy, których potrzebujesz, aby gry działały na różnych komputerach i systemach operacyjnych, bez konieczności poznawania wszystkich bałaganiarskich szczegółów każdego systemu. Pygame jest darmowe. Powinien zostać zainstalowany, jeśli instalator Pythona użył go.Jeśli nie, musisz zainstalować go osobno. Możesz go pobrać ze strony Pygame, www.pygame.org.
Okno Pygame
Pierwszą rzeczą, którą musimy zrobić, jest stworzenie okna, w którym zaczniemy rysować naszą grafikę. Oto bardzo prosty program, który tworzy okno Pygame.
Listing 17.1 Tworzenie okna Pygame
import pygame
pygame.init ()
screen = pygame.display.set_mode ([640, 480])
Spróbuj uruchomić ten program. Co widzisz? W zależności od posiadanego systemu operacyjnego na ekranie może pojawić się okno (wypełnione czarnym). Możesz też uzyskać okno, które nie zamyka się, gdy próbujesz je zamknąć. Co z tym? Cóż, Pygame jest przeznaczony do tworzenia gier. Gry nie robią rzeczy same - muszą wchodzić w interakcje z odtwarzaczem. Więc programy Pygame mają coś, co nazywa się pętlą zdarzeń, która stale sprawdza, czy użytkownik coś robi, np. naciskanie klawiszy, poruszanie myszą lub zamykanie okna. Programy Pygame muszą mieć uruchomioną pętlę zdarzeń przez cały czas. W naszym pierwszym programie Pygame nie uruchomiliśmy pętli zdarzeń, więc program nie działał poprawnie. Sposób działania pętli zdarzeń Pygame polega na użyciu pętli while. Chcemy, aby pętla działała tak długo, jak długo użytkownik uruchamia naszą grę. Ponieważ programy Pygame zazwyczaj nie mają menu, użytkownik zamknie program za pomocą X w prawym górnym rogu okna (w systemie Windows ) lub przycisk zamykania w lewym górnym rogu (dla MacOS). W systemach Linux ikona zamknięcia okna różni się w zależności od używanego menedżera okien i używanego interfejsu GUI - ale jeśli używasz Linuksa, zakładam, że wiesz, jak zamknąć okno! Kod na następnej liście otwiera okno Pygame i utrzymuje je otwarte, dopóki użytkownik nie zamknie okna
Listing 17.2 Dokonywanie poprawnego działania okna Pygame
import pygame
pygame.init()
screen = pygame.display.set_mode([640, 480])
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Uruchom listing i powinieneś zobaczyć okno Pygame, które działa poprawnie i zamyka się, gdy próbujesz je zamknąć. Jak dokładnie działa kod w tej pętli? Używa pętli zdarzeń Pygame. Ale zamierzamy zapisać ten temat w części 18, gdzie rozmawiamy o wydarzeniach w Pygame.
Rysowanie w oknie
Teraz mamy okno Pygame, które pozostaje otwarte, dopóki go nie zamkniemy - i zamyka się z wdziękiem. [640, 480] w trzecim wierszu listingu 17.2 ma rozmiar naszego okna: 640 pikseli szerokości i 480 pikseli wysokości. Zacznijmy rysować tam trochę grafiki. Zmień swój program, aby wyglądał tak.
Listing 17.3 Rysowanie okręgu
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255,255,255]) <- Wypełnia okno białym tłem
pygame.draw.circle(screen, [255,0,0],[100,100], 30, 0) <- Rysuje okrąg
pygame.display.flip() <- Odwraca monitor
Żartuję!
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Co to jest "flip"?
Obiekt wyświetlany w Pygame ma dwie kopie tego, co jest wyświetlane w oknie Pygame. Powodem jest to, że kiedy zaczynamy robić animację, chcemy sprawić, aby była jak najbardziej płynna i szybka. Więc zamiast aktualizować wyświetlacz za każdym razem, gdy dokonujemy niewielkiej zmiany w naszej grafice, możemy wprowadzić wiele zmian, a następnie "przerzucić" na nową wersję grafiki. To sprawia, że zmiany pojawiają się od razu, zamiast pojedynczo. W ten sposób nie dostaniemy półokreślonych okręgów (lub kosmitów, czy cokolwiek) na naszym ekranie. Pomyśl o dwóch kopiach jako o bieżącym ekranie i "następnym" ekranie. Bieżący ekran jest tym, co widzisz teraz. "Następny" ekran jest tym, co zobaczysz po wykonaniu klatki. Dokonujesz wszystkich zmian na "następnym" ekranie, a następnie przechodzisz na niego, aby je zobaczyć.
Jak zrobić okrąg
Po uruchomieniu programu na listingu 17.3 powinieneś zobaczyć czerwone kółko w lewym górnym rogu okna, w ten sposób:
Nic dziwnego, że funkcja pygame.draw.circle() rysuje okrąg. Musisz powiedzieć pięć rzeczy:
• Na jakiej powierzchni narysować okrąg. (W tym przypadku znajduje się na powierzchni zdefiniowanej w linii 3, zwanej ekranem, która jest powierzchnią wyświetlania).
• Jakiego koloru ma być. (W tym przypadku jest czerwony, co reprezentuje [255, 0, 0]).
• W jakim miejscu go narysować. (W tym przypadku jest to [100, 100], czyli 100 pikseli w dół i 100 pikseli ponad lewym górnym rogiem.)
• Jaki rozmiar narysować. (W tym przypadku jest to 30, czyli promień w pikselach - odległość od środka okręgu do jego zewnętrznej krawędzi).
• Szerokość linii. (Jeśli szerokość = 0, okrąg jest wypełniany całkowicie, tak jak tutaj.)
Teraz przyjrzymy się tym pięciu szczegółom bardziej szczegółowo.
Słowo piksel to skrót od "picture element". Oznacza to jedną kropkę na ekranie lub na obrazie. Jeśli spojrzysz na zdjęcie za pomocą przeglądarki obrazów i powiększysz (sprawisz, że obraz będzie naprawdę duży), zobaczysz pojedyncze piksele.
Powierzchnie Pygame
Gdybym poprosił cię o narysowanie obrazu w prawdziwym życiu, jednym z twoich pierwszych pytań będzie: "Gdzie powinienem narysować?" W Pygame, to na czym rysujesz, to jest powierzchnia. Powierzchnia wyświetlacza to ta, którą widzisz na ekranie. To ten, który nazwaliśmy screenem w listingu 17.3. Ale program Pygame może mieć wiele powierzchni i można kopiować obrazy z jednej powierzchni na drugą. Możesz także robić rzeczy na powierzchniach, np. obracać je i zmieniać ich rozmiar (czynią je większymi lub mniejszymi). Jak wspomniałem wcześniej, są dwie kopie powierzchni wyświetlacza. W żargonie software′owym mówimy ,że powierzchnia wyświetlacza jest podwójnie buforowana. Jest tak dlatego, że nie otrzymujesz na pół ukończonych kształtów i obrazów narysowanych na ekranie. Narysuj swoje kręgi, kosmitów lub cokolwiek w buforze, a następnie "odwróć" powierzchnię ekranu, aby wyświetlić całkowicie narysowane obrazy.
Kolory w Pygame
System kolorów używany w Pygame jest powszechny w wielu językach i programach komputerowych. Nazywa się RGB. R, G i B oznaczają czerwony, zielony i niebieski. Być może nauczyłeś się na lekcjach, że możesz stworzyć dowolny kolor, łącząc lub mieszając trzy podstawowe kolory światła: czerwony, zielony i niebieski. Tak samo działa to na komputerach. Każdy kolor - czerwony, zielony i niebieski - otrzymuje liczbę od 0 do 255. Kolory są podawane jako lista trzech liczb całkowitych, każda w zakresie od 0 do 255. Jeśli wszystkie liczby są równe 0, nie ma żadnego koloru, który jest całkowicie ciemny, więc masz kolor czarny. Jeśli wszystkie mają 255, otrzymasz najjaśniejszy ze wszystkich trzech zmieszanych kolorów, który jest biały. Jeśli masz coś takiego jak [255, 0, 0], będzie to czysta czerwień bez zieleni lub błękitu. Czysta zieleń to e [0, 255, 0]. Czysty niebieski byłby [0, 0, 255]. Jeśli wszystkie trzy liczby są takie same, jak [150, 150, 150], otrzymasz odcień szarości. Im niższe liczby, tym ciemniejszy jest cień; im wyższe liczby, tym jaśniejszy odcień.
Nazwy kolorów
Pygame ma listę nazwanych kolorów, których możesz użyć, jeśli nie chcesz używać notacji [R, G, B]. Zdefiniowano ponad 600 nazw kolorów. Nie będę ich tutaj wszystkich wymieniać, ale jeśli chcesz zobaczyć, czym one są, przeszukaj dysk twardy w poszukiwaniu pliku o nazwie colordict.py i otwórz go w edytorze tekstu. Jeśli chcesz użyć nazw kolorów, musisz dodać ten wiersz na początku programu:
from import pygame.color THECOLORS
Następnie, jeśli chcesz użyć jednego z nazwanych kolorów, zrobisz to w ten sposób (w naszym przykładzie z kręgiem):
pygame.draw.circle (ekran, THECOLORS ["red"], [100,100], 30, 0)
Jeśli chcesz się bawić i eksperymentować z połączeniem kolorów czerwonego, zielonego i niebieskiego do różnych kolorów, możesz wypróbować program colormixer.py. Pozwoli to wypróbować dowolną kombinację czerwieni, zieleni i błękitu, aby zobaczyć, jaki kolor otrzymujesz.
Dlaczego 255? Zakres od 0 do 255 daje nam 256 różnych wartości dla każdego koloru podstawowego (czerwony, zielony i niebieski). Więc co jest specjalnego w tym numerze? Dlaczego nie 200 lub 300 lub 500? Dwieście pięćdziesiąt sześć to liczba różnych wartości, które można uzyskać za pomocą 8 bitów. To wszystkie możliwe kombinacje ośmiu 1-nek i 0-er. Osiem bitów nazywane jest również bajtami, a bajt to najmniejszy fragment pamięci, który ma swój własny adres. Adres to sposób, w jaki komputer znajduje określone fragmenty pamięci. To jak na twojej ulicy. Twój dom lub mieszkanie ma adres, ale twój pokój nie ma własnego adresu. Dom jest najmniejszą "jednostką adresowalną" na ulicy. Bajt to najmniejsza "jednostka adresowalna" w pamięci komputera. Mogliby użyć więcej niż 8 bitów dla każdego koloru, ale następna kwota, która miałaby sens, wynosiłaby 16 bitów (2 bajty), ponieważ nie jest zbyt wygodne używanie tylko części bajtu. Okazuje się, że ze względu na sposób, w jaki ludzkie oko widzi kolor, 8 bitów wystarczy, aby uzyskać realistycznie wyglądające kolory. Ponieważ są trzy wartości (czerwona, zielona, niebieska), każdy z 8 bitsmi, czyli łącznie 24 bity, więc ten sposób reprezentowania koloru jest również znany jako "kolor 24-bitowy". Wykorzystuje 24 bity na każdy piksel, 8 na każdy kolor podstawowy.
Lokalizacje - współrzędne ekranu
Jeśli chcesz narysować lub umieścić coś na ekranie, musisz określić, gdzie na ekranie powinien się znaleźć. Istnieją dwie liczby: jedna dla osi X (kierunek poziomy) i jedna dla osi Y (kierunek pionowy). W Pygame liczby zaczynają się od [0, 0] w lewym górnym rogu okna. Gdy zobaczysz parę liczb takich jak [320, 240], pierwsza liczba jest pozioma lub odległość od lewej strony. Druga liczba jest pionowa lub odległość w dół od góry. W matematyce i programowaniu litera x jest często używana dla odległości poziomej, a y jest często używane dla odległości pionowej. Nasze okno ma szerokość 640 pikseli i wysokość 480 pikseli. Gdybyśmy chcieli umieścić okrąg na środku okna, musielibyśmy go narysować w [320, 240]. To 320 pikseli od lewej krawędzi i 240 pikseli od górnej krawędzi
Spróbujmy narysować okrąg na środku okna. Oto program.
Listing 17.4 Umieszczanie okręgu na środku okna
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
pygame.draw.circle(screen, [255,0,0],[320,240], 30, 0) <- Zmień to z [100, 100] na [320, 240]
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Położenie [320, 240] jest używane jako środek okręgu. Porównaj wyniki uruchomienia wykazu 16.3 z wynikami, które widziałeś, gdy uruchomiłeś listing 17.4, aby zobaczyć różnicę.
Rozmiar kształtów
Kiedy używasz funkcji rysowania Pygame do rysowania kształtów, musisz określić, jaki rozmiar ma kształt. Dla okręgu istnieje tylko jeden rozmiar: promień. W przypadku czegoś takiego jak prostokąt trzeba określić długość i szerokość. Pygame ma specjalny rodzaj obiektu zwany rect (skrót od prostokąt), który jest używany do definiowania prostokątnych obszarów. Definiujesz rect używając współrzędnych lewego górnego rogu oraz jego szerokości i wysokości
rect(left, top, width, height)
Określa zarówno lokalizację, jak i rozmiar. Oto przykład
my_rect = Rect (250, 150, 300, 200)
Spowoduje to utworzenie prostokąta, w którym lewy górny róg ma 250 pikseli od lewej strony okna i 150 pikseli w dół od górnej części okna. Prostokąt ma szerokość 300 pikseli i wysokość 200 pikseli. Spróbujmy i zobacz. Zamień ten wiersz na wiersz 5 na listing 17.4 i zobacz, jak to wygląda:
pygame.draw.rect (screen, [255,0,0], [250, 150, 300, 200], 0
Położenie i rozmiar prostokąta może być prostą listą (lub krotką) liczb lub obiektu Pygame Rect. Możemy więc zastąpić poprzednią linię dwoma liniami takimi jak ten
my_list = [250, 150, 300, 200]
pygame.draw.rect(screen, [255,0,0], my_list, 0)
lub
my_rect = pygame.Rect(250, 150, 300, 200)
pygame.draw.rect(screen, [255,0,0], my_rect, 0)
Oto, jak powinien wyglądać prostokąt. Dodałem kilka wymiarów, aby pokazać, które liczby oznaczają co:
Zauważ, że przekazujemy tylko cztery argumenty do pygame.draw.rect. To dlatego, że rect ma zarówno lokalizację, jak i rozmiar w jednym argumencie. W pygame.draw.circle położenie i rozmiar są dwoma różnymi argumentami, więc przekazujemy mu pięć argumentów.
Myślenie jak programista (Pygame)
Po utworzeniu prostokąta z Rect (lewy, górny, szerokość, wysokość) istnieje kilka innych atrybutów, których można użyć do przesunięcia i wyrównania Rect:
o cztery krawędzie: top, left, down, right
o cztery rogi: topleft, bottomleft, topright, bottomright
o środek każdej strony: midtop, midleft, midbottom, midright
o centrum: centrum, centrum, centrum
o wymiary: size, width, height
Są tylko dla wygody. Jeśli więc chcesz przesunąć prostokąt, tak aby jego środek znajdował się w określonym punkcie, nie musisz się zastanawiać, gdzie współrzędne górne i lewe powinny być; możesz uzyskać bezpośredni dostęp do lokalizacji centrum.
Szerokość linii
Ostatnią rzeczą, którą musisz określić podczas rysowania kształtów, jest grubość linii. W przykładach użyliśmy szerokości linii 0, która wypełnia cały kształt. Jeśli użyjemy innej szerokości linii, zobaczymy zarys kształtu. Spróbuj zmienić szerokość linii na 2:
pygame.draw.rect (ekran, [255,0,0], [250, 150, 300, 200], 2)
Wypróbuj i zobacz, jak to wygląda. Wypróbuj także inne szerokości linii.
Sztuka współczesna?
Chcesz spróbować stworzyć nowoczesną sztukę komputerową? Dla zabawy wypróbuj kod z listingu 17.5. Możesz zacząć od tego, co miałeś na listingu 17.4 i zmodyfikować go lub zacząć od zera.
Listing 17.5 Używanie funkcji draw.rect do tworzenia sztuki
import pygame, sys, random
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
for i in range (100):
width = random.randint(0, 250)
height = random.randint(0, 100)
top = random.randint(0, 400)
left = random.randint(0, 500)
pygame.draw.rect(screen, [0,0,0], [left, top, width, height], 1)
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Uruchom to i zobacz, co otrzymasz. Powinno wyglądać mniej więcej tak:
Czy rozumiesz, jak działa program? Rysuje 100 prostokątów o losowych rozmiarach i pozycjach. Aby uczynić go jeszcze bardziej "artystycznym", dodaj trochę koloru i ustaw losowo szerokość linii, jak na poniższej liście.
Listing 17.6 Sztuka współczesna w kolorze
import pygame, sys, random
from pygame.color import THECOLORS
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
for i in range (100):
width = random.randint(0, 250); height = random.randint(0, 100)
top = random.randint(0, 400); left = random.randint(0, 500)
color_name = random.choice(THECOLORS.keys())
color = THECOLORS[color_name]
line_width = random.randint(1, 3)
pygame.draw.rect(screen, color, [left, top, width, height], line_width)
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Po uruchomieniu otrzymasz coś, co za każdym razem wygląda inaczej. Jeśli otrzymasz wynik, który wygląda naprawdę ładnie, nadaj mu fantazyjny tytuł, taki jak "Voice of the Machine" i sprawdź, czy możesz go sprzedać swojej lokalnej galerii sztuki!
Pojedyncze piksele
Czasami nie chcesz rysować okręgu lub prostokąta, ale chcesz narysować pojedyncze kropki lub piksele. Może tworzysz program matematyczny i chcesz na przykład narysować falę sinusoidalną.
Nie martw się, jeśli nie wiesz, co to jest sinusoida. Dla celów tej części jest to tylko falisty kształt. Nie martw się również o formuły matematyczne w kolejnych kilku przykładowych programach. Po prostu wpisz je tak, jak pojawiają się na aukcjach. Są tylko sposobem na uzyskanie falistego kształtu, który jest ładnym rozmiarem, aby wypełnić nasze okno Pygame.
Ponieważ nie ma metody pygame.draw.sinewave (), musimy narysować ją sami z poszczególnych punktów. Jednym ze sposobów jest narysowanie maleńkich okręgów lub prostokątów o rozmiarze zaledwie jednego lub dwóch pikseli. Poniższy listing pokazuje, jak wyglądałoby to przy użyciu prostokątów.
Listing 17.7 Rysowanie krzywych za pomocą wielu małych prostokątów
import pygame, sys
import math <- Importuje funkcje matematyczne, w tym sin()
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255]) <- Pętle od lewej do prawej, x = 0 do 63
for x in range(0, 640):
y = int(math.sin(x/640.0 * 4 * math.pi) * 200 + 240)<- Oblicza położenie (w pionie) każdego punktu
pygame.draw.rect(screen, [0,0,0],[x, y, 1, 1], 1) <-Rysuje punkt za pomocą małego prostokąta
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
A oto jak wygląda, gdy działa:
Aby narysować każdy punkt, użyliśmy prostokąta o szerokości 1 piksela i wysokości 1 piksela. Zauważ, że użyliśmy również szerokości linii 1, a nie 0. Jeśli użyjemy szerokości linii 0, nic się nie pojawi, ponieważ nie ma "środkowego" wypełnienia.
Połącz kropki
Jeśli przyjrzysz się naprawdę uważnie, możesz zauważyć, że fala sinusoidalna nie jest ciągła - między punktami w środku znajdują się spacje. To dlatego, że na stromej części fali sinusoidalnej musimy poruszać się w górę (lub w dół) o 3 piksele, gdy przesuniemy się o jeden piksel w prawo. I ponieważ rysujemy pojedyncze punkty, a nie linie, nic nie wypełnia przestrzeni między nimi. Spróbujmy tego samego, używając krótkiej linii, aby dołączyć do każdego punktu fabuły. Pygame ma metodę rysowania pojedynczej linii, ale ma również metodę, która będzie rysować linie między seriami punktów (np. "Łącz kropki"). Ta metoda to pygame.draw.lines () i potrzebuje pięciu parametrów:
• Powierzchnia do rysowania.
• Kolor.
• Czy kształt zostanie zamknięty przez narysowanie linii łączącej ostatni punkt z powrotem do pierwszego. Nie chcemy dołączać naszej fali sinusoidalnej, więc będzie to dla nas fałszywe.
• Lista punktów do połączenia.
• Szerokość linii.
W naszym przykładzie fali sinusoidalnej metoda pygame.draw.lines () wyglądałaby następująco:
pygame.draw.lines (ekran, [0,0,0], False, plotPoints, 1)
W pętli for zamiast rysować każdy punkt, utworzymy listę punktów, z którymi będzie się łączyć draw.lines (). Następnie mamy pojedyncze wywołanie draw.lines (), które znajduje się poza pętlą for. Cały program zostanie wyświetlony w następnej kolejności.
Listing 17.8 Dobrze połączona fala sinusoidalna
import pygame, sys
import math
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
plotPoints = []
for x in range(0, 640):
y = int(math.sin(x/640.0 * 4 * math.pi) * 200 + 240)<- Oblicza pozycję y dla każdego punktu
plotPoints.append([x, y]) <- Dodaje każdy punkt do listy
pygame.draw.lines(screen, [0,0,0],False, plotPoints, 1) <- Rysuje całą krzywą za pomocą funkcji draw.lines()
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Teraz, gdy go uruchomimy, wygląda to tak:
To lepiej - nie ma luk między punktami. Jeśli zwiększymy szerokość linii do 2, wygląda jeszcze lepiej:
Połącz kropki ponownie
Pamiętasz te łamigłówki, które robiłeś, kiedy byłeś młody? Oto Pygameversion. Program na listingu 17.9 tworzy kształt za pomocą funkcji draw.lines() i listy punktów. Aby ujawnić tajny obraz, wpisz program. Tym razem nie ma oszustwa!
Listing 17.9 Tajemniczy obrazek "Połącz kropki"
import pygame, sys
pygame.init()
dots = [[221, 432], [225, 331], [133, 342], [141, 310],
[51, 230], [74, 217], [58, 153], [114, 164],
[123, 135], [176, 190], [159, 77], [193, 93],
[230, 28], [267, 93], [301, 77], [284, 190],
[327, 135], [336, 164], [402, 153], [386, 217],
[409, 230], [319, 310], [327, 342], [233, 331],
[237, 432]]
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
pygame.draw.lines(screen, [255,0,0],True, dots, 2)
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Rysowanie punkt po punkcie
Wróćmy na chwilę do rysowania punkt po punkcie. Wydaje się głupie rysowanie małego okręgu lub prostokąta, gdy wszystko, co chcemy zrobić, to zmienić kolor jednego piksela. Zamiast korzystać z funkcji rysowania, można uzyskać dostęp do każdego pojedynczego piksela na powierzchni za pomocą metody Surface.set_at (). Mówisz, jaki piksel chcesz ustawić i jaki kolor ustawić:
screen.set_at ([x, y], [0, 0, 0])
Jeśli użyjemy tej linii kodu w naszym przykładzie fali sinusoidalnej (zamiast linii 8 na liście 16.7), wygląda to tak samo, jak w przypadku prostokątów o szerokości jednego piksela Można również sprawdzić, w jakim kolorze piksel jest już ustawiony metoda Surface.get_at (). Po prostu przekazujesz mu współrzędne piksela, który chcesz sprawdzić, tak jak poniżej: pixel_color = screen.get_at ([320, 240]). W tym przykładzie ekran był nazwą powierzchni.
Obrazy
Rysowanie kształtów, linii i pojedynczych pikseli na ekranie jest jednym ze sposobów wykonywania grafiki. Ale czasami chcemy używać obrazów, które otrzymujemy z innego miejsca - może ze zdjęcia cyfrowego, czegoś, co pobraliśmy z Internetu lub czegoś stworzonego w programie do edycji obrazów. W Pygame najprostszym sposobem użycia obrazów jest funkcja obrazu. Powinieneś skopiować plik beach_ball.png do dowolnego miejsca w którym zapisujesz swoje programy w Pythonie podczas pracy z tymi przykładami. W ten sposób Python może go łatwo znaleźć, gdy program działa. Po znalezieniu pliku beach_ball.png we właściwej lokalizacji wpisz program z listingu 17.10 i wypróbuj go.
Listing 17.10 Wyświetlanie obrazu piłki plażowej w oknie Pygame
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
my_ball = pygame.image.load("beach_ball.png")
screen.blit(my_ball, [50, 50])
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Po uruchomieniu tego programu powinieneś zobaczyć obraz piłki plażowej wyświetlany w lewym górnym rogu okna Pygame, w ten sposób:
W listingu 17.10 jedynymi nowymi liniami są linie 5 i 6. Wszystko, co widziałeś wcześniej w listingach 17.3 do 17.9. Zastąpiliśmy kod z naszych poprzednich przykładów kodem, który ładuje obraz z dysku i wyświetla go. W linii 5 funkcja pygame.image.load() ładuje obraz z dysku i tworzy obiekt o nazwie my_ball. Obiekt my_ball jest powierzchnią. (Rozmawialiśmy o powierzchniach kilka stron temu.) Ale nie widzimy tej powierzchni. To tylko w pamięci. Jedyną powierzchnią, jaką możemy zobaczyć, jest powierzchnia wyświetlacza, która nazywana jest ekranem. (Stworzyliśmy go w linii 3.) Linia 6 kopiuje powierzchnię my_ball na powierzchnię ekranu. Następnie display.flip() sprawia, że jest widoczny, tak jak wcześniej. Być może zauważyłeś zabawnie wyglądającą rzecz w linii 6 listy 16.10: screen.blit (). Co oznacza Blit? Zobacz "WORD BOX", aby się dowiedzieć.
Robiąc programowanie graficzne, kopiowanie pikseli z jednego miejsca do drugiego jest czymś, co robimy całkiem sporo (np. kopiowanie ze zmiennej na ekran lub z jednej powierzchni na drugą). Kopiowanie pikseli ma specjalną nazwę w programowaniu. To się nazywa blitting. Mówimy, że mieszamy obraz (lub część obrazu lub tylko kilka pikseli) z jednego miejsca do drugiego. To po prostu fantazyjny sposób powiedzenia "kopia", ale kiedy zobaczysz "blit", wiesz, że odnosi się to do kopiowania pikseli, a nie kopiowania innych rzeczy.
W Pygame kopiujesz lub mieszasz piksele z jednej powierzchni na drugą. Tutaj skopiowaliśmy piksele z powierzchni my_ball na powierzchnię ekranu. W linii 6 listingu 16.10 zmyliśmy obraz piłki plażowej do lokalizacji 50, 50. Oznacza to 50 pikseli od lewej krawędzi i 50 pikseli od góry okno. Gdy pracujesz z powierzchnią lub prostokątem, ustawia to położenie lewego górnego rogu obrazu.
Lewa krawędź piłki plażowej wynosi 50 pikseli od lewej krawędzi okna, a górna krawędź piłki plażowej wynosi 50 pikseli od górnej krawędzi okna.
Ruszajmy się!
Teraz, kiedy możemy pobrać grafikę do naszego okna Pygame, zacznijmy je przenosić. To prawda, zamierzamy zrobić animację! Animacja komputerowa polega po prostu na przenoszeniu obrazów (grup pikseli) z jednego miejsca na drugie. Spróbujmy przenieść naszą piłkę plażową. Aby ją przenieść, musimy zmienić jej lokalizację. Po pierwsze, spróbujmy przesunąć ją w bok. Aby upewnić się, że widzimy ruch, przesuńmy ją o 100 pikseli w prawo. Kierunek lewy-prawy (poziomy) jest pierwszym numerem w parze liczb określającym położenie. Aby przesunąć coś o prawo o 100 pikseli, musimy zwiększyć pierwszą liczbę o 100. Zrobimy także opóźnienie, abyśmy mogli zobaczyć, jak animacja się wydarzyła. Zmień program z listy 16.10, aby wyglądał jak ten z listingu 17.11. (Musisz dodać linie 8, 9 i 10 przed pętlą while.)
Listing 17.11 Próba przesunięcia piłki plażowej
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
my_ball = pygame.image.load('beach_ball.png')
screen.blit(my_ball,[50, 50])
pygame.display.flip()
pygame.time.delay(2000)
screen.blit(my_ball,[150, 50])
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Uruchom program i zobacz, co się stanie. Zrobiłem piłkę
Rusza się? Cóż, w pewnym sensie. Powinieneś zobaczyć dwie piłki plażowe:
Pierwszy pojawił się w pierwotnej pozycji, a drugi pojawił się po prawej stronie kilka sekund później. Więc przesunęliśmy piłkę plażową w prawo, ale zapomnieliśmy o jednej rzeczy. Musimy usunąć pierwszą piłkę!
Animacja
Kiedy robisz animację z grafiką komputerową, są dwa kroki do przeniesienia czegoś:
1 Narysuj rzecz w nowej pozycji.
2 Wymazujesz rzecz ze starej pozycji.
Widziałeś już pierwszą część. Narysowaliśmy piłkę w nowej pozycji. Teraz musimy wymazać piłkę z miejsca, w którym była wcześniej. Ale co tak naprawdę znaczy "wymazywanie"?
Kasowanie obrazów
Kiedy rysujesz coś na papierze lub na tablicy, łatwo to usunąć. Używasz tylko gumki, prawda? Ale co, jeśli zrobiłeś obraz? Powiedzmy, że zrobiłeś obraz błękitnego nieba, a potem pomalowałeś ptaka na niebie. Jak "skasujesz" ptaka? Nie możesz usunąć farby. Musiałbyś namalować jakieś nowe błękitne niebo tam gdzie był ptak. Grafika komputerowa jest jak farba, a nie jak ołówek lub kreda. Aby "wymazać" coś, naprawdę musisz "pomalować" to. Ale z czym to malujesz? W przypadku twojego malowania nieba niebo jest niebieskie, więc będziesz malował go na niebiesko. Nasze tło jest białe, więc musimy pomalować oryginalny obraz piłki plażowej białym. Spróbujmy tego. Zmodyfikuj program z listingu 17.11, aby pasował do następującej listy. Do dodania jest tylko jedna nowa linia.
Listing 17.12 Próba ponownego przesunięcia piłki plażowej
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
my_ball = pygame.image.load('beach_ball.png')
screen.blit(my_ball,[50, 50])
pygame.display.flip()
pygame.time.delay(2000)
screen.blit(my_ball, [150, 50])
pygame.draw.rect(screen, [255,255,255], [50, 50, 90, 90], 0)<- Ta linia "wymazuje" pierwszą piłkę
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Dodaliśmy linię 10, aby narysować biały prostokąt nad pierwszą piłką plażową. Obraz piłki plażowej ma około 90 pikseli szerokości i 90 pikseli wysokości, więc to, jak duży zrobiliśmy biały prostokąt. Jeśli uruchomisz program na liście 16.12, powinien on wyglądać tak, jakby piłka plażowa przesunęła się z oryginalnej lokalizacji do nowej lokalizacji.
Co tam jest?
Malowanie na białym tle (lub błękitne niebo na obrazie) jest dość łatwe. Ale co, jeśli pomalowałeś ptaka na pochmurnym niebie? Albo na tle drzew? Następnie musisz pomalować ptaka chmurami lub drzewami, aby go wymazać. Ważną ideą jest to, żeby śledzić, co znajduje się w tle, "pod" obrazami, ponieważ gdy je przenosisz, musisz odłożyć lub odmalować to, co było wcześniej. Jest to całkiem łatwe dla naszego przykładu piłki plażowej, ponieważ tło jest tylko białe. Ale gdyby tło było sceną plaży, byłoby trudniejsze. Zamiast malować tylko na biało musielibyśmy namalować prawidłową część obrazu tła. Inną opcją byłoby przemalowanie całej sceny, a następnie umieszczenie piłki plażowej w nowym miejscu.
Płynniejsza animacja
Jak dotąd poruszyliśmy naszą piłkę raz! Zobaczmy, czy uda nam się to poruszyć w bardziej realistyczny sposób. Podczas animowania rzeczy na ekranie dobrze jest przesuwać je małymi krokami, aby ruch był gładki. Spróbujmy przesunąć naszą piłkę w mniejszych krokach. Nie będziemy tylko zmniejszać liczby kroków - dodamy pętlę, aby przesunąć piłkę (ponieważ chcemy zrobić wiele małych kroków). Począwszy od listingu 17.12, edytuj kod, aby wyglądał tak.
Listing 17.13 Płynne przesuwanie obrazu piłki plażowej
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
my_ball = pygame.image.load('beach_ball.png')
x = 50
y = 50 <-Dodajemy te linie
screen.blit(my_ball,[x, y]) <- Używa x i y (zamiast liczb)
pygame.display.flip()
for looper in range (1, 100): <- Rozpoczyna pętlę for
pygame.time.delay(20) <- Wartość time.delay zmieniła się z 2000 na 20
pygame.draw.rect(screen, [255,255,255], [x, y, 90, 90], 0)
x = x + 5
screen.blit(my_ball, [x, y])
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Jeśli uruchomisz ten program, zobaczysz, że piłka porusza się z pierwotnej pozycji na prawą stronę okna
Utrzymywanie piłki w ruchu
W poprzednim programie piłka przesunęła się na prawą stronę okna, a następnie zatrzymała. Teraz spróbujemy utrzymać piłkę w ruchu. Jeśli będziemy zwiększać x, co się stanie? Piłka będzie się przesuwać w prawo, gdy jej wartość x wzrasta. Ale nasze okno (powierzchnia wyświetlacza) zatrzymuje się przy x = 640. Więc piłka zniknie. Spróbuj zmienić pętlę for w wierszu 10 listingu 17.13 na:
for looper in range (1, 200):
Teraz, gdy pętla działa dwa razy dłużej, piłka znika z krawędzi! Jeśli chcemy kontynuować oglądanie piłki, mamy dwie możliwości:
• Sprawiamy, że piłka odbija się od boku okna.
• Sprawiamy, że piłka zawija się na drugą stronę okna.
Spróbujmy obu sposobów, aby zobaczyć, jak to zrobić.
Odbijając piłkę
Jeśli chcemy sprawić, by piłka odbijała się od boku okna, musimy wiedzieć, kiedy "uderzy" ona w krawędź okna, a następnie musimy odwrócić jej kierunek. Jeśli chcemy, aby piłka poruszała się tam i z powrotem, musimy to zrobić zarówno na lewej, jak i prawej krawędzi okna. Po lewej stronie jest to łatwe, ponieważ po prostu sprawdzamy, czy pozycja piłki wynosi 0 (lub jakąś małą liczbę). Po prawej stronie musimy sprawdzić, czy prawa strona piłki znajduje się po prawej stronie okna. Ale pozycja piłki jest ustawiana od lewej strony (górny lewy róg), a nie od prawej strony. Musimy więc odjąć szerokość piłki:
Gdy piłka porusza się w kierunku prawej krawędzi okna, musimy ją odbić (odwrócić jej kierunek), gdy jej pozycja wynosi 550. Aby to ułatwić, wprowadzimy kilka zmian w naszym kodzie:
• Będziemy mieć piłkę podskakującą na zawsze (lub dopóki nie zamkniemy okna Pygame). Ponieważ mamy już pętlę, która działa tak długo, jak długo okno jest otwarte, przeniesiemy nasz kod wyświetlania kulki do tej pętli. (To pętla while, która jest w ostatniej części programu.)
• Zamiast zawsze dodawać 5 do pozycji piłki, zrobimy nową zmienną, speed, aby określić, jak szybko poruszyć piłkę przy każdej iteracji. Będziemy również nieco przyspieszać, ustawiając tę wartość na 10.
Nowy kod znajduje się na poniższej liście.
Listing 17.14 Odbijanie piłki plażowej
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
my_ball = pygame.image.load('beach_ball.png')
x = 50
y = 50
x_speed = 10 <- Oto zmienna szybkości
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.time.delay(20)
pygame.draw.rect(screen, [255,255,255], [x, y, 90, 90], 0)
x = x + x_speed <- Oto zmienna szybkości
if x > screen.get_width() - 90 or x < 0: <-Gdy piłka uderza w dowolną krawędź okna
x_speed = - x_speed <-
odwraca kierunek, czyniąc prędkość przeciwnym znakiem
screen.blit(my_ball, [x, y])
pygame.display.flip()
pygame.quit()
Kluczem do odbicia piłki od boków okna są linie 19 i 20. W linii 19 (jeśli x> screen.get_width () - 90 lub x <0 :), wykrywamy, czy piłka znajduje się na skraju okno, a jeśli tak, odwracamy jego kierunek w linii 20 (x_speed = - x_speed). Spróbuj tego i zobacz, jak to działa.
Odbijanie w 2-D
Do tej pory piłka porusza się tylko w tę iz powrotem lub w ruchu jednowymiarowym. Przejdźmy teraz w górę iw dół w tym samym czasie. Aby to zrobić, potrzebujemy tylko kilku zmian, jak pokazano tutaj
Listing 17.15 Odbijanie piłki plażowej w 2-D
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
my_ball = pygame.image.load('beach_ball.png')
x = 50
y = 50
x_speed = 10
y_speed = 10 <- Dodaj kod dla prędkości y (ruch pionowy)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.time.delay(20)
pygame.draw.rect(screen, [255,255,255], [x, y, 90, 90], 0)
x = x + x_speed
y = y + y_speed <-Dodaj kod dla prędkości y (ruch pionowy)
if x > screen.get_width() - 90 or x < 0:
x_speed = - x_speed
if y > screen.get_height() - 90 or y < 0: <- Odbija piłkę od
y_speed = -y_speed <- góry lub dołu okna
screen.blit(my_ball, [x, y])
pygame.display.flip()
pygame.quit()
Dodaliśmy linie 9 (y_speed = 10), 18 (y = y + y_speed), 21 (jeśli y> screen.get_height () - 90 lub y <0 :), a 22 (y_speed = -y_speed) do poprzedniego programu . Wypróbuj teraz i zobacz, jak to działa!
Jeśli chcemy spowolnić piłkę, można to zrobić na kilka sposobów:
• Możemy zmniejszyć zmienne prędkości (x_speed i y_speed). Zmniejsza to, jak daleko piłka porusza się w każdym kroku animacji, więc ruch będzie również gładszy.
• Możemy również zwiększyć ustawienie opóźnienia. W listingu 16.15 jest 20. To jest mierzone w milisekundach, czyli tysięcznych sekundy. Tak więc za każdym razem w pętli program czeka przez 0,02 sekundy. Jeśli zwiększymy tę liczbę, ruch zwolni. Jeśli go zmniejszymy, ruch przyspieszy.
Spróbuj grać z prędkością i opóźnieniem, aby zobaczyć efekty.
Zawijanie piłki
Spójrzmy teraz na drugą opcję, aby utrzymać piłkę w ruchu. Zamiast odbijać go od ekranu, będziemy go zawijać. Oznacza to, że gdy piłka zniknie z prawej strony ekranu, pojawi się ponownie po lewej stronie. Aby to uprościć, wrócimy do zwykłego przesuwania piłki w poziomie. Program znajduje się na następnym listingu
Listing 17.16 Przenoszenie obrazu piłki plażowej z zawijaniem
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
my_ball = pygame.image.load('beach_ball.png')
x = 50
y = 50
x_speed = 5
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.time.delay(20)
pygame.draw.rect(screen, [255,255,255], [x, y, 90, 90], 0)
x = x + x_speed
if x > screen.get_width(): <-Jeśli piłka jest po prawej stronie
x = 0 <-
zacznij od lewej strony
screen.blit(my_ball, [x, y])
pygame.display.flip()
pygame.quit()
W wierszach 17 (jeśli x> screen.get_width () :) i 18 (x = 0) wykryliśmy, że piłka dotarła do prawej krawędzi okna, a my przesunęliśmy ją z powrotem lub zawinęliśmy z powrotem na lewą stronę . Być może zauważyłeś, że kiedy piłka pojawia się po prawej stronie, "pojawia się" w [0, 50]. Wyglądałoby to bardziej naturalnie, gdyby "wsunął się" z ekranu. Zmień linię 18 (x = 0) na x = -90 i zobacz, czy zauważysz różnicę.
Czego się nauczyłeś?
• Jak korzystać z Pygame
• Jak utworzyć okno graficzne i narysować w nim niektóre kształty
• Jak ustawić kolory w grafice komputerowej
• Jak kopiować obrazy do okna graficznego
• Jak animować obrazy, w tym "wymazywać" je, gdy przenosisz je do nowego miejsca
• Jak sprawić, aby piłka plażowa "odbijała się" wokół okna
• Jak sprawić, aby piłka plażowa "zawijała się" wokół wiatru
Sprawdź swoją wiedzę
1 Jakiego koloru jest wartość RGB [255, 255, 255]?
2 Jakiego koloru jest wartość RGB [0, 255, 0]?
3 Jakiej metody Pygame możesz użyć do rysowania prostokątów?
4 Jakiej metody Pygame możesz użyć do narysowania linii łączących kilka punktów?
5 Co oznacza termin piksel?
6 Gdzie w oknie Pygame znajduje się lokalizacja [0, 0]?
7 Jeśli okno Pygame ma 600 pikseli szerokości i 400 pikseli wysokości, jaka litera na poniższym diagramie znajduje się w [50, 200]?
8 Jaka litera na diagramie znajduje się w lokalizacji [300, 50]?
9 Jaka jest metoda Pygame do kopiowania obrazów na powierzchnię (jak powierzchnia wyświetlania)?
10 Jakie są dwa główne etapy "poruszania się" lub animowania obrazu?
Wypróbuj to
1 Rozmawialiśmy o rysowaniu okręgów i prostokątów. Pygame ma również metody rysowania linii, łuków, elips i wielokątów. Spróbuj użyć ich do narysowania innych kształtów w programie. Więcej informacji na temat tych metod można znaleźć w dokumentacji Pygame na stronie www.pygame.org/docs/ref/draw.html. Jeśli nie masz dostępu do Internetu, możesz go również znaleźć na dysku twardym (jest zainstalowany z Pygame), ale może być trudno go znaleźć. Wyszukaj na dysku twardym plik o nazwie pygame_draw.html. Możesz także użyć systemu pomocy Pythona. Jedną z rzeczy, których SPE nie ma, jest interaktywna powłoka, która działa, więc uruchom IDLE i wpisz następujące:
>>> import pygame
>>> help ()
help> pygame.draw
Otrzymasz listę różnych metod rysowania i wyjaśnienia dla każdego z nich.
2 Spróbuj zmienić jeden z przykładowych programów, które używają obrazu piłki plażowej, aby użyć innego obrazu. Możesz znaleźć przykładowe obrazy w folderze przykładów lub pobrać lub narysować jeden z własnych. Możesz także użyć fragmentu zdjęcia cyfrowego.
3 Spróbuj zmienić wartości x_speed i y_speed w listingu 17.15 lub 17.16, aby utworzyć piłkę która porusza się szybciej lub wolniej i w różnych kierunkach.
4 Spróbuj zmienić listing 17.15, aby piłka "odbijała się" od niewidzialnej ściany lub podłogi, która nie jest krawędzią okna.
5 W listingu 17.5 do 17.9 (programy współczesnej sztuki, sinusoida i tajemniczy obraz) spróbuj przesunąć linię pygame.display.flip wewnątrz pętli while. Aby to zrobić, wystarczy wcisnąć cztery spacje. Po tej linii, a także wewnątrz pętli while, dodaj opóźnienie za pomocą tej linii i zobacz, co się stanie:
pygame.time.delay (30)
W tej części będziemy kontynuować używanie animacji Pygame. Zobaczymy rzeczy zwane sprite′ami, które pomagają nam śledzić wiele obrazów poruszających się na ekranie. Zobaczymy również, jak wykryć, kiedy dwa obrazy nakładają się na siebie lub uderzają o siebie, na przykład kiedy piłka uderza w wiosło lub statek kosmiczny uderza w asteroidę.
Duszki
W ostatniej części zobaczyłeś, że prosta animacja nie jest wcale taka prosta. Jeśli masz dużo obrazów i przenosisz je dookoła, śledzenie tego, co jest "pod" każdym obrazem, może być bardzo trudne, dzięki czemu możesz odświeżyć obraz po przesunięciu. W naszym pierwszym przykładzie z piłką plażową tło było tylko białe, więc było łatwiej. Ale możesz sobie wyobrazić, że z grafiką w tle będzie się to komplikować. Na szczęście Pygame zapewnia dodatkową pomoc. Poszczególne obrazy lub części obrazu, które się poruszają, nazywane są duszkami, a Pygame ma specjalny moduł do obsługi duszków, sprite. Pozwala to łatwiej przenosić obiekty graficzne. W ostatniej części podskoczyliśmy na plaży. A co, jeśli chcemy, aby cała masa piłek plażowych podskakiwała? Moglibyśmy napisać kod, aby zarządzać każdą piłką indywidualnie, ale zamiast tego użyjemy modułu sprite. Pygame, aby ułatwić sobie pracę. Sprite oznacza grupę pikseli, które są przenoszone i wyświetlane jako pojedyncza jednostka, rodzaj obiektu graficznego.
Termin "sprite" jest zapisem ze starszych komputerów i maszyn do gier. Te starsze pudełka nie były w stanie szybko rysować i usuwać normalnej grafiki, aby mogły działać jako gry. Maszyny te miały specjalny sprzęt do obsługi obiektów podobnych do gry, które musiały być Obiekty te nazywano "duszkami" i miały specjalne ograniczenia, ale można je było szybko rysować i aktualizować. W dzisiejszych czasach komputery stały się na ogół wystarczająco szybkie, aby obsługiwać obiekty sprite bez dedykowanego sprzętu.
Co jest sprite?
Pomyśl o duszku jako małej grafice - rodzaju obiektu graficznego, który będzie poruszał się po ekranie i wchodził w interakcje z innymi obiektami graficznymi. Większość duszków ma kilka podstawowych właściwości:
• image - grafika wyświetlana dla ikonki
• rect - prostokątny obszar zawierający ikonkę
Obraz może być taki, który narysujesz za pomocą funkcji rysowania Pygame lub takiego, który otrzymujesz z pliku obrazu.
Klasa sprite
Moduł sprite Pygame zapewnia klasę sprite bazową o nazwie Sprite. (Pamiętaj, kiedy rozmawialiśmy o obiektach i klasach kilka rozdziałów temu?). Zwykle nie używasz bezpośrednio klasy bazowej, ale zamiast tego utwórz własną podklasę opartą na pygame.sprite.Sprite. Zróbmy to w przykładzie i wywołajmy klasę
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self) <- Inicjuje sprite′a
self.image = pygame.image.load(image_file)<- Ładuje do niego plik obrazu
self.rect = self.image.get_rect() <- Pobiera prostokąt określający granice obrazu
self.rect.left, self.rect.top = location <- Ustawia początkową lokalizację piłki
Ostatniemu wierszowi tego kodu warto przyjrzeć się bliżej. lokalizacja to lokalizacja [x, y], która jest listą z dwoma elementami. Ponieważ mamy listę z dwoma elementami po jednej stronie znaku = (x i y), możemy przypisać dwie rzeczy po drugiej stronie. Tutaj przypisaliśmy lewy i górny atrybut prostokąta prostego. Teraz, gdy zdefiniowaliśmy MyBallClass, musimy utworzyć kilka jego wystąpień. (Pamiętaj, że definicja klasy to tylko plan; teraz musimy zbudować kilka domów.) Nadal potrzebujemy tego samego kodu, którego użyliśmy w ostatnim rozdziale, aby utworzyć okno Pygame. Będziemy także tworzyć kilka kulek na ekranie, ułożonych w rzędy i kolumny. Zrobimy to za pomocą zagnieżdżonej pętli:
img_file = "beach_ball.png"
balls = []
for row in range (0, 3):
for column in range (0, 3):
location = [column * 180 + 10, row * 180 + 10] <-Zmienia lokalizację za każdym razem w pętli
ball = MyBallClass(img_file, location) <- Tworzy piłkę w tym miejscu
balls.append(ball) <- Zbieraj piłki z listy
Musimy również wymieszać piłki na powierzchni wyświetlacza
for ball in balls:
screen.blit(ball.image, ball.rect)
pygame.display.flip()
Łącząc wszystko, nasz program jest pokazany na poniższej liście.
Listing 18.1 Używanie duszków do umieszczania wielu obrazów kul na ekranie
import sys, pygame
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
screen.fill([255, 255, 255])
img_file = "beach_ball.png"
balls = []
for row in range (0, 3):
for column in range (0, 3):
location = [column * 180 + 10, row * 180 + 10]
ball = MyBallClass(img_file, location)
balls.append(ball) <- Dodaje piłki do listy
for ball in balls:
screen.blit(ball.image, ball.rect)
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Jeśli to uruchomisz, powinieneś zobaczyć dziewięć piłek plażowych w oknie Pygame, w ten sposób:
Za chwilę zaczniemy je przenosić. Czy zauważyłeś małą zmianę w wierszach 10 i 11, która określa rozmiar okna Pygame? Zastąpiliśmy
screen = pygame.display.set_mode ([640,480])
z
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
Ten kod nie tylko ustawia rozmiar okna - jak poprzednio - ale także definiuje dwie zmienne, szerokość i wysokość, które możemy wykorzystać później. Dobrą rzeczą jest to, że zdefiniowaliśmy listę, zwaną size, z dwoma elementami w niej, a także zdefiniowaliśmy dwie zmienne całkowite, szerokość i wysokość, wszystko w jednej instrukcji. Nie używaliśmy również nawiasów kwadratowych wokół naszej listy, a Python ma z tym coś wspólnego. Chciałem ci tylko pokazać, że czasami w Pythonie można robić różne rzeczy. Jedna niekoniecznie jest lepsza od drugiej (o ile obie działają). Nawet jeśli musisz przestrzegać składni Pythona (zasady języka), wciąż jest miejsce na wolność wypowiedzi. Jeśli poprosiłeś 10 programistów o napisanie tego samego programu, prawdopodobnie nie otrzymasz dwóch identycznych fragmentów kodu.
Metoda move()
Ponieważ tworzymy kule jako instancje MyBallClass, sensowne jest ich przenoszenie za pomocą metody klasowej. Stwórzmy więc nową metodę klasy o nazwie move ():
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > height:
self.speed[1] = -self.speed[1]
Sprite′y (właściwie ich prostokąty) mają wbudowaną metodę o nazwie move(). Ta metoda wymaga parametru o nazwie prędkość, aby powiedzieć, jak daleko (czyli jak szybko) przesunąć obiekt. Ponieważ mamy do czynienia z grafiką dwuwymiarową, prędkość to lista dwóch liczb, jedna dla prędkości x, a druga dla prędkości y. Sprawdzamy również, czy piłka uderza w krawędzie okna, abyśmy mogli "odbić" kule wokół ekranu. Zmieńmy definicję MyBallClass, aby dodać właściwość speed i metodę move ():
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, speed):<- Dodaje argument prędkości
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed <- Dodaje tę linię, aby utworzyć atrybut prędkości dla piłki
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > height:
self.speed[1] = -self.speed[1]
Zwróć uwagę na zmianę w linii 2 (def __init __ (self, image_file, location, speed) :) oraz dodanie linii 7 (self.speed = speed), a także nową metodę move () w liniach od 9 do 15. Teraz kiedy tworzymy każde wystąpienie piłki, musimy powiedzieć jej prędkość, a także plik obrazu i lokalizację:
speed = [2, 2]
ball = MyBallClass(img_file, location, speed)
Poprzedni kod utworzy wszystkie kule z tą samą prędkością (w tym samym kierunku), ale fajnie byłoby zobaczyć, jak kule poruszają się trochę losowo. Użyjmy funkcji random.choice (), aby ustawić prędkość, tak jak poniżej:
from random import *
speed = [choice([-2, 2]), choice([-2, 2])
Spowoduje to wybranie -2 lub 2 zarówno dla prędkości x, jak i y. Oto kompletny program.
Listing 18.2 Program do przenoszenia kulek za pomocą ikonek
import sys, pygame
from random import *
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, speed):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > height:
self.speed[1] = -self.speed[1]
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
screen.fill([255, 255, 255])
img_file = "beach_ball.png"
balls = [] <-Tworzy listę do śledzenia piłki
for row in range (0, 3):
for column in range (0, 3):
location = [column * 180 + 10, row * 180 + 10]
speed = [choice([-2, 2]), choice([-2, 2])]
ball = MyBallClass(img_file, location, speed)
balls.append(ball) <- Dodaje każdą piłkę do listy w jej postaci
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.time.delay(20)
screen.fill([255, 255, 255])
for ball in balls:
ball.move()
screen.blit(ball.image, ball.rect)
pygame.display.flip()
pygame.quit()
Ten program używa listy do śledzenia wszystkich piłek. W linii 32 (balls.append (ball)) każda piłka jest dodawana do listy w jej postaci. Kod w ostatnich pięciu wierszach powoduje ponowne narysowanie ekranu. Tutaj trochę oszukujemy i zamiast "wymazywać" (malując) każdą piłkę oddzielnie, po prostu wypełniamy okno bielą, a następnie przerysowujemy wszystkie piłki. Możesz eksperymentować z tym kodem, mając więcej (lub mniej) piłek, zmieniając ich prędkość, zmieniając sposób poruszania się i "odbijania", i tak dalej. Zauważysz, że kule poruszają się i odbijają od boków okna, ale nie odbijają się od siebie - jeszcze!
Whaw! Wykrywanie kolizji
W większości gier komputerowych musisz wiedzieć, kiedy jeden sprite uderza w innego. Na przykład, możesz potrzebować wiedzieć, kiedy kula do kręgli uderzy w kręgle lub kiedy pocisk trafi w statek kosmiczny. Być może myślisz, że jeśli znasz położenie i rozmiar każdego duszka, możesz napisać kod, aby sprawdzić, czy są one ustawione względem rozmiaru i pozycji każdego innego duszka, aby zobaczyć, gdzie się nakładają. Ale ludzie, którzy napisali Pygame, już to dla nas zrobili. Pygame ma wbudowaną funkcję wykrywania kolizji.
Wykrywanie kolizji oznacza po prostu wiedzę, kiedy dwa sprite′y dotykają się lub nakładają się. Kiedy dwie rzeczy, które się poruszają, wpadają na siebie, nazywa się to kolizją
Pygame ma także sposób grupowania duszków. Na przykład w grze w kręgle wszystkie kręgle mogą znajdować się w jednej grupie, a piłka będzie w grupie własnej. Grupy i wykrywanie kolizji idą w parze. W przykładzie gry w kręgle chciałbyś wykryć, kiedy piłka uderzy w któryś z kręgli, więc będziesz szukał kolizji między duszkiem piłki i wszelkie duchy w grupie kręgli. Możesz także wykryć kolizje w grupie (jak uderzenia o siebie szpilki). Przejdźmy do przykładu. Zaczniemy od naszych odbijających się piłek plażowych, ale aby łatwiej było zobaczyć, co się dzieje, zaczniemy od zaledwie czterech piłek zamiast dziewięciu. I zamiast tworzyć listę piłek, tak jak w poprzednim przykładzie, użyjemy klasy grupy Pygame. Będziemy też trochę wyczyścić kod, umieszczając część, która animuje kule (kilka ostatnich linii na listingu 18.2) w funkcji, którą nazwiemy animate(). Funkcja animate() będzie również miała kod do wykrywania kolizji. Kiedy zderzą się dwie kule, sprawimy, że będą odwrócone. Następny listing pokazuje kod.
Listing 18.3 Wykrywanie kolizji za pomocą grupy ikonek zamiast listy
import sys, pygame
from random import *
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, speed):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > height:
self.speed[1] = -self.speed[1]
def animate(group):
screen.fill([255,255,255])
for ball in group:
group.remove(ball) <-Usuwa sprite z grupy
if pygame.sprite.spritecollide(ball, group, False): <-Sprawdza kolizje między spritem a grupą
ball.speed[0] = -ball.speed[0]
ball.speed[1] = -ball.speed[1]
group.add(ball) <- Dodaje piłkę do grupy
ball.move()
screen.blit(ball.image, ball.rect)
pygame.display.flip()
pygame.time.delay(20)
size = width, height = 640, 480 <-Główny program zaczyna się tutaj
screen = pygame.display.set_mode(size)
screen.fill([255, 255, 255])
img_file = "beach_ball.png"
group = pygame.sprite.Group() <-Tworzy grupę ikonek
for row in range (0, 2):
for column in range (0, 2):
location = [column * 180 + 10, row * 180 + 10]
speed = [choice([-2, 2]), choice([-2, 2])]
ball = MyBallClass(img_file, location, speed)
group.add(ball) <-Dodaje każdą piłkę do grupy
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
animate(group) <-Wywołuje funkcję animate (), przekazując do niej grupę
pygame.quit()
Najbardziej interesującą nowością jest sposób działania wykrywania kolizji. Moduł sprite Pygame ma funkcję o nazwie spritecollide(), który szuka kolizji pomiędzy pojedynczym duszkiem i dowolnym duszkiem w grupie. Jeśli sprawdzasz kolizje między ikonkami w tej samej grupie, musisz to zrobić w trzech krokach:
1 Usuń ikonkę z grupy.
2 Sprawdź, czy nie ma kolizji między ikonką a resztą grupy.
3 Dodaj sprite do grupy.
Dzieje się tak w pętli for w liniach od 21 do 29 (w środkowej części funkcji animate()). Jeśli najpierw nie usuniemy ikonki z grupy, spritecollide() wykryje kolizję między ikonką a sobą, ponieważ znajduje się w grupie. Na początku może to wydawać się dziwne, ale ma to sens, jeśli zastanowisz się przez chwilę. Uruchom program i zobacz, jak to wygląda. Czy zauważyłeś jakieś dziwne zachowanie? Zauważyłem dwie rzeczy:
• Gdy piłki zderzają się, robią "jąkanie" lub podwójne uderzenie.
• Czasami piłka utknie wzdłuż krawędzi okna i trzęsie się przez chwilę.
Dlaczego to się dzieje? Cóż, ma to związek ze sposobem, w jaki napisaliśmy funkcję animate(). Zauważ, że poruszamy jedną kulą, a następnie sprawdzamy jej kolizje, a następnie przesuwamy kolejną kulę, a następnie sprawdzamy jej kolizje i tak dalej. Najpierw powinniśmy wykonać wszystkie ruchy, a następnie wykonać wszystkie kontrole kolizji. Więc chcemy wziąć linię 28, ball.move () i umieścić ją we własnej pętli, tak jak poniżej:
def animate(group):
screen.fill([255,255,255])
for ball in group:
ball.move() <-Najpierw przenosimy wszystkie piłki
for ball in group:
group.remove(ball)
if pygame.sprite.spritecollide(ball, group, False):
ball.speed[0] = -ball.speed[0]
ball.speed[1] = -ball.speed[1]
group.add(ball)
screen.blit(ball.image, ball.rect)
pygame.display.flip()
pygame.time.delay(20)
Spróbuj tego i sprawdź, czy działa trochę lepiej. Możesz bawić się kodem, zmieniać rzeczy takie jak prędkość (liczba time.delay ()), liczba piłek, oryginalna lokalizacja piłek, losowość i tak dalej, aby zobaczyć, co dzieje się z piłkami.
Kolizja prostokątów a kolizja perfekcyjna pikseli
Jedna rzecz, którą zauważysz, to fakt, że kulki nie zawsze dotykają się całkowicie, gdy "zderzają się". Spritecollide() nie używa okrągłego kształtu kuli do wykrywania kolizji. Wykorzystuje rect piłki, prostokąt wokół piłki. Jeśli chcesz to zobaczyć, narysuj prostokąt wokół obrazu piłki i użyj tego nowego obrazu zamiast zwykłego obrazu piłki plażowej. Zrobiłem dla ciebie jeden, więc możesz spróbować:
img_file = "b_ball_rect.png"
Powinien wyglądać mniej więcej tak:
Jeśli chcesz, aby kule odbijały się od siebie tylko wtedy, gdy okrągłe części kulek (a nie krawędzie prostokątów) rzeczywiście się dotknęły, musisz użyć czegoś, co nazywa się wykrywaniem kolizji doskonałych w pikselach. Funkcja spritecollide () tego nie robi, ale zamiast tego używa prostszego wykrywania kolizji. Oto różnica. Przy prostym wykrywaniu kolizji dwie kule zderzają się, gdy jakakolwiek część ich prostokątów styka się ze sobą. Dzięki doskonałej detekcji kolizji w pikselach dwie kule zderzają się tylko wtedy, gdy same piłki dotkną, tak:
Perfekcyjne wykrywanie kolizji pikseli jest bardziej realistyczne. (Nie widziałeś żadnych niewidzialnych prostokątów wokół prawdziwych piłek plażowych, prawda?) Ale jest to bardziej skomplikowane w programie. Dla większości rzeczy, które zrobisz w Pygame, poprawne wykrywanie kolizji jest wystarczająco dobre. Doskonałe wykrywanie kolizji w pikselach wymaga więcej kodu i sprawi, że Twoje gry będą działać wolniej, więc używaj ich tylko wtedy, gdy naprawdę tego potrzebujesz. Dostępnych jest kilka modułów doskonałych dla pikseli (co najmniej dwa na stronie Pygame podczas ostatniego sprawdzenia). Niektóre wyszukiwania w sieci znajdą je, jeśli chcesz wypróbować wykrywanie kolizji w sposób idealny dla pikseli
Liczenie czasu
Do tej pory używaliśmy time.delay() do kontrolowania szybkości działania naszej animacji. Ale to nie jest najlepszy sposób, ponieważ kiedy używasz time.delay(), tak naprawdę nie wiesz, jak długo każda pętla będzie. Kod w pętli wymaga trochę czasu (nieznany czas) i wtedy opóźnienie zajmuje więcej czasu (znany czas). Część czasu jest znana, ale część jest nieznana. Jeśli chcesz wiedzieć, jak często działa pętla, musisz znać całkowity czas każdej pętli, czyli czas kodu + czas opóźnienia. Aby obliczyć czas animacji, wygodnie jest użyć milisekund, lub tysięcznych części sekundy. Skrót to ms, więc 25 milisekund wynosi 25 ms.
W naszym przykładzie załóżmy, że czas kodu wynosi 15 ms. Oznacza to, że uruchomienie kodu w pętli while trwa 15 ms, nie wliczając w to time.delay(). Znamy czas opóźnienia, ponieważ ustawiamy go na 20 ms za pomocą time.delay(20). Całkowity czas pętli wynosi 20 ms + 15 ms = 35 ms, a w ciągu jednej sekundy jest 1000 ms. Jeśli każda pętla zajmuje 35 ms, otrzymujemy 1000 ms / 35 ms = 28,57. Oznacza to, że otrzymamy około 29 pętli na sekundę. W grafice komputerowej każdy krok animacji nazywany jest klatką , a programiści gier mówią o szybkości klatek i klatkach na sekundę, kiedy omawiają szybkość aktualizacji swojej grafiki. W naszym przykładzie szybkość klatek wynosiłaby około 29 klatek na sekundę. Problem polega na tym, że tak naprawdę nie można kontrolować części "czasu kodu" równania. Jeśli dodasz lub usuniesz kod, czas się zmieni. Nawet z tym samym kodem, jeśli jest inny numer sprite′ów (na przykład, gdy obiekty gry pojawiają się i znikają), czas potrzebny na ich narysowanie się zmieni. Również ten sam kod będzie działać szybciej lub wolniej na różnych komputerach. Zamiast 15 ms czas kodu może wynosić 10 ms lub 20 ms. Byłoby dobrze, gdyby istniał bardziej przewidywalny sposób kontrolowania liczby klatek na sekundę. Na szczęście moduł czasu Pygame daje nam narzędzia do tego, z klasą o nazwie Zegar.
Sterowanie częstotliwością klatek za pomocą pygame.time.Clock ()
Zamiast dodawać opóźnienie do każdej pętli, pygame.time.Clock () kontroluje, jak często działa każda pętla. To jak zegar, który trzyma startując, mówiąc "Zacznij teraz od następnej pętli! Rozpocznij teraz kolejną pętlę! … "
Zanim zaczniesz używać zegara Pygame, musisz utworzyć instancję obiektu Clock. To działa tak samo jak tworzenie wystąpienie dowolnej innej klasy:
clock = pygame.time.Clock ()
Następnie, w ciele głównej pętli, mówisz zegarowi, jak często powinien on "zaznaczyć", czyli jak często pętla powinna działać:
clock.tick (60)
Liczba, którą przekazujesz clock.tick () nie jest liczbą milisekund. Zamiast tego to liczba uruchomień pętli na sekundę. Więc ta pętla powinna działać 60 razy na sekundę. Mówię "powinien działać", ponieważ pętla może działać tylko tak szybko, jak komputer może ją uruchomić. Przy 60 pętlach (lub klatkach) na sekundę, to 1000/60 = 16,66 ms (około 17 ms) na pętlę. Jeśli uruchomienie kodu w pętli trwa dłużej niż 17 ms, nie zostanie to wykonane przez zegar wskazujący, że ma rozpocząć następną pętlę. Zasadniczo oznacza to ograniczenie liczby klatek na sekundę, które może uruchomić Twoja grafika. Ten limit zależy od złożoności grafiki, rozmiaru okna i szybkości komputera, na którym działa program. W przypadku niektórych programów jeden komputer może działać z szybkością 90 klatek na sekundę, podczas gdy starszy, wolniejszy komputer łączy się z szybkością 10 klatek na sekundę. W przypadku dość złożonej grafiki większość współczesnych komputerów nie będzie miała problemów z uruchomieniem programów Pygame z prędkością od 20 do 30 fps. Jeśli więc chcesz, aby gry działały z taką samą prędkością na większości komputerów, wybierz częstotliwość odświeżania od 20 do 30 klatek na sekundę lub mniej. Jest to wystarczająco szybkie, aby uzyskać płynny ruch. Od teraz użyjemy clock.tick (30) do przykładów.
Sprawdzanie liczby klatek na sekundę
Jeśli chcesz wiedzieć, jak szybko program może działać, możesz sprawdzić częstotliwość klatek za pomocą funkcji o nazwie clock.get_fps(). Oczywiście, jeśli ustawisz wskaźnik na 30, zawsze osiągniesz 30 klatek na sekundę (zakładając, że komputer może działać tak szybko). Aby zobaczyć jak najszybciej dany program może uruchomić na konkretnej maszynie, ustaw clock.tick bardzo szybko (np. 200 fps), a następnie uruchom program i sprawdź rzeczywistą szybkość klatek za pomocą clock.get_fps(). (Wkrótce pojawi się przykład.)
Skalowanie szybkości klatek
Jeśli chcesz mieć pewność, że Twoja animacja działa z taką samą prędkością na każdej maszynie, możesz skorzystać z sztuczki clock.tick() i clock.get_fps(). Ponieważ znasz szybkość, z jaką chcesz biegać i prędkość, na której aktualnie się poruszasz, możesz dostosować lub skalować szybkość animacji w zależności od prędkości maszyny.
Załóżmy na przykład, że masz clock.tick(30), co oznacza, że próbujesz uruchomić z prędkością 30 fps. Jeśli używasz clock.get_fps() i odkrywasz, że osiągasz tylko 20 fps, wiesz, że obiekty na ekranie poruszają się wolniej niż chcesz. Ponieważ uzyskasz mniej klatek na sekundę, musisz przesuwać obiekty dalej w każdej klatce, aby wyglądały, jakby poruszały się z właściwą prędkością. Prawdopodobnie będziesz mieć zmienną (lub atrybut) nazywaną prędkością dla poruszających się obiektów, która mówi im, jak daleko się poruszać w każdej klatce. Wystarczy zwiększyć prędkość, aby nadrobić wolniejszą maszynę. Ile to zwiększyć? Zwiększasz go o stosunek pożądanych fps / rzeczywistych fps. Jeśli bieżąca prędkość obiektu wynosi 10 dla żądanego 30 klatek na sekundę, a program działa z prędkością 20 klatek na sekundę,
object_speed = current_speed * (pożądane fps / rzeczywiste fps)
object_speed = 10 * (30/20)
object_speed = 15
Zamiast przesuwać 10 pikseli na klatkę, przesuwałbyś obiekt o 15 pikseli na klatkę, aby zrekompensować wolniejszą częstotliwość klatek. Oto lista programów do piłki plażowej wykorzystujących rzeczy omówione w ostatnich kilku sekcjach: Zegar i get_fps()
Listing 18.4 Korzystanie z zegara i get_fps () w programie piłki plażowej
import sys, pygame
from random import *
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, speed):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > height:
self.speed[1] = -self.speed[1]
def animate(group):
screen.fill([255,255,255])
for ball in group:
ball.move()
for ball in group:
group.remove(ball)
if pygame.sprite.spritecollide(ball, group, False):
ball.speed[0] = -ball.speed[0]
ball.speed[1] = -ball.speed[1]
group.add(ball)
screen.blit(ball.image, ball.rect)
pygame.display.flip() <-time.delay () został usunięty
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
screen.fill([255, 255, 255])
img_file = "beach_ball.png"
clock = pygame.time.Clock() <-Tworzy instancję zegara
group = pygame.sprite.Group()
for row in range (0, 2):
for column in range (0, 2):
location = [column * 180 + 10, row * 180 + 10]
speed = [choice([-4, 4]), choice([-4, 4])]
ball = MyBallClass(img_file, location, speed)
group.add(ball) #add the ball to the group
running = True
while running: <-Tutaj rozpoczyna się główna pętla while
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
frame_rate = clock.get_fps() <-Sprawdza szybkość klatek
print "frame rate = ", frame_rate
animate(group)
clock.tick(30) <- clock.tick steruje teraz szybkością klatek (ograniczoną prędkością komputera)
pygame.quit()
Obejmuje to podstawy Pygame i sprite′ów. W następnym rozdziale zrobimy prawdziwą grę przy użyciu Pygame, a zobaczysz inne rzeczy, które możesz zrobić, takie jak dodawanie tekstu (do wyników gry) oraz wprowadzanie danych za pomocą myszy i klawiatury.
Czego się nauczyłeś?
• Sprites w Pygame i jak ich używać do obsługi wielu ruchomych obrazów
• Grupy ikonek
• Wykrywanie kolizji
• pygame.clock i liczba klatek na sekundę
Sprawdź swoją wiedzę
1 Co to jest wykrywanie kolizji?
2 Co to jest wykrywanie kolizji w trybie pikselowym i czym różni się od wykrywania bezpośredniego kolizji?
3 Jakie są dwa sposoby śledzenia wielu obiektów sprite razem?
4 Jakie są dwa sposoby kontrolowania szybkości animacji w kodzie?
5 Dlaczego używanie pygame.clock jest bardziej dokładne niż użycie pygame.time.delay ()?
6 W jaki sposób możesz sprawdzić, na jakiej szybkości odtwarzania działa Twój program?
Wypróbuj to
Jeśli wpisałeś wszystkie przykłady kodu , wypróbowałeś wystarczająco dużo. Jeśli nie, wróć i zrób to. Obiecuję, że się czegoś nauczysz!
Do tej pory mieliśmy bardzo proste rodzaje danych wejściowych dla naszych programów. Albo użytkownik wpisał ciągi przy użyciu raw_input (), albo otrzymaliśmy liczby i łańcuchy z EasyGui. Pokazałem również, jak możesz użyć myszy do zamknięcia okna Pygame, ale tak naprawdę nie wyjaśniłem, jak to działa. W tej części dowiesz się o innym rodzaju danych wejściowych zwanych zdarzeniami. Po drodze przyjrzymy się dokładnie, co robi kod wyjścia dla okna Pygame i jak działa. Otrzymamy także dane z myszy i sprawimy, że nasze programy zareagują natychmiast na naciśnięcie klawisza, bez konieczności czekania na naciśnięcie klawisza Enter przez użytkownika.
Wydarzenia
Gdybym zapytał cię "Co to jest wydarzenie?" W prawdziwym życiu, możesz powiedzieć, że jest to "coś, co się zdarza". To całkiem dobra definicja i ta sama definicja jest prawdziwa w programowaniu. Wiele programów musi reagować na "rzeczy, które się zdarzają"
• Mysz jest przesuwana lub kliknięta
• Naciskane klawisze
• Pewna ilość czasu
Większość programów, które napisaliśmy do tej pory, podążała dość przewidywalną ścieżką od początku do końca, być może z pewnymi pętlami lub warunkami w środku. Ale istnieje inna cała klasa programów, nazywana programami sterowanymi zdarzeniami, które nie działają w ten sposób. Programy sterowane zdarzeniami w zasadzie siedzą i nic nie robią, czekając, aż wydarzy się coś - zdarzenie. Kiedy zdarzenie się zdarza, zaczynają działać, robiąc wszystko, co jest konieczne do obsługi zdarzenia. Dobrym przykładem jest system operacyjny Windows (lub dowolny inny GUI). Jeśli włączysz komputer z systemem Windows, po prostu stanie gdy skończy uruchamianie. Żadne programy nie zostaną uruchomione i nie zobaczysz kursora myszy zapinającego się po ekranie. Ale jeśli zaczniesz się poruszać lub klikniesz myszką, sprawy zaczną się dziać. Kursor myszy przesuwa się po ekranie, pojawi się menu Start lub cokolwiek innego.
Pętla zdarzenia
Aby program sterowany zdarzeniami "widział" wydarzenia, musi "szukać" ich. Program musi stale skanować część pamięci komputera, która jest używana do sygnalizowania zdarzenia. Robi to w kółko, dopóki program działa. W części 8 dowiedziałeś się, jak programy wykonują różne czynności - używają pętli. Specjalna pętla, która szuka zdarzeń, nazywana jest pętlą zdarzenia. W programach Pygame, które tworzyliśmy w dwóch ostatnich Częściach, zawsze była pętla na końcu. Powiedzieliśmy, że ta pętla działa przez cały czas działania programu. Ta pętla while jest pętlą zdarzenia Pygame. (Jest pierwszy kawałek układanki na temat działania kodu wyjścia).
Kolejka zdarzeń
Wszystkie te zdarzenia zdarzają się, gdy ktoś porusza się lub klika mysz lub naciska klawisz. W ostatniej części powiedziałem, że pętla zdarzeń stale skanuje część pamięci. Część pamięci, w której przechowywane są zdarzenia, nazywana jest kolejką zdarzeń.
Kolejka słów wymawia się "kju". W codziennym użytkowaniu oznacza to linię oczekiwania. W programowaniu kolejka zazwyczaj oznacza listę rzeczy, które dotarły w określonej kolejności lub zostaną użyte wokreślonej kolejności.
Kolejka zdarzeń to lista wszystkich zdarzeń, które miały miejsce, w kolejności, w jakiej się wydarzyły.
Obsługa zdarzeń
Jeśli piszesz program GUI lub grę, program musi wiedzieć, kiedy użytkownik naciśnie klawisz lub poruszy myszą. Te naciśnięcia, kliknięcia i ruchy myszą to wszystkie zdarzenia, a program musi wiedzieć, co z nimi zrobić. Musi się nimi zająć. Część programu, która obsługuje pewien rodzaj zdarzenia, nazywana jest procedurą obsługi zdarzeń. Nie każde zdarzenie będzie obsługiwane. Podczas przesuwania myszy po biurku tworzone są setki zdarzeń, ponieważ pętla zdarzeń działa bardzo szybko. W ułamku sekundy, jeśli mysz poruszy się choćby odrobinę, generowane jest nowe zdarzenie. Ale twój program może nie przejmować się każdym małym ruchem myszy. Może to mieć znaczenie tylko wtedy, gdy użytkownik kliknie określoną rzecz. Twój program może ignorować zdarzenia mouseMove i zwracać uwagę tylko na zdarzenia mouseClick. Programy sterowane zdarzeniami mają moduły obsługi zdarzeń dla takich zdarzeń, na których im zależy. Jeśli masz grę, która używa klawiszy strzałek na klawiaturze do sterowania ruchem statku, możesz napisać handler dla zdarzenia keyDown. Jeśli zamiast tego używasz myszy do sterowania statkiem, możesz napisać handler dla zdarzenia mouseMove.
Zaczniemy teraz szukać konkretnych wydarzeń, które możesz wykorzystać w swoich programach. Ponownie użyjemy Pygame, więc wszystkie wydarzenia, o których będziemy mówić w dalszej części , będą pochodziły z kolejki zdarzeń Pygame. Różne moduły Pythona mają różne zestawy zdarzeń jakich możesz użyć. Na przykład przyjrzymy się innemu modułowi o nazwie PyQt w Części 20. PyQt ma swój własny zestaw zdarzeń, z których niektóre różnią się od Pygame. Ale sposób obsługi zdarzeń jest generalnie taki sam od jednego zestawu zdarzeń do drugiego (a nawet od jednego języka programowania do drugiego). Nie jest dokładnie taki sam dla każdego systemu zdarzeń, ale istnieje więcej podobieństw niż różnic.
Zdarzenia klawiatury
Zacznijmy od przykładu zdarzenia klawiatury. Powiedzmy, że chcemy, aby coś się stało, gdy tylko klawisz zostanie naciśnięty na klawiaturze. W Pygame zdarzeniem dla tego jest KEYDOWN. Aby zilustrować, w jaki sposób jest to stosowane, skorzystajmy z naszego przykładu odbijającej się piłki , która po prostu przesuwa piłkę na boki, odbijając się od boków okna. Ale zanim zaczniemy dodawać wydarzenia, zaktualizujmy ten program za pomocą nowych rzeczy, których się nauczyliśmy:
• Korzystanie z ikonek
• Używanie clock.tick() zamiast time.delay()
Najpierw potrzebujemy klasy dla piłki. Ta klasa będzie miała metodę __init __ () i metodę move(). Stworzymy instancję klasy, a w głównej pętli while użyjemy clock.tick (30). Poniższa lista przedstawia kod z tymi zmianami
Listing 19.1 Program odbijania piłki, z ikonkami i Clock.tick ()
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
background = pygame.Surface(screen.get_size())
background.fill([255, 255, 255])
clock = pygame.time.Clock()
class Ball(pygame.sprite.Sprite):
def __init__(self, image_file, speed, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
if self.rect.left <= screen.get_rect().left or
self.rect.right >= screen.get_rect().right:
self.speed[0] = - self.speed[0]
newpos = self.rect.move(self.speed)
self.rect = newpos
my_ball = Ball('beach_ball.png', [10,0], [20, 20]) <-Tworzy instancję piłki
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
clock.tick(30) <-To jest zegar
screen.blit(background, (0, 0))
my_ball.move()
screen.blit(my_ball.image, my_ball.rect)
pygame.display.flip()
pygame.quit()
Należy zauważyć, że zrobiliśmy coś innego, aby "wymazać" piłkę, gdy ją przenieśliśmy. Widziałeś dwa sposoby wymazywania duszków przed ich przemalowaniem w nowych pozycjach: jednym jest malowanie koloru tła nad starą pozycją każdego duszka, a drugim malowanie całego tła dla każdej klatki - zasadniczo zaczynając od pustego ekranu. czas. W tym przypadku zrobiliśmy drugi. Ale zamiast używać screen.fill() za każdym razem w pętli, zrobiliśmy powierzchnię zwaną tłem i wypełniliśmy ją bielą. Następnie za każdym razem, gdy przechodzimy przez pętlę, mieszamy to tło na powierzchni ekranu, na ekranie. Osiąga to samo; to tylko trochę inny sposób.
Kluczowe wydarzenia
Teraz dodamy moduł obsługi zdarzeń, który powoduje, że piłka przesuwa się w górę, gdy zostanie naciśnięta strzałka w górę, i przesuwa się w dół po naciśnięciu strzałki w dół. Pygame składa się z wielu różnych modułów. Moduł, którego użyjemy w tym rozdziale, to pygame.event. Mamy już uruchomioną pętlę zdarzeń Pygame (pętla while). Ta pętla szuka specjalnego zdarzenie o nazwie QUIT:
while running:
for event in pygame.event.get ():
if event.type == pygame.QUIT:
running = False
Metoda pygame.event.get() pobiera listę wszystkich zdarzeń z kolejki zdarzeń. Pętla for iteruje przez każde zdarzenie na liście, a jeśli widzi zdarzenie QUIT, ustawia działanie na False, co powoduje zakończenie pętli while i zakończenie programu. Teraz masz całą historię na temat działania kodu "kliknij X, aby zakończyć program". W tym przykładzie chcemy jednak wykryć inny typ zdarzenia. Chcemy wiedzieć, kiedy klawisz jest wciśnięty, więc musimy poszukać zdarzenia KEYDOWN. Potrzebujemy czegoś takiego:
if event.type == pygame.KEYDOWN
Ponieważ mamy już instrukcję if, możemy po prostu dodać kolejny warunek z elif, tak jak nauczyliście się w Części 7:
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
# do something
Co jeśli "coś" chcemy zrobić po naciśnięciu klawisza? Powiedzieliśmy, że jeśli zostanie naciśnięta strzałka w górę, sprawimy, że piłka podniesie się, a jeśli zostanie naciśnięta strzałka w dół, przesuniemy ją w dół. Możemy więc zrobić coś takiego:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
my_ball.rect.top = my_ball.rect.top - 10 <- Sprawia, że piłka porusza się w górę o 10 pikseli
elif event.key == pygame.K_DOWN:
my_ball.rect.top = my_ball.rect.top + 10 <-Sprawia, że piłka porusza się w dół o 10 pikseli
K_UP i K_DOWN to nazwy Pygame dla klawiszy strzałek w górę iw dół. Dokonaj zmiany na listingu 19.1, a program powinien teraz wyglądać tak.
Listing 19.2 Odbijająca się piłka z klawiszem strzałki w górę i w dół
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
background = pygame.Surface(screen.get_size())
background.fill([255, 255, 255])
clock = pygame.time.Clock()
class Ball(pygame.sprite.Sprite):
def __init__(self, image_file, speed, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
if self.rect.left <= screen.get_rect().left or \
self.rect.right >= screen.get_rect().right:
self.speed[0] = - self.speed[0]
newpos = self.rect.move(self.speed)
self.rect = newpos
my_ball = Ball('beach_ball.png', [10,0], [20, 20]) <- Tworzy instancję piłki
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
my_ball.rect.top = my_ball.rect.top - 10
elif event.key == pygame.K_DOWN:
my_ball.rect.top = my_ball.rect.top + 10
clock.tick(30)
screen.blit(background, (0, 0))
my_ball.move()
screen.blit(my_ball.image, my_ball.rect)
pygame.display.flip()
pygame.quit()
Uruchom program z listingu 18.2 i wypróbuj klawisze strzałek w górę i w dół. Czy to działa?
Powtarzające się klawisze
Być może zauważyłeś, że jeśli przytrzymasz klawisz strzałki w górę lub w dół, piłka porusza się tylko o jeden krok w górę lub w dół. To dlatego, że nie powiedzieliśmy naszemu programowi, co zrobić, jeśli klawisz został przytrzymany. Gdy użytkownik nacisnął klawisz, wygenerował jedno zdarzenie KEYDOWN, ale w Pygame jest ustawienie, które powoduje generowanie wielu zdarzeń KEYDOWN, jeśli klawisz zostanie przytrzymany. Jest to znane jako powtórzenie klawisza. Mówisz, jak długo czekać, zanim zacznie się powtarzać i jak często powtarzać. Wartości podano w milisekundach (tysięczne części sekundy). Wygląda to tak: Wartość opóźnienia mówi Pygame, jak długo czekać przed rozpoczęciem powtarzania, a wartość interwału mówi Pygame, jak szybko klucz powinien się powtarzać - innymi słowy, jak długo między każdym zdarzeniem KEYDOWN.
Spróbuj dodać to do listingu 19.2 (gdzieś po pygame.init, ale przed pętlą while), aby zobaczyć, jak zmienia zachowanie programu.
Nazwy zdarzeń i nazwy kluczy
Kiedy szukaliśmy naciskanych klawiszy strzałek w górę i w dół, szukaliśmy typu zdarzenia KEYDOWN i nazw kluczy K_UP i K_DOWN. Jakie inne wydarzenia są dostępne? Jakie są nazwy innych kluczy? Jest ich całkiem sporo, więc nie wymienię ich wszystkich tutaj. Ale są na stronie internetowej Pygame. Listę wydarzeń w sekcji zdarzeń w dokumentacji Pygame można znaleźć:
www.pygame.org/docs/ref/event.html
Lista nazw kluczy znajduje się w sekcji klucza:
www.pygame.org/docs/ref/key.html
Oto kilka typowych wydarzeń, z których będziesz korzystać:
• UIT
• KEYDOWN
• KEYUP
• MOUSEMOTION
• MOUSEBUTTONUP
• MOUSEBUTTONDOWN
Pygame ma również nazwy dla każdego klawisza, który można nacisnąć. Widziałeś strzałkę w górę i strzałkę w dół, K_UP i K_DOWN. Zobaczysz niektóre inne nazwy kluczy, które będą się pojawiać, ale wszystkie zaczynają się od K_, po którym następuje nazwa klucza, w ten sposób:
• K_a, K_b itd. (Dla klawiszy literowych)
• K_SPACE
• K_ESCAPE
i tak dalej.
Zdarzenia myszy
Właśnie zobaczyłeś, jak uzyskać kluczowe zdarzenia z klawiatury i użyć ich do kontrolowania czegoś w swoim programie. Sprawiliśmy, że piłka plażowa poruszała się w górę i w dół za pomocą klawiszy strzałek. Teraz użyjemy myszy do sterowania piłką. To pokaże, jak obsługiwać zdarzenia myszy i jak korzystać z informacji o pozycji myszy. Najczęściej używane są trzy typy zdarzeń myszy
• MOUSEBUTTONUP
• MOUSEBUTTONDOWN
• MOUSEMOTION
Najprostszą rzeczą jest, aby piłka plażowa podążała za pozycją myszy za każdym razem, gdy mysz jest poruszana w oknie Pygame. Aby przenieść piłkę plażową, użyjemy atrybutu rect.center piłki. W ten sposób środek piłki podąży za myszą. Zastąpimy kod, który wykrył kluczowe zdarzenia w pętli while kodem, aby wykryć zdarzenia myszy:
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEMOTION:
my_ball.rect.center = event.pos
Jest to nawet prostsze niż przykład klawiatury. Dokonaj tej zmiany na listingu 19.2 i spróbuj. Część event.pos to pozycja (współrzędne xiy) myszy. Przesuwamy środek piłki do tego miejsca. Zauważ, że piłka podąża za myszą tak długo, jak myszą porusza się - to znaczy tak długo, jak zdarzają się wydarzenia MOUSEMOVE. Zmiana prostokąta kulki zmieniła zarówno pozycję x, jak i y. Nie poruszamy już tylko piłką w górę lub w dół, ale także na boki. Gdy nie ma żadnych zdarzeń myszy - ponieważ mysz nie porusza się lub kursor myszy znajduje się poza oknem Pygame - piłka odbija się od boku do boku. Teraz spróbujmy, aby sterowanie myszą działało tylko wtedy, gdy przycisk myszy jest wciśnięty. Przesuwanie myszy przy wciśniętym przycisku myszy nazywa się przeciąganiem. Nie ma typu zdarzenia MOUSEDRAG, więc użyjemy tych, które musimy uzyskać, aby uzyskać pożądany efekt. Jak możesz stwierdzić, czy mysz jest przeciągana? Przeciąganie oznacza, że mysz jest przesuwana podczas przytrzymywania przycisku myszy. Za pomocą zdarzenia MOUSEBUTTONDOWN możesz określić, kiedy przycisk zostanie wyłączony, i możesz określić, kiedy zostanie on wydany (powróci), za pomocą zdarzenia MOUSEBUTTONUP. Następnie musisz śledzić status przycisku. Możesz to zrobić, tworząc zmienną; nazwij to czymś w rodzaju hold_down. Oto jak by to wyglądało:
held_down = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
held_down = True
elif event.type == pygame.MOUSEBUTTONUP:
held_down = False
elif event.type == pygame.MOUSEMOTION:
if held_down:
my_ball.rect.center = event.pos <- Wykonuje się, gdy mysz jest przeciągana
Warunek przeciągania (poruszanie myszą podczas przytrzymywania przycisku) jest wykrywany w ostatnim bloku elifu w poprzednim kodzie. Spróbuj dokonać tej zmiany w pętli while we wcześniej zmodyfikowanej wersji listingu 19.2. Uruchom go i zobacz, jak to działa.
Hej, programowaliśmy od pierwszej części! Ale teraz, gdy robimy rzeczy z grafiką, duszkami i myszką, staje się to coraz ciekawsze. Mówiłem ci, że tam dotrzemy. Po prostu musiałeś się ze mną trzymać i najpierw nauczyć się podstaw.
Zdarzenia czasowe
Do tej pory widziałeś zdarzenia klawiatury i zdarzenia myszy. Innym bardzo przydatnym zdarzeniem, szczególnie w grach i symulacjach, jest zdarzenie czasowe. Zegar generuje zdarzenie w regularnych odstępach czasu, np. Alarm Jeśli go ustawisz i pozostawisz włączony alarm, będzie dzwonił o tej samej porze każdego dnia. Zegary Pygame można ustawić na dowolny interwał. Gdy timer się wyłącza, tworzy zdarzenie, które pętla zdarzeń może wykryć. A jakie wydarzenie generuje? Generuje coś, co nazywa się zdarzeniem użytkownika. Pygame ma wiele predefiniowanych typów zdarzeń. Zdarzenia te są ponumerowane, począwszy od 0, a także mają nazwy, które ułatwiają ich zapamiętanie. Widziałeś już niektóre z nich, jak MOUSEBUTTONDOWN i KEYDOWN. W Pygame jest także miejsce na zdarzenia zdefiniowane przez użytkownika. Są to wydarzenia, których Pygame nie odłożył na nic konkretnego, i możesz ich użyć do tego, co chcesz. Jedną z rzeczy, do których mogą być używane, są liczniki czasu. Aby ustawić timer w Pygame, użyj funkcji set_timer (), tak jak poniżej:
pygame.time.set_timer (EVENT_NUMBER, interval)
EVENT_NUMBER to numer zdarzenia, a odstęp czasu określa, jak często (w milisekundach) timer wyłączy się i wygeneruje zdarzenie. Z czego EVENT_NUMBER należy korzystać? Powinieneś użyć tego, którego Pygame już nie używa do czegoś innego. Możesz zapytać Pygame, jakie liczby są już używane. Wypróbuj to w trybie interaktywnym:
>>> import pygame
>>> pygame.USEREVENT
24
To mówi nam, że Pygame używa numerów zdarzeń od 0 do 23, a pierwszy dostępny dla zdarzeń użytkowników to 24. Więc musimy wybrać liczbę 24 lub wyższą. Jak wysoko możemy iść? Zapytajmy ponownie Pygame:
>>> pygame.NUMEVENTS
32
NUMEVENTS mówi nam, że maksymalna liczba typów zdarzeń, które możemy mieć w Pygame, wynosi 32 (od 0 do 31). Musimy więc wybrać liczbę 24 lub większą, ale mniejszą niż 32. Możemy ustawić nasz timer tak:
pygame.time.set_timer (24, 1000)
Ale jeśli z jakiegoś powodu wartość USEREVENT zmieni się, kod może nie działać. Lepiej byłoby to zrobić w ten sposób:
pygame.time.set_timer (pygame.USEREVENT, 1000)
Gdybyśmy musieli skonfigurować inne zdarzenie użytkownika, moglibyśmy użyć USEREVENT + 1 i tak dalej. 1000 w tym przykładzie oznacza 1000 milisekund, czyli jedną sekundę, więc ten timer wyłączy się raz na sekundę. Dodajmy to do naszego programu odbijającej piłki. Tak jak poprzednio, użyjemy tego wydarzenia, aby przesunąć piłkę w górę lub w dół. Ale ponieważ tym razem piłka nie będzie kontrolowana przez użytkownika, powinniśmy ją odbić od góry i dołu oraz od boków. Kompletny program, oparty na modyfikacji listingu 19.2, jest pokazany poniżej
Listing 19.3 Korzystanie z wydarzenia z zegarem, aby przesunąć piłkę w górę i w dół
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
background = pygame.Surface(screen.get_size())
background.fill([255, 255, 255])
clock = pygame.time.Clock()
class Ball(pygame.sprite.Sprite):
def __init__(self, image_file, speed, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
if self.rect.left <= screen.get_rect().left or \
self.rect.right >= screen.get_rect().right:
self.speed[0] = - self.speed[0]
newpos = self.rect.move(self.speed)
self.rect = newpos
my_ball = Ball('beach_ball.png', [10,0], [20, 20]) <-Tworzy instancję Ball
pygame.time.set_timer(pygame.USEREVENT, 1000) <-Tworzy timer: 1000 ms = 1 sekund
direction = 1
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.USEREVENT:
my_ball.rect.centery = my_ball.rect.centery + (30*direction)
if my_ball.rect.top <= 0 or \
my_ball.rect.bottom >= screen.get_rect().bottom:
direction = -direction
clock.tick(30)
screen.blit(background, (0, 0))
my_ball.move()
screen.blit(my_ball.image, my_ball.rect)
pygame.display.flip()
pygame.quit()
Pamiętaj, że \ jest to znak kontynuacji linii . Możesz go użyć, aby napisać coś na dwóch liniach, które normalnie byłyby w jednej linii. (Po prostu nie wpisuj żadnych spacji po tym, jak kontynuacja linii nie będzie działać). Jeśli zapiszesz i uruchomisz program na listingu 19.3, powinieneś zobaczyć piłkę poruszającą się w przód iw tył (z boku na bok), a także przesuwać 30 pikseli w górę lub w dół (raz na sekundę). Ten ruch w górę lub w dół pochodzi ze zdarzenia timera. Czas na kolejną grę - PyPong. W tej sekcji zestawimy kilka rzeczy, których się nauczyliśmy - w tym sprite&pime;y, wykrywanie kolizji i wydarzenia - aby stworzyć prostą grę typu paddle-and-ball, podobną do Ponga.
Pong był jedną z pierwszych gier wideo, które ludzie używali w swoich domach. Oryginalna gra Pong nie miała żadnego oprogramowania - była to tylko masa układów! To było zanim pojawiły się komputery domowe. Podłączono go do telewizora i kontrolowano "paletki" za pomocą pokręteł.
Zaczniemy od prostej wersji dla jednego gracza. Naszej grze będzie potrzebna:
• Piłka do odbijania się
• Paletka do uderzenia piłką
• Sposób kontroli paletki
• Sposób na zachowanie wyniku i wyświetlenie wyniku w oknie
• Sposób na śledzenie "życia" - jak wiele zwrotów masz
Każdy z tych wymagań będziemy pokrywać jeden po drugim, gdy budujemy nasz program
Piłka
Piłka plażowa, z której korzystaliśmy do tej pory, jest trochę za duża w grze Pong. Potrzebujemy czegoś mniejszego. W tej grze użyjemy sprite′ów, więc musimy zrobić sprite′a dla naszej piłki, a następnie utworzyć jej instancję. Użyjemy klasy Ball z metodami __init __ () i move ():
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, speed, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
<
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > width: <-Odbija się od boków okna
self.speed[0] = -self.speed[0]
if self.rect.top <= 0 :
self.speed[1] = -self.speed[1] <- Odbija się od górnej części okna
Kiedy utworzymy instancję piłki, powiemy jej, który obraz użyć, prędkość piłki i jej lokalizację początkową:
myBall = MyBallClass ('wackyball.bmp', ball_speed, [50, 50])
Musimy także dodać piłkę do grupy, abyśmy mogli wykryć kolizję między piłką a paletką. Możemy utworzyć grupę i jednocześnie dodać do niej piłkę
ballGroup = pygame.sprite.Group(myBall)
Paletka
Dla paletki będziemy trzymać się tradycji Pong i użyjemy prostego prostokąta. Użyjemy białego tła, więc zrobimy paletkę czarnym prostokątem. Stworzymy także klasę sprite i instancję paddle:
class MyPaddleClass(pygame.sprite.Sprite):
def __init__(self, location):
pygame.sprite.Sprite.__init__(self)
image_surface = pygame.surface.Surface([100, 20]) <- Tworzymy powierzchnię paletki
image_surface.fill([0,0,0]) <- Wypełniamy powierzchnię czernią
self.image = image_surface.convert() <- Konwertuje powierzchnię na obraz
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
paddle = MyPaddleClass([270, 400])
Zauważ, że dla paletki nie załadowaliśmy obrazu z pliku obrazu; stworzyliśmy jeden, wypełniając prostokątną powierzchnię czernią. Ale każdy ikonka potrzebuje atrybutu obrazu, więc użyliśmy metody Surface.convert (), aby przekształcić powierzchnię w obraz. Paletka może poruszać się tylko w lewo lub w prawo, a nie w górę lub w dół. Ustawimy pozycję x paletki (jego lewa-prawa pozycja) za myszą, aby użytkownik kontrolował paletkę za pomocą myszy. Ponieważ zrobimy to dobrze w pętli zdarzeń, nie potrzebujemy osobnej metody move () dla wiosła.
Kontrolowanie paletki
Jak już wspomniałem w ostatniej sekcji, będziemy sterować wiosłem za pomocą myszy. Użyjemy zdarzenia MOUSEMOTION, co oznacza, że paletka będzie się poruszać za każdym razem, gdy mysz poruszy się w oknie Pygame. Ponieważ Pygame "widzi" mysz tylko wtedy, gdy znajduje się w oknie Pygame, wiosło zostanie automatycznie ograniczone do krawędzi okna. Ustawimy środek paletki myszą.
Kod powinien wyglądać następująco:
elif event.type == pygame.MOUSEMOTION:
paddle.rect.centerx = event.pos [0]
event.pos to lista z wartościami [x, y] pozycji myszy. Więc event.pos [0] podaje nam lokalizację x myszy, gdy tylko zostanie przeniesiona. Oczywiście, jeśli mysz znajduje się na lewej lub prawej krawędzi, paletka będzie w połowie drogi z okna, ale w porządku. Ostatnią rzeczą, jakiej potrzebujemy, jest wykrycie kolizji między piłką a paletką. W ten sposób "uderzamy" piłkę paletką. Gdy dojdzie do kolizji, po prostu odwrócimy prędkość y piłki (więc gdy będzie spadać i uderzy w paletkę, będzie się odbijać i zacząć podnosić). Kod wygląda tak:
if pygame.sprite.spritecollide (paddle, ballGroup, False):
myBall.speed [1] = -myBall.speed [1]
Musimy także pamiętać o przerysowywaniu rzeczy za każdym razem w pętli. Jeśli połączymy to wszystko razem, otrzymamy bardzo prosty program podobny do Ponga. Oto pełny kod (do tej pory).
Listing 19.4 Pierwsza wersja PyPong
import pygame, sys
from pygame.locals import *
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, speed, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > screen.get_width():
self.speed[0] = -self.speed[0]
if self.rect.top <= 0 :
self.speed[1] = -self.speed[1]
class MyPaddleClass(pygame.sprite.Sprite):
def __init__(self, location = [0,0]):
pygame.sprite.Sprite.__init__(self)
image_surface = pygame.surface.Surface([100, 20])
image_surface.fill([0,0,0])
self.image = image_surface.convert()
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
pygame.init()
screen = pygame.display.set_mode([640,480])
clock = pygame.time.Clock()
ball_speed = [10, 5]
myBall = MyBallClass('wackyball.bmp', ball_speed, [50, 50])
ballGroup = pygame.sprite.Group(myBall)
paddle = MyPaddleClass([270, 400])
running = True
while running: <- Początek głównej pętli while
clock.tick(30)
screen.fill([255, 255, 255])
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == pygame.MOUSEMOTION:
paddle.rect.centerx = event.pos[0]
if pygame.sprite.spritecollide(paddle, ballGroup, False):
myBall.speed[1] = -myBall.speed[1]
myBall.move() <- Przesuwa piłkę
screen.blit(myBall.image, myBall.rect)
screen.blit(paddle.image, paddle.rect)
pygame.display.flip()
pygame.quit()
Oto, jak powinien wyglądać program, gdy działa:
Dobra, więc nie jest to najbardziej ekscytująca gra, ale dopiero zaczynamy tworzyć gry w Pygame. Dodajmy jeszcze kilka rzeczy do naszej gry PyPong
Zachowywanie wyniku i wyświetlanie go za pomocą pygame.font
Musimy śledzić dwie rzeczy: liczbę żyć i liczbę punktów. Aby uprościć sprawę, otrzymamy jeden punkt za każdym razem, gdy piłka znajdzie się w górnej części okna. Damy graczowi trzy życia. Potrzebujemy także sposobu, aby wyświetlić wynik. Pygame używa modułu o nazwie czcionki do wyświetlania tekstu. Oto jak go używać:
• Zrób obiekt font, informując Pygame o wybranym stylu czcionki i rozmiarze.
• Renderuj tekst, przekazując ciąg do obiektu czcionki, który zwraca nową powierzchnię z narysowanym tekstem.
• Nałóż tę powierzchnię na powierzchnię wyświetlacza.
W naszym przypadku ciągiem będzie wynik gracza (ale najpierw musimy go przekonwertować z int na ciąg). Potrzebujemy takiego kodu, tuż przed pętlą zdarzeń (po linii paddle = MyPaddleClass ([270, 400])) w liście 18.4:
score_font = pygame.font.Font (brak, 50) <-Tworzy obiekt czcionki
score_surf = score_font.render (str (wynik), 1, (0, 0, 0))<- Renderuje tekst na powierzchni score_surf
score_pos = [10, 10] <-Ustawia lokalizację tekstu
None w pierwszej linii to miejsce, w którym możemy powiedzieć Pygame, jakiej czcionki (stylu tekstu) chcemy użyć. Umieszczając None, mówimy Pygame, by użył domyślnej czcionki. Następnie w pętli zdarzeń potrzebujemy czegoś takiego:
screen.blit (score_surf, score_pos) <- Blits powierzchni zawierającej tekst partytury w tym miejscu.
Spowoduje to ponowne narysowanie tekstu partytury za każdym razem w pętli. Oczywiście, Carter, jeszcze nie stworzyliśmy zmiennej wyników. (Właśnie do tego doszedłem.) Dodaj tę linię tuż przed kodem, który tworzy obiekt czcionki:
score = 0
Teraz, aby śledzić punkty
. Wykryliśmy już, kiedy piłka uderza w górną część okna, w metodzie move() piłki (aby ją odbić). Po prostu musimy dodać kilka linii:
if self.rect.top <= 0 :
self.speed[1] = -self.speed[1]
score = score + 1
score_surf = score_font.render(str(score), 1, (0, 0, 0))
Śledzenie (ostatnie wywołanie połączenia):
File "C:...", line 59, in
myBall.move()
File "C:\...", line 24, in move
score = score + 1
UnboundLocalError: local variable 'score'
referenced before assignment
Ups! Zapomnieliśmy coś o przestrzeniach nazw. Pamiętasz to duże, długie wyjaśnienie? Teraz możesz zobaczyć prawdziwy przykład tego. Chociaż mamy zmienną o nazwie score, staramy się jej używać z metody move () klasy Ball. Klasa szuka lokalnej zmiennej o nazwie score, która nie istnieje. Zamiast tego chcemy użyć globalnej zmiennej, którą już stworzyliśmy, więc musimy powiedzieć metodzie move (), aby użyła wyniku globalnego, w ten sposób:
def move(self):
global score
Musimy również globalnie utworzyć score_font (obiekt czcionki dla partytury) i score_surf (powierzchnia zawierająca renderowany tekst), ponieważ są one aktualizowane w metodzie move (). Kod powinien więc wyglądać tak:
def move(self):
global score, score_font, score_surf
Teraz powinno działać! Wypróbuj: powinieneś zobaczyć wynik w lewym górnym rogu okna, a wynik powinien wzrosnąć, gdy odbijasz piłkę od górnej części okna.
Śledzenie życia
Teraz śledzimy życie. Obecnie, jeśli tęsknisz za piłką, po prostu spada ona z dołu okna, nigdy więcej nie widziana. Chcemy dać graczowi trzy życia lub szanse, więc zróbmy zmienną o nazwie życia i ustawmy ją na 3:
live = 3
Po tym, jak gracz opuści piłkę i spadnie na dno okna, odejmiemy 1 od życia, zaczekamy kilka sekund, a następnie zaczniemy od nowa z nową piłką:
if myBall.rect.top >= screen.get_rect().bottom:
lives = lives - 1
pygame.time.delay(2000)
myBall.rect.topleft = [50, 50]
Ten kod wchodzi do pętli while. Nawiasem mówiąc, powodem dla którego piszemy myBall.rect dla piłki i get_rect () dla ekranu jest:
• myBall to sprite, a sprite mają poprawkę.
• ekran jest powierzchnią, a powierzchnia nie ma dołączonego prostokąta. Możesz znaleźć rect, który otacza powierzchnię za pomocą funkcji get_rect (). Jeśli wprowadzisz te zmiany i uruchomisz program, zobaczysz, że gracz ma teraz trzy życia.
Dodawanie licznika życia
Większość gier, które dają graczowi wiele żyć, ma sposób pokazania, ile życia zostało. Możemy zrobić to samo z naszą grą. Jednym z łatwych sposobów jest pokazanie liczby piłek równej liczbie pozostałych żyć. Możemy umieścić je w prawym górnym rogu. Oto mała formuła w pętli for, która narysuje licznik życia:
for i in range (lives):
width = screen.get_rect().width
screen.blit(myBall.image, [width - 40 * i, 20]
Kod ten musi również znajdować się w pętli main while, tuż przed pętlą zdarzeń (po linii screen.blit
Koniec gry
Ostatnią rzeczą, którą musimy dodać, jest komunikat "Game Over", gdy gracz zużywa ostatnie życie. Zrobimy kilka obiektów czcionek, które zawierają naszą wiadomość i końcowy wynik gracza, renderujemy je (tworzymy powierzchnie z tekstem na nich) i mieszamy powierzchnie na ekranie. Musimy także powstrzymać piłkę przed ponownym pojawieniem się po ostatniej turze. Aby temu zaradzić, zrobimy zmienną gotową, aby powiedzieć nam, kiedy jesteśmy na końcu gry. Poniższy kod to zrobi - wchodzi do głównej pętli while:
if myBall.rect.top >= screen.get_rect().bottom:
lives = lives - 1 <- Odejmuje życie, jeśli piłka uderzy w dno
if lives == 0:
final_text1 = "Game Over"
final_text2 = "Your final score is: " + str(score)
ft1_font = pygame.font.Font(None, 70)
ft1_surf = ft1_font.render(final_text1, 1, (0, 0, 0))
ft2_font = pygame.font.Font(None, 50)
ft2_surf = ft2_font.render(final_text2, 1, (0, 0, 0))
screen.blit(ft1_surf, [screen.get_width()/2 - \<-Znaki kontynuacji linii
ft1_surf.get_width()/2, 100])
screen.blit(ft2_surf, [screen.get_width()/2 - \<-Znaki kontynuacji linii
ft2_surf.get_width()/2, 200])
pygame.display.flip()
done = True
else: #wait 2 seconds, then start the next ball
pygame.time.delay(2000)
myBall.rect.topleft = [(screen.get_rect().width) - 40*lives, 20]
Jeśli połączymy to wszystko, ostatni program PyPong będzie wyglądał następująco.
Listing 18.5 Końcowy kod PyPong
import pygame, sys
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, speed, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
global score, score_surf, score_font
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > screen.get_width():
self.speed[0] = -self.speed[0]
if self.rect.top <= 0 :
self.speed[1] = -self.speed[1]
score = score + 1
score_surf = score_font.render(str(score), 1, (0, 0, 0))
class MyPaddleClass(pygame.sprite.Sprite):
def __init__(self, location = [0,0]):
pygame.sprite.Sprite.__init__(self)
image_surface = pygame.surface.Surface([100, 20])
image_surface.fill([0,0,0])
self.image = image_surface.convert()
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
pygame.init()
screen = pygame.display.set_mode([640,480])
clock = pygame.time.Clock()
myBall = MyBallClass('wackyball.bmp', [10,5], [50, 50])
ballGroup = pygame.sprite.Group(myBall)
paddle = MyPaddleClass([270, 400])
lives = 3
score = 0
score_font = pygame.font.Font(None, 50)
score_surf = score_font.render(str(score), 1, (0, 0, 0))
score_pos = [10, 10]
done = False
z
running = True
while running: <- Początek programu głównego (pętla while)
clock.tick(30)
screen.fill([255, 255, 255])
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEMOTION:
paddle.rect.centerx = event.pos[0]
if pygame.sprite.spritecollide(paddle, ballGroup, False):
myBall.speed[1] = -myBall.speed[1]
myBall.move() <- Ruch myszki
if not done:
screen.blit(myBall.image, myBall.rect)
screen.blit(paddle.image, paddle.rect)
screen.blit(score_surf, score_pos)
for i in range (lives):
width = screen.get_width()
screen.blit(myBall.image, [width - 40 * i, 20])
pygame.display.flip()
if myBall.rect.top >= screen.get_rect().bottom:
lives = lives - 1
if lives == 0:
final_text1 = "Game Over"
final_text2 = "Your final score is: " + str(score)
ft1_font = pygame.font.Font(None, 70)
ft1_surf = ft1_font.render(final_text1, 1, (0, 0, 0))
ft2_font = pygame.font.Font(None, 50)
ft2_surf = ft2_font.render(final_text2, 1, (0, 0, 0))
screen.blit(ft1_surf, [screen.get_width()/2 - \
ft1_surf.get_width()/2, 100])
screen.blit(ft2_surf, [screen.get_width()/2 - \
ft2_surf.get_width()/2, 200])
pygame.display.flip()
done = True
else:
pygame.time.delay(2000)
myBall.rect.topleft = [50, 50]
pygame.quit()
Jeśli uruchomisz kod z listingu, powinieneś zobacz coś takiego
Jeśli zwracałeś uwagę w edytorze, jest to około 75 linii kodu (plus kilka pustych linii). To największy program, jaki do tej pory stworzyliśmy, ale ma też wiele rzeczy do zrobienia, mimo że po uruchomieniu wygląda całkiem prosto. W następnej imprezie dowiesz się o dźwiękach w Pygame, a my dodamy trochę dźwięku do naszej gry PyPong.
Czego się nauczyłeś?
• Wydarzenia
• Pętla zdarzenia Pygame
• Obsługa zdarzeń
• Zdarzenia klawiatury
• Zdarzenia myszy
• Zdarzenia czasowe (i typy zdarzeń użytkownika)
• pygame.font (do dodawania tekstu do programów Pygame)
• Łączenie wszystkich tych rzeczy w jedną grę!
Sprawdź swoją wiedzę
1 Jakie są dwa rodzaje zdarzeń, na które program może odpowiedzieć?
2 Jak nazywasz fragment kodu, który dotyczy zdarzenia?
3 Jaka jest nazwa typu zdarzenia, którego Pygame używa do wykrywania naciskanych klawiszy?
4 Jaki atrybut zdarzenia MOUSEMOVE informuje, gdzie w oknie znajduje się mysz?
5 Jak dowiesz się, jaki jest następny dostępny numer zdarzenia w Pygame (na przykład, jeśli chcesz dodać zdarzenie użytkownika)?
6 Jak stworzyć timer do generowania zdarzeń timera w Pygame?
7 Jaki obiekt jest używany do wyświetlania tekstu w oknie Pygame?
8 Jakie są trzy kroki, aby tekst pojawił się w oknie Pygame?
Wypróbuj to
1 Czy zauważyłeś coś dziwnego, gdy piłka uderza w bok wiosła zamiast w górę? Od czasu do czasu odbija się na środku wiosła. Czy wiesz dlaczego? Czy możesz to naprawić? Spróbuj, zanim spojrzysz na moje rozwiązanie w sekcji odpowiedzi.
2 Spróbuj przepisać program (listing 19.4 lub 19.5), tak aby odbiły się losowo. Możesz zmienić sposób, w jaki piłka odbija się od wiosła lub ścian, sprawić, że prędkość będzie losowa lub coś innego, o czym myślisz. (Widziałeś random.randint () i random.random () w części 15, więc wiesz, jak generować liczby losowe, zarówno liczby całkowite, jak i zmiennoprzecinkowe.)
W ostatniej części stworzyliśmy naszą pierwszą graficzną grę PyPong, wykorzystując to, czego się dowiedzieliśmy, o grafice, duszkach, kolizjach, animacjach i wydarzeniach. W tym rozdziale dodamy kolejny element układanki: dźwięk. Każda gra wideo i wiele innych programów używa dźwięku, aby uczynić je bardziej interesującymi i przyjemnymi. Dźwięk może być zarówno wejściem, jak i wyjściem. Jako dane wejściowe podłączysz mikrofon lub inne źródło dźwięku do komputera, a program nagra dźwięk lub zrobi z nim coś innego (może wysłać go przez Internet). Ale dźwięk jest o wiele bardziej powszechny jako produkt wyjściowy, i to właśnie omówimy tutaj. Dowiesz się, jak odtwarzać dźwięki, takie jak muzyka lub efekty dźwiękowe, i dodawać je do swoich programów, takich jak PyPong.
Więcej pomocy od Pygame - mixer
Dźwięk to kolejna z tych rzeczy, na przykład grafika, która może się skomplikować, ponieważ różne komputery mają inny sprzęt i oprogramowanie do odtwarzania dźwięków. Aby uprościć sprawę, ponownie otrzymamy pomoc od Pygame. Pygame ma moduł do pracy z dźwiękiem, zwany pygame.mixer. W prawdziwym, nieprogramującym świecie urządzenie, które pobiera różne dźwięki i łączy je, nazywa się mikserem, a tam właśnie Pygame ma nazwę.
Tworzenie dźwięków a odtwarzanie dźwięków
Istnieją dwa podstawowe sposoby generowania dźwięków przez program. Program może generować lub syntetyzować dźwięki - oznacza to tworzenie ich od podstaw, tworząc fale dźwiękowe o różnej wysokości i głośności. Lub program może odtwarzać nagrany dźwięk. Może to być utwór muzyczny na płycie CD, plik dźwiękowy MP3 lub inny rodzaj pliku dźwiękowego. Tutaj dowiesz się tylko o odtwarzaniu dźwięków. Tworzenie własnych dźwięków od podstaw jest dość dużym tematem, a jest tak dużo miejsca. Jeśli interesują Cię dźwięki generowane komputerowo, istnieje wiele programów do generowania muzyki i dźwięku z komputera.
Odtwarzanie dźwięków
Gdy odtwarzasz dźwięk, bierzesz plik dźwiękowy z dysku twardego (lub z płyty CD lub czasami z Internetu) i zamieniasz go w dźwięk, który możesz usłyszeć w głośnikach komputera lub słuchawkach. Istnieje wiele różnych typów plików dźwiękowych, których można używać na komputerze. Oto niektóre z najbardziej popularnych:
• Pliki Wave - nazwy plików kończą się na .wav, podobnie jak hello.wav.
• Pliki MP3 - nazwy plików kończą się na .mp3, podobnie jak mySong.mp3.
• Pliki WMA (Windows Media Audio) - nazwy plików kończą się na .wma, jak someSong.wma.
• Pliki Ogg Vorbis - nazwy plików kończą się na .ogg, podobnie jak yourSong.ogg.
W naszych przykładach będziemy używać plików .wav i .mp3. Wszystkie dźwięki, których użyjemy, znajdują się w folderze dźwięków, w którym zainstalowano HelloWorld. Na przykład na komputerach z systemem Windows powinno to być c: Pliki programów Przykłady przykładów HelloWorld. Istnieją dwa sposoby dołączenia pliku dźwiękowego do programu. Możesz skopiować plik dźwiękowy do tego samego folderu, w którym zapisany jest program. W tym miejscu Python spodziewa się znaleźć plik, więc możesz po prostu użyć nazwy pliku w swoim programie, tak jak poniżej:
sound_file = "my_sound.wav"
Jeśli nie skopiujesz pliku dźwiękowego do tego samego folderu co program, musisz powiedzieć Pythonowi dokładnie, gdzie znajduje się plik dźwiękowy, tak
sound_file = "c: Program Files HelloWorld brzmi my_sound.wav"
Dla naszych przykładów zakładam, że skopiowałeś pliki dźwiękowe do folderu, w którym zapisujesz swoje programy. Oznacza to, że wszędzie tam, gdzie w przykładach używany jest plik dźwiękowy, zobaczysz tylko nazwę pliku i nie pełna lokalizacja pliku. Jeśli nie skopiujesz plików dźwiękowych do folderu programu, musisz zastąpić nazwy plików pełnymi lokalizacjami plików.
Rozpoczęcie pygame.mixer
Aby odtwarzać dźwięki, musisz zainicjować pygame.mixer. Pamiętasz, co znaczy inicjowanie? Oznacza to, że na początku otrzymasz coś gotowego. Przygotowanie pygame.mixer jest bardzo proste. Musimy tylko dodać linię
pygame.mixer.init()
po zainicjowaniu Pygame. Tak więc kod na początku programu używającego Pygame do dźwięku wygląda tak:
import pygame
pygame.init ()
pygame.mixer.init ()
Teraz jesteśmy gotowi do odtwarzania niektórych dźwięków. Istnieją dwa główne typy dźwięków, których będziesz używać w swoich programach. Pierwsze to efekty dźwiękowe lub klipy dźwiękowe. Są one zazwyczaj krótkie i najczęściej są przechowywane w plikach .wav. Dla tego rodzaju dźwięków pygame.mixer używa obiektu Sound, takiego jak ten:
splat = pygame.mixer.Sound ("splat.wav")
splat.play ()
Innym rodzajem dźwięku, którego często używasz, jest muzyka. Muzyka jest najczęściej przechowywana w plikach .mp3, .wma lub .ogg. Aby je odtworzyć, Pygame używa modułu w mikserze zwanego muzyką. Używasz go w ten sposób:
pygame.mixer.music.load ("bg_music.mp3")
pygame.mixer.music.play ()
Spowoduje to odtworzenie utworu (lub tego, co znajduje się w pliku muzycznym), a następnie zatrzymanie. Spróbujmy zagrać kilka dźwięków. Po pierwsze, spróbujmy zagrać dźwięk "splat". Nadal potrzebujemy pętli while, aby program Pygame był uruchomiony. Ponadto, nawet jeśli teraz nie będziemy rysować grafiki, programy Pygame nie będą zadowolone, jeśli nie mają okna. W niektórych systemach zainicjowanie miksera zajmuje trochę czasu. Jeśli spróbujesz rozpocząć odtwarzanie dźwięku zbyt szybko, usłyszysz tylko jego część lub wcale. Poczekamy więc trochę, aż mikser się przygotuje. Kod powinien wyglądać podobnie do poniższej listy.
Listing 20.1 Próbowanie dźwięków w Pygame
import pygame, sys
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode([640,480]) <-Tworzy okno Pygame
pygame.time.delay(1000) <- Czeka sekundę, aż mikser zakończy inicjowanie
splat = pygame.mixer.Sound("splat.wav") <- Tworzy obiekt dźwiękowy
splat.play() <- Odtwarza dźwięk
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Spróbuj tego i zobacz, jak to działa. Teraz spróbujmy odtworzyć muzykę za pomocą modułu mixer.music. Musimy tylko zmienić kilka linii w listingu 20.1. Nowy kod zostanie wyświetlony obok.
Listing 20.2 Odtwarzanie muzyki
import pygame, sys
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode([640,480])
pygame.time.delay(1000)
pygame.mixer.music.load("bg_music.mp3")
pygame.mixer.music.play()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Spróbuj tego i upewnij się, że słychać odtwarzanie muzyki. Nie wiem o tobie, ale wydawało mi się to trochę głośne. Musiałem zmniejszyć głośność na moim komputerze. Dowiedzmy się, jak kontrolować głośność dźwięku w programach.
Kontrolowanie głośności
Możesz kontrolować głośność dźwięku na komputerze za pomocą regulatorów głośności. W systemie Windows odbywa się to za pomocą małej ikony głośnika w zasobniku systemowym. To ustawienie kontroluje głośność wszystkich dźwięków na komputerze. Możesz również mieć pokrętło głośności na samych głośnikach. Ale możesz także kontrolować głośność wysyłaną przez Pygame na kartę dźwiękową twojego komputera. Dobrą rzeczą jest to, że możesz indywidualnie kontrolować głośność każdego dźwięku - np. wyciszenie muzyki i "splat" nieco głośniej, jeśli chcesz. W przypadku muzyki używasz pygame.mixer.music.set_volume(). W przypadku dźwięków istnieje metoda set_volume() dla każdego obiektu dźwiękowego. W naszym pierwszym przykładzie splat był nazwą naszego obiektu dźwiękowego, więc użyliśmy splat.set_volume(). Wolumin to liczba zmiennoprzecinkowa od 0 do 1; na przykład 0,5 to 50 procent lub połowa objętości. Teraz spróbujmy mieć muzykę i dźwięk w tym samym programie. Co powiesz na odtwarzanie utworu, a następnie na zakończenie "splat" na końcu. Będziemy też nieco zmniejszać głośność naszego dźwięku. Ustawimy muzykę na 30 procent, a dźwięk "splat" na 50 procent. Kod powinien wyglądać mniej więcej tak.
Listing 20.3 Muzyka i dźwięk z regulacją głośności
import pygame, sys
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode([640,480])
pygame.time.delay(1000)
pygame.mixer.music.load("bg_music.mp3")
pygame.mixer.music.set_volume(0.30) <- Dostosowuje głośność muzyki
pygame.mixer.music.play()
splat = pygame.mixer.Sound("splat.wav")
splat.set_volume(0.50) <-Dostosowuje głośność efektu dźwiękowego
splat.play()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
Odtwarzanie muzyki w tle
Muzyka w tle jest przeznaczona do odtwarzania w tle podczas gry. Po uruchomieniu piosenki w tle, Pygame musi przygotować się do innych rzeczy, takich jak poruszanie sprite′mi lub sprawdzanie danych wejściowych za pomocą myszy i klawiatury. Nie czeka na zakończenie utworu. Ale co, jeśli chcesz wiedzieć, kiedy piosenka się kończy? Może chcesz rozpocząć inną piosenkę lub odtworzyć inny dźwięk (jak chcemy to zrobić). Skąd wiesz, kiedy skończy się muzyka? Pygame ma sposób, by ci powiedzieć: możesz zapytać moduł mixer.music, czy nadal jest zajęty odtwarzaniem utworu. Jeśli tak, wiesz, że piosenka nie została jeszcze wykonana. Jeśli nie jest zajęty, wiesz, że utwór został ukończony. Spróbujmy tego. Aby dowiedzieć się, czy moduł muzyczny jest nadal zajęty odtwarzaniem utworu, użyj funkcji get_busy () modułu mixer.music. Spowoduje to zwrócenie wartości True, jeśli nadal jest zajęta lub Fałsz, jeśli nie jest. Tym razem sprawimy, że nasz program odtworzy utwór, a następnie odtworzy efekt dźwiękowy, a następnie automatycznie zakończy program. Następny listing pokazuje, jak to zrobić.
Listing 20.4 Oczekiwanie na koniec utworu
import pygame, sys
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode([640,480])
pygame.time.delay(1000)
pygame.mixer.music.load("bg_music.mp3")
pygame.mixer.music.set_volume(0.3)
pygame.mixer.music.play()
splat = pygame.mixer.Sound("splat.wav")
splat.set_volume(0.5)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if not pygame.mixer.music.get_busy(): <-Sprawdza, czy odtwarzanie muzyki zostało zakończone
splat.play()
pygame.time.delay(1000) <-Czeka sekundę na dźwięk "splat", aby zakończyć
running = False
pygame.quit()
Ten kod odtworzy utwór raz, a następnie odtworzy efekt dźwiękowy, a następnie program zakończy się.
Powtarzająca się muzyka
Jeśli zamierzasz użyć utworu jako podkładu muzycznego do gry, prawdopodobnie chcesz, aby muzyka była kontynuowana tak długo, jak długo program jest uruchomiony. Moduł muzyczny może to zrobić za Ciebie. Możesz powtórzyć odtwarzanie określoną liczbę razy, tak jak to
pygame.mixer.music.play (3)
To odtworzy utwór trzy razy. Możesz również powtórzyć utwór na zawsze, przekazując specjalną wartość -1, w ten sposób:
pygame.mixer.music.play (-1)
Będzie to powtarzać utwór na zawsze lub tak długo, jak działa program Pygame. (Właściwie nie musi to być -1. Każda liczba ujemna zadziała.)
Dodawanie dźwięków do PyPong
Teraz, gdy znasz podstawy odtwarzania dźwięków, dodajmy trochę dźwięku do naszej gry PyPong. Najpierw dodamy dźwięk za każdym razem, gdy piłka uderzy w rakietkę. Wiemy już, kiedy to jest, ponieważ używamy wykrywania kolizji, aby odwrócić kierunek piłki, gdy uderzy ona w rakietkę?
jeśli pygame.sprite.spritecollide (paddle, ballGroup, False):
myBall.speed [1] = -myBall.speed [1]
Teraz musimy dodać kod odtwarzający dźwięk. Musimy dodać pygame.mixer.init () w pobliżu początku programu, a także utworzymy obiekt dźwiękowy, aby był gotowy do użycia:
hit = pygame.mixer.Sound ("hit_paddle.wav")
Ustawimy także głośność, aby nie była zbyt głośna:
hit.set_volume (0.4)
Wtedy, gdy piłka uderzy w rakietkę, zagrają dźwięk:
jeśli pygame.sprite.spritecollide (paddle, ballGroup, False):
myBall.speed [1] = -myBall.speed [1]
hit.play () <- Odtwarza dźwięk
Spróbuj dodać to do programu PyPong . Upewnij się, że skopiowałeś plik hit_paddle.wav do tego samego miejsca, w którym zapisujesz swój program. Kiedy go uruchomisz, powinieneś usłyszeć dźwięk za każdym razem, gdy piłka uderza w rakietkę.
Więcej zwariowanych dźwięków
Teraz, gdy mamy uderzenie, gdy piłka uderza w rakietkę, dodajmy jeszcze kilka innych dźwięków. Dodamy dźwięki do tych rzeczy:
• Gdy piłka uderza w ściany boczne
• Gdy piłka uderza w górną ścianę, a gracz zdobywa punkt
• Gdy gracz opuści piłkę i piłka uderzy w dno
• Kiedy zaczyna się nowe życie
• Po zakończeniu gry
Najpierw musimy stworzyć obiekty dźwiękowe dla wszystkich tych. Możesz umieścić kod w dowolnym miejscu po pygame.mixer.init (), ale przed pętlą while:
hit_wall = pygame.mixer.Sound ("hit_wall.wav")
hit_wall.set_volume (0.4)
get_point = pygame.mixer.Sound ("get_point.wav")
get_point.set_volume (0.2)
splat = pygame.mixer.Sound ("splat.wav")
splat.set_volume (0.6)
new_life = pygame.mixer.Sound ("new_life.wav")
new_life.set_volume (0.5)
bye = pygame.mixer.Sound ("game_over.wav")
bye.set_volume (0.6)
Wybrałem poziomy głośności, po prostu wypróbowując je, aby zobaczyć, co brzmi dobrze. Możesz ustawić je na co tylko chcesz. Pamiętaj, aby skopiować wszystkie pliki dźwiękowe do dowolnego miejsca, w którym zapisujesz swój kod. Wszystkie te dźwięki można znaleźć w folderze przykładów lub na stronie internetowej. Teraz musimy dodać metody play () do miejsc, w których te zdarzenia występują. Dźwięk hit_wall powinien się zdarzyć za każdym razem, gdy uderzymy w boki okna. Wykrywamy to w metodzie move () piłki i odwracamy prędkość x piłki (aby piłka "odbijała się" od boków). W pierwotnym listingu jest to wiersz 14:
if self.rect.left <0 lub self.rect.right> screen.get_width ():
Więc kiedy odwracamy kierunek, możemy również odtwarzać nasz dźwięk. Kod wygląda tak:
if self.rect.left <0 lub self.rect.right> screen.get_width ():
self.speed [0] = -self.speed [0]
hit_wall.play () <- Odtwarza dźwięk uderzenia w ścianę boczną
Możemy zrobić to samo dla dźwięku get_point. Troszkę dalej w metodzie move () kulki wykrywamy uderzenie piłki w górną część okna. W tym miejscu odbijamy piłkę i dodajemy punkt do wyniku gracza. Teraz zagramy również dźwięk. Nowy kod wygląda tak:
if self.rect.top <= 0 :
self.speed[1] = -self.speed[1]
points = points + 1
score_text = font.render(str(points), 1, (0, 0, 0))
get_point.play() <- Odtwarza dźwięk, aby uzyskać punkt
Spróbuj dodać te dodatki, aby zobaczyć, jak działają. Następnie możemy dodać kod, aby zagrać dźwięk, gdy gracz opuści piłkę i straci życie. Wykryliśmy to w pętli main while, w linii 63 oryginalnej listy 18.5 (jeśli myBall.rect.top> = screen.get_rect (). Bottom :). Musimy tylko dodać linię taką jak ta:
if myBall.rect.top >= screen.get_rect().bottom:
splat.play() <- Odtwarza dźwięk za brak piłki i utratę życia
# stracić życie, jeśli piłka uderzy w dół
lives = lives - 1
Możemy również dodać dźwięk, gdy zaczyna się nowe życie. Dzieje się tak w trzech ostatnich liniach listingu w bloku else. Tym razem nadamy naszemu efektowi dźwiękowemu trochę czasu, zanim zaczniemy nowe życie:
else:
pygame.time.delay(1000)
new_life.play()
myBall.rect.topleft = [50, 50]
screen.blit(myBall.image, myBall.rect)
pygame.display.flip()
pygame.time.delay(1000)
Zamiast czekać dwie sekundy (tak jak w oryginalnym programie), czekamy jedną sekundę (1000 milisekund), odtwarzamy dźwięk, a następnie czekamy kolejną sekundę przed rozpoczęciem nowej tury. Spróbuj i zobacz, jak to brzmi. Do dodania jest jeszcze jeden efekt dźwiękowy, i to już po zakończeniu gry. Dzieje się tak w linii 65 listingu (if lives == 0 :). Dodaj linię, aby odtworzyć dźwięk "bye" tutaj:
if lives == 0:
bye.play()
Spróbuj tego i zobacz, jak to działa.
Ups! Zapomnieliśmy coś. Kod odtwarzający dźwięk "bye" i dźwięk "splat" znajduje się w głównej pętli while, która nie zatrzymuje się, dopóki okno Pygame nie zostanie zamknięte, więc będzie ono odtwarzane w kółko tak długo, jak działa pętla while! Musimy dodać coś, aby upewnić się, że gra się tylko raz. Jedną z rzeczy, których możemy użyć, jest zmienna o nazwie done, która informuje nas, kiedy gra się skończy. Możemy zmienić nasz kod, aby wyglądał tak:
if myBall.rect.top >= screen.get_rect().bottom:
if not done:
splat.play()
lives = lives - 1
if lives == 0:
if not done:
bye.play()
Spróbuj tego i upewnij się, że działa.
Hmmm
Może będziemy musieli trochę o tym pomyśleć. Mamy naszą zmienną zrobioną, aby powiedzieć nam, kiedy gra się skończyła, i używamy jej, aby wiedzieć, kiedy zagrać nasz "bye" dźwięk, a także kiedy wyświetlić ostateczną wiadomość z wynikiem. Ale co robi piłka? Nawet jeśli piłka dotarła do dolnej części okna, nadal się porusza! Nie ma nic, co mogłoby powstrzymać piłkę przed zejściem w dół, więc jej wartość y po prostu staje się coraz większa. To "poniżej" ekranu, na którym go nie widzimy, ale wciąż go słyszymy! Piłka wciąż się porusza, więc wciąż odbija się od "boków", gdy jej wartość x staje się wystarczająco duża lub wystarczająco mały. Dzieje się tak w metodzie move () i ta metoda działa tak długo, jak działa pętla while. Jak możemy to naprawić? Jest kilka sposobów:
• Zatrzymaj ruch piłki, ustawiając jej prędkość na [0,0] po zakończeniu gry.
• Sprawdź, czy piłka znajduje się poniżej dolnej krawędzi okna i nie odtwarzaj dźwięku hit_wall, jeśli jest.
• Sprawdź wykonaną zmienną i nie odtwarzaj dźwięku hit_wall, jeśli gra jest ukończona.
Wybrałem drugą opcję, ale każda z nich zadziała. Pozostawię ci wybór jednego z nich i zmodyfikowanie kodu, aby rozwiązać ten problem.
Dodawanie muzyki do PyPong
Pozostaje tylko jedna rzecz - dodać muzykę. Musimy załadować plik muzyczny, ustawić głośność i rozpocząć odtwarzanie. Chcemy, aby powtarzał się podczas gry, więc użyjemy specjalnej wartości -1, w ten sposób:
pygame.mixer.music.load("bg_music.mp3")
pygame.mixer.music.set_volume(0.3)
pygame.mixer.music.play(-1)
Ten kod może przejść gdziekolwiek przed główną pętlą while. To rozpocznie odtwarzanie muzyki. Teraz musimy zatrzymać muzykę na końcu, a jest na to dobry sposób. pygame.mixer.music ma metodę zwaną fadeout (), która stopniowo wycisza muzykę, zamiast ją nagle zatrzymywać. Po prostu powiesz, jak długo powinno się zanikać bądź tak: to jest 2000 milisekund, czyli 2 sekundy. Ta linia może iść w to samo miejsce, w którym ustawiliśmy done = True. (Nie ma znaczenia, czy pojawi się przed, czy po.) Program jest teraz kompletny z efektami dźwiękowymi i muzyką. Spróbuj i zobacz, jak to brzmi! W przypadku, gdy chcesz zobaczyć, jak to wszystko idzie w parze, zamieściłem moją ostateczną wersję na listingu 20.5. Musisz się upewnić, że wackyball.bmp i wszystkie pliki dźwiękowe znajdują się w tym samym folderze co program
Listing 20.5 PyPong z dźwiękiem i muzyką
import pygame, sys
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, speed, location = [0,0]):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
def move(self):
self.speed = speed
global points, score_text
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > screen.get_width():
self.speed[0] = -self.speed[0]
if self.rect.top < screen.get_height():
hit_wall.play() <- Odtwarza dźwięk, gdy piłka uderza w ścianę boczną
if self.rect.top <= 0 :
self.speed[1] = -self.speed[1]
points = points + 1
score_text = font.render(str(points), 1, (0, 0, 0))
get_point.play() <- Odtwarza dźwięk, gdy piłka uderza w górę (gracz otrzymuje punkt)
class MyPaddleClass(pygame.sprite.Sprite):
def __init__(self, location = [0,0]):
pygame.sprite.Sprite.__init__(self)
image_surface = pygame.surface.Surface([100, 20])
image_surface.fill([0,0,0])
self.image = image_surface.convert()
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
pygame.init() <- Inicjalizuje moduł dźwiękowy Pygame
pygame.mixer.init()
pygame.mixer.music.load("bg_music.mp3") <-Ładuje plik muzyczny
pygame.mixer.music.set_volume(0.3) <-Ustawia głośność muzyki
pygame.mixer.music.play(-1) <-Rozpoczyna odtwarzanie muzyki; powtarza na zawsze
hit = pygame.mixer.Sound("hit_paddle.wav")
hit.set_volume(0.4)
new_life = pygame.mixer.Sound("new_life.wav")
new_life.set_volume(0.5)
splat = pygame.mixer.Sound("splat.wav")
splat.set_volume(0.6)
hit_wall = pygame.mixer.Sound("hit_wall.wav")
hit_wall.set_volume(0.4)
get_point = pygame.mixer.Sound("get_point.wav")
get_point.set_volume(0.2)
bye = pygame.mixer.Sound("game_over.wav")
bye.set_volume(0.6)
screen = pygame.display.set_mode([640,480])
clock = pygame.time.Clock()
myBall = MyBallClass('wackyball.bmp', [12,6], [50, 50])
ballGroup = pygame.sprite.Group(myBall)
paddle = MyPaddleClass([270, 400])
lives = 3
points = 0
font = pygame.font.Font(None, 50)
score_text = font.render(str(points), 1, (0, 0, 0))
textpos = [10, 10]
done = False
running = True
while running:
clock.tick(30)
screen.fill([255, 255, 255])
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEMOTION:
paddle.rect.centerx = event.pos[0]
if pygame.sprite.spritecollide(paddle, ballGroup, False):
hit.play() <- Odtwarza dźwięk, gdy piłka uderza w paletkę
myBall.speed[1] = -myBall.speed[1]
myBall.move()
if not done:
screen.blit(myBall.image, myBall.rect)
screen.blit(paddle.image, paddle.rect)
screen.blit(score_text, textpos)
for i in range (lives):
width = screen.get_width()
screen.blit(myBall.image, [width - 40 * i, 20])
pygame.display.flip()
if myBall.rect.top >= screen.get_rect().bottom:
if not done:
splat.play() <-Odtwarza dźwięk, gdy gracz traci życie
lives = lives - 1
if lives <= 0:
if not done:
pygame.time.delay(1000) <- Czeka sekundę, a następnie odtwarza dźwięk końcowy
bye.play()
final_text1 = "Game Over"
final_text2 = "Your final score is: " + str(points)
ft1_font = pygame.font.Font(None, 70)
ft1_surf = font.render(final_text1, 1, (0, 0, 0))
ft2_font = pygame.font.Font(None, 50)
ft2_surf = font.render(final_text2, 1, (0, 0, 0))
screen.blit(ft1_surf, [screen.get_width()/2 - \
ft1_surf.get_width()/2, 100])
screen.blit(ft2_surf, [screen.get_width()/2 - \
ft2_surf.get_width()/2, 200]
pygame.display.flip()
done = True
pygame.mixer.music.fadeout(2000) <- Znika muzyka
else:
pygame.time.delay(1000)
new_life.play() <-Odtwarza dźwięk, gdy rozpoczyna się nowe życie
myBall.rect.topleft = [50, 50]
screen.blit(myBall.image, myBall.rect)
pygame.display.flip()
pygame.time.delay(1000)
pygame.quit()
To trwa długo! (Jest około 100 linii plus puste linie.) Może to być nieco krótsze, ale może być trudniejsze do przeczytania i zrozumienia. W tych rozdziałach budowaliśmy program po trochu, więc nie musieliście wpisywać go od razu. Jeśli poszedłeś razem z książką, powinieneś zrozumieć, co robi każda część programu i jak te części idą w parze. Na wszelki wypadek pełna lista znajduje się w folderze przykładów na komputerze (jeśli został zainstalowany) i na stronie internetowej. W następnym rozdziale stworzymy inny rodzaj programu graficznego: jeden z przyciskami, menu itd. - GUI.
Czego się nauczyłeś?
• Jak dodać dźwięk do swoich programów
• Jak odtwarzać klipy dźwiękowe (zwykle pliki WAV)
• Jak odtwarzać pliki muzyczne (zwykle pliki .mp3)
• Jak wiedzieć, kiedy dźwięk jest odtwarzany
• Jak kontrolować głośność efektów dźwiękowych i muzyki
• Jak powtarzać muzykę, aby była odtwarzana wielokrotnie
• Jak stopniowo ściemniać muzykę
Sprawdź swoją wiedzę
1 Jakie są trzy typy plików używanych do przechowywania dźwięku?
2 Jakiego modułu Pygame używa się do odtwarzania muzyki?
3 Jak ustawić głośność obiektu dźwiękowego Pygame?
4 Jak ustawić głośność muzyki w tle?
5 Jak wygasać muzykę?
Wypróbuj to
1 Spróbuj dodać dźwięki do gry z odgadywaniem numerów w rozdziale 1. Mimo że gra jest w trybie tekstowym, musisz dodać okno Pygame, tak jak w przykładach w tej części. Istnieje kilka dźwięków, których można użyć w folderze przykładów (i na stronie):
• Ahoy.wav
• TooLow.wav
• TooHigh.wav
• WhatsYerGuess.wav
• AvastGotIt.wav
• NoMore.wav
Lub może być fajnie nagrywać własne dźwięki. Możesz użyć czegoś takiego jak Sound Recorder w Windows, lub możesz pobrać darmowy program Audacity
Zrobiliśmy kilka prostych GUI w Części 6, kiedy użyliśmy EasyGui do stworzenia niektórych okien dialogowych (lub po prostu skrótów). Ale GUI potrzebują czegoś więcej niż dialogów. W większości nowoczesnych programów cały program działa w GUI. W tym rozdziale omówimy tworzenie GUI z PyQt, co daje większą elastyczność i kontrolę nad wyglądem. PyQt to moduł, który pomaga tworzyć GUI. Najpierw użyjemy go do stworzenia wersji naszego programu do konwersji temperatury.
Praca z PyQt
Przed użyciem PyQt musisz upewnić się, że jest zainstalowany na Twoim komputerze. Jeśli zainstalowałeś Pythona za pomocą instalatora , PyQt jest już zainstalowany. Jeśli nie, musisz pobrać i zainstalować go oddzielnie. PyQt możesz pobrać ze strony
www.riverbankcomputing.com/software/pyqt / download.
Upewnij się, że masz poprawną wersję systemu operacyjnego i używanej wersji Pythona. Używamy PyQt 4.1. Istnieją zasadniczo dwie główne części do napisania programu GUI. Musisz utworzyć sam interfejs użytkownika ("UI") i musisz utworzyć kod, który sprawi, że interfejs użytkownika zrobi to, co chcesz. Tworzenie interfejsu użytkownika polega na umieszczaniu takich rzeczy, jak przyciski, pola tekstowe, pola wyboru itd. w oknie. Następnie piszesz kod, który powoduje, że coś się dzieje po kliknięciu przycisku, wpisaniu pola tekstowego lub wybraniu opcji z pola wyboru. Używając Qt, tworzysz interfejs użytkownika używając czegoś o nazwie Qt Designer. Zobaczmy, jak to działa.
Qt Designer
Po zainstalowaniu PyQt jedną z zainstalowanych rzeczy był program o nazwie Qt Designer. Znajdź ikonę tego (na przykład w menu Start w systemie Windows) i uruchom Qt Designer. Kiedy to zrobisz, powinieneś zobaczyć otwarte okno Qt, a po środku zobaczysz okno dialogowe Nowy formularz:
Form to termin programowania dla okna GUI. Ponieważ zamierzasz utworzyć nowe okno GUI, wybierz opcję Okno główne, a następnie kliknij przycisk Utwórz. Teraz spójrzmy na resztę okna Qt.
W interfejsie GUI poszczególne przyciski, pola wyboru itd. Są nazywane widżetami. Nazywane są również komponentami, a czasami także kontrolkami.
Po lewej stronie znajduje się okienko Widget, w którym widać wszystkie różne elementy graficzne, których można użyć w interfejsie GUI. Są pogrupowane w kilka różnych kategorii. Po prawej stronie znajduje się Inspektor obiektów i Edytor właściwości. W tym miejscu możesz sprawdzić i zmienić właściwości widżetów. Istnieje również trzecie pole, którego funkcja jest wybierana przez zakładki na dole. Może to być Inspektor Sygnału / Gniazda, Edytor Akcji lub Przeglądarka Zasobów. W środku znajduje się nowy, pusty formularz, który właśnie utworzyłeś. Mówi, że okno główne - bez tytułu u góry, ponieważ jeszcze nie nadano mu nazwy. To puste miejsce to miejsce, w którym umieścisz widżety, aby utworzyć interfejs użytkownika. (Na komputerze Mac, aby uzyskać ten widok, musisz przejść do Qt Designer> Preferencje i zmienić tryb interfejsu użytkownika z wielu okien najwyższego poziomu na zadokowane.
Dodajmy przycisk do GUI.
Po lewej stronie okna Qt Designer znajdź sekcję Przyciski i poszukaj widżetu Przycisk Push. Przeciągnij przycisk Push do pustego formularza i upuść go gdzieś. Teraz masz przycisk na formularzu i ma etykietę PushButton.
Teraz spójrz na prawą stronę, w edytorze właściwości. Jeśli przycisk jest nadal zaznaczony (jeśli ma małe niebieskie kwadraty wokół siebie), zobaczysz jego właściwości w Edytorze właściwości. Widać, że nazwa przycisku to PushButton. Jeśli przewijasz niektóre inne właściwości na liście Właściwości, możesz zobaczyć takie rzeczy, jak szerokość i wysokość przycisku, jego położenie x i y, i tak dalej.
Teraz spójrz na prawą stronę, w edytorze właściwości. Jeśli przycisk jest nadal zaznaczony (jeśli ma małe niebieskie kwadraty wokół niego), zobaczysz jego właściwości w Edytorze właściwości. Widać, że nazwa przycisku to PushButton. Jeśli przewijasz niektóre inne właściwości na liście Właściwości, możesz zobaczyć takie rzeczy, jak szerokość i wysokość przycisku, jego położenie x i y, i tak dalej.
Zmiana przycisku
Istnieją dwa sposoby zmiany rozmiaru lub pozycji przycisku w oknie: przeciągnij go myszą lub zmień właściwości Rozmiar lub Położenie. Spróbuj obu sposobów przesuwania i zmiany rozmiaru przycisku, aby zobaczyć, jak działają. Aby przesunąć przycisk za pomocą myszy, kliknij gdziekolwiek przycisk i przeciągnij go do nowej pozycji. Aby zmienić rozmiar za pomocą myszy, kliknij jeden z niebieskich kwadratów wokół krawędzi przycisku (są one nazywane uchwytami) i przeciągnij krawędź lub róg przycisku, aby zwiększyć lub zmniejszyć. Aby zmienić jego rozmiar za pomocą właściwości, kliknij mały trójkąt obok właściwości geometrii, aby rozwinąć właściwości X, Y, Szerokość i Wysokość. Wystarczy wpisać różne liczby, aby przesunąć lub zmienić rozmiar przycisku. Możesz także zmienić tekst wyświetlany na przycisku. W tej chwili tekst jest taki sam jak nazwa przycisku, ale tak nie musi być. Zmieńmy to, aby tekst na przycisku powiedział: "Jestem przyciskiem!". W Edytorze właściwości przewiń w dół, aż znajdziesz właściwość o nazwie tekst. Zmień tekst na Jestem przyciskiem!. Możesz również zmienić tekst przycisku, klikając dwukrotnie przycisk i edytując tekst bezpośrednio na przycisku. Jeśli spojrzysz na przycisk na formularzu, teraz zmienił się on na "Jestem przyciskiem!". Ale nazwa widgetu (właściwość objectName) nadal jest przyciskiem PushButton. W ten sposób odnosisz się do tego w kodzie, jeśli chcesz coś zrobić za pomocą przycisku.
Zapisywanie GUI
Zapiszmy to, co mamy do tej pory. W PyQt opis GUI jest zapisywany w pliku .ui. Ten plik zawiera wszystkie informacje o oknie, menu i widżetach. Jest to ta sama informacja, która została wyświetlona w oknach właściwości po prawej stronie Qt Designer, a teraz musisz zapisać ją w pliku, aby program PyQt mógł być używany podczas jego działania. Aby zapisać interfejs użytkownika, przejdź do menu Plik i wybierz Zapisz jako i nadaj plikowi nazwę. Nazwijmy nasze GUI MyFirstGui. Zauważysz, że rozszerzenie pliku jest automatycznie ustawiane na .ui. Tak więc interfejs użytkownika zostanie zapisany jako MyFirstGui.ui. Upewnij się, że zapisałeś go w wybranym folderze. Domyślnie Designer zapisze go w folderze, w którym znajdują się jego własne pliki, co prawdopodobnie nie jest tym, czego chcesz. Przejdź do folderu, w którym zapisujesz swoje programy Python, zanim klikniesz Zapisz. Możesz przejrzeć ten plik w dowolnym edytorze tekstu, w tym w edytorze IDLE. Jeśli go otworzysz, zobaczysz coś takiego:
< ?xml version="1.0" encoding="UTF-8"? >
< ui version="4.0" >
< class >MainWindow< /class >
< widget class="QMainWindow" name="MainWindow" >
< property name="geometry" >
< rect >
< x >0< /x >
< y >0< /y >
< width >576< /width >
< height >425< /height >
< /rect >
< /property >
< property name="windowTitle" >
< string >MainWindow< /string >
< /property >
< widget class="QWidget" name="centralwidget" >
< widget class="QPushButton" name="pushButton" >
< property name="geometry" >
< rect >
< x >60< /x >
< y >70< /y >
< width >121< /width >
< height >41< /height >
rect >
property >
< property name="toolTip" >
< string / >
< /property >
< property name="text" >
< string >Jestem przyciskiem!< /string >
property >
widget >
widget >
< widget class="QMenuBar" name="menubar" >
< property name="geometry" >
< rect >
< x >0< /x >
< y >0< /y >
< width >576< /width >
< height >21< /height >
rect >
property >
widget >
widget >
< widget class="QStatusBar" name="statusbar" / >
< /widget >
< resources / >
< connections / >
< /ui >
Wygląda to trochę myląco, ale jeśli przyjrzysz się bliżej, zobaczysz część opisującą okno i część opisującą przycisk, a także kilka innych części, o których jeszcze nie rozmawialiśmy, takich jak menu i pasek stanu.
Przekonaj nasze GUI aby coś robiło
Mamy teraz bardzo proste GUI - okno z przyciskiem. Ale to nic nie robi. Nie napisaliśmy żadnego kodu, który informowałby program, co robić, gdy ktoś kliknie przycisk. To tak, jakbyś miał samochód z czterema kołami i nadwoziem, ale bez silnika. Wygląda ładnie, ale nigdzie nie pójdzie. Potrzebujemy trochę kodu, aby uruchomić nasz program. W przypadku programu PyQt minimum, którego potrzebujesz, to coś takiego.
Wymagany wpis 21.1 minimalnego kodu PyQt
import sys
from PyQt4 import QtCore, QtGui, uic <- Importuje potrzebne biblioteki PyQt
form_class = uic.loadUiType("MyFirstGui.ui")[0] <- Ładuje interfejs użytkownika, który utworzyliśmy w programie Designer (1)
class MyWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
app = QtGui.QApplication(sys.argv) <- Obiekt PyQt, który uruchamia pętlę zdarzeń
myWindow = MyWindowClass() <- Tworzy instancję klasy okna
myWindow.show()
app.exec_()
Jeśli zastanawiasz się, czym jest [0] na końcu linii (1), wyjaśnienie znajduje się w nocie.
Wyjątkiem dla [0] na końcu linii ładującej interfejs użytkownika jest to, że metoda uic.loadUiType () zwraca listę zawierającą dwie rzeczy: coś o nazwie form_class i coś o nazwie base_class. Dla naszych celów potrzebujemy tylko pierwszego elementu, klasy form_class, który jest pozycją [0] na liście
Jak można się spodziewać w Pythonie, wszystko w PyQt jest obiektem. Każde okno jest obiektem zdefiniowanym za pomocą słowa kluczowego class. Ten program i wszystkie programy PyQt, które stworzymy, mają klasę dziedziczącą z klasy PyQt QMainWindow. W liście 20.1 nazwaliśmy klasę MyWindowClass (w linii 6), ale mogliśmy użyć dowolnej nazwy. Pamiętaj, że definicja klasy to tylko projekt. Nadal musimy zbudować dom - stwórz instancję klasy - i zrobimy to za pomocą linii myWindow = MyWindowClass () blisko dołu. myWindow jest instancją klasy MyWindowClass. Wpisz to w oknie edytora IDLE lub SPE i zapisz je jako MyFirstGui.py:
• Kod główny - MyFirstGui.py
• Plik interfejsu użytkownika - MyFirstGui.ui
Oba pliki należy zapisać w tej samej lokalizacji, aby program główny mógł znaleźć plik interfejsu użytkownika i załadować go na początku programu.
Możesz teraz uruchomić to z IDLE. Zobaczysz okno otwarte i możesz kliknąć przycisk. Ale nic się jeszcze nie dzieje. Mamy uruchomiony program, ale nadal nie napisaliśmy żadnego kodu dla tego przycisku. Zamknij program, klikając X na pasku tytułu. Zróbmy coś prostego. Po kliknięciu przycisku przejdźmy do nowego miejsca w oknie. Dodaj kod w wierszach od 10 do 17 listing 21.2 do kodu wpisanego w listingu 21.1.
Listing 21.2 Dodawanie modułu obsługi zdarzeń dla przycisku z listy 20.1
import sys
from PyQt4 import QtCore, QtGui, uic
form_class = uic.loadUiType("MyFirstGui.ui")[0]
class MyWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.button_clicked) |<- Łączy moduł obsługi zdarzeń ze zdarzeniem
def button_clicked(self): ,
x = self.pushButton.x()
y = self.pushButton.y()
x += 50
y += 50
self.pushButton.move(x, y) <- Przesuwa przycisk, gdy go klikamy
app = QtGui.QApplication(sys.argv)
myWindow = MyWindowClass()
myWindow.show()
app.exec_()
Upewnij się, że wcięto cały blok def cztery spacje w wyciągu klasowym, jak pokazano na liście. Musisz to zrobić, ponieważ wszystkie składniki znajdują się w oknie lub są jego częścią. Zatem kod obsługi zdarzeń przycisku wchodzi do definicji klasy. Spróbuj uruchomić, aby zobaczyć, co się stanie. Szczegółowo zobaczymy ten kod w następnej sekcji.
Powrót obsługi zdarzeń
W naszych programach Pygame w ostatnich kilku częściach dowiedziałeś się o modułach obsługi zdarzeń i jak ich używać do wyszukiwania aktywności klawiatury i myszy lub zdarzeń. To samo dotyczy PyQt. W MyWindowClass definiujemy obsługę zdarzeń dla okna. Ponieważ przycisk znajduje się w naszym głównym oknie, znajduje się tam moduł obsługi zdarzeń dla przycisku. Najpierw musimy poinformować główne okno, że tworzymy program obsługi zdarzeń dla konkretnego widgetu. W listingu 20.2 dzieje się to w linii 10:
self.pushButton.clicked.connect (self.button_clicked)
Tutaj łączymy lub łączymy zdarzenie (self.pushButton.clicked) z procedurą obsługi zdarzeń (self.button_clicked). Definicja obsługi zdarzenia button_clicked rozpoczyna się w linii 12. kliknięcie jest tylko jednym ze zdarzeń, które możemy uzyskać dla przycisku. Inne obejmują prasowane i uwalniane.
Myślenie jak programista (Python)
Łączenie zdarzenia przycisku z procedurą obsługi zdarzeń nazywa się wiązaniem modułu obsługi zdarzeń. To tylko programista mówiący o łączeniu rzeczy. W PyQt i wielu innych programach sterowanych zdarzeniami , usłyszysz odniesienia do wiążących rzeczy. Zazwyczaj łączysz zdarzenie lub inny sygnał z kodem, który obsługuje to zdarzenie lub sygnał. Sygnał jest terminem programowania dla sposobu przekazywania informacji z jednej części kodu do drugiej.
Czym jest self?
W procedurze obsługi zdarzenia button_clicked () istnieje jeden parametr: self. Tak jak po raz pierwszy mówiliśmy o obiektach w części 14, self odnosi się do instancji, która wywołuje metodę. W tym przypadku wszystkie zdarzenia pochodzą z tła lub głównego okna, więc jest to obiekt okna, który wywołuje procedurę obsługi zdarzeń. Tutaj self odnosi się do głównego okna. Możesz pomyśleć, że self odnosi się do klikniętego komponentu, ale tak nie jest; odnosi się do okna zawierającego komponent.
Przesuwanie przycisku
Kiedy chcesz coś zrobić z tym przyciskiem, w jaki sposób odnosisz się do niego? PyQt śledzi wszystkie widżety w oknie. Ponieważ wiesz, że self odnosi się do okna, a pushButton to nazwa widgetu, możesz użyć self.pushButton, aby uzyskać dostęp do tego widgetu. W naszym przykładzie na listingu 21.2, przycisk przesuwał się za każdym razem, gdy go klikaliśmy. Pozycja przycisku w oknie zależy od jego właściwości geometrii, która zawiera właściwości x, y, szerokość i wysokość. Istnieją dwa sposoby zmiany tych właściwości. Jednym ze sposobów jest użycie metody o nazwie setGeometry () do zmiany właściwości geometrii. Innym sposobem (którego użyliśmy w listingu 21.2) jest użycie metody move (), która zmienia tylko x i y części geometrii i pozostawia samą szerokość i wysokość. Pozycja x to odległość od lewej strony okna, a pozycja y to odległość od górnej części okna. Lewy górny róg okna to [0, 0] (tak jak w Pygame). Po uruchomieniu tego programu zobaczysz, że po kilku kliknięciach przycisk znika z prawego dolnego rogu okna. Jeśli chcesz, możesz zmienić rozmiar okna (przeciągnij krawędź lub narożnik), aby powiększyć i znaleźć przycisk ponownie. Po zakończeniu możesz zamknąć okno, klikając znak X na pasku tytułu (lub cokolwiek, co jest używane do zamknięcia okna w systemie operacyjnym). Zauważ, że w przeciwieństwie do Pygame, nie musisz się martwić o "wymazanie" przycisku ze starej pozycji i przerysowanie go w nowej pozycji. Po prostu go przenieś. PyQt troszczy się o wszystkie operacje kasowania i przerysowywania.
Bardziej przydatne GUI
Nasze pierwsze GUI PyQt było dobre do przyjrzenia się podstawom tworzenia GUI w PyQt, ale nie jest to przydatne i nie jest zbyt zabawne. W dalszej części tego rozdziału oraz w części 22 będziemy pracować nad kilkoma innymi projektami, jednym małym i jednym większym, które pozwolą nam dowiedzieć się więcej o używaniu PyQt. Pierwszym projektem będzie wersja PyQt naszego programu konwersji temperatury. W dalszej części ponownie użyjemy PyQt do stworzenia programu Virtual Pet.
TempGUI
W Części 3 (w sekcji "Wypróbuj to") wykonałeś swój pierwszy program konwersji temperatury. W Części 5 dodaliśmy do niego dane użytkownika, aby konwertowana temperatura nie musiała być zakodowana na stałe w programie. W rozdziale 6 użyliśmy EasyGui, aby pobrać wejście i wyświetlić wyjście. Teraz użyjemy PyQt do stworzenia graficznej wersji programu do konwersji temperatury
Komponenty TempGUI
Nasze GUI do konwersji temperatury będzie całkiem prosty. Potrzebujemy tylko kilku rzeczy:
• Miejsca do wprowadzania temperatur (Celsjusza lub Fahrenheita)
• Przyciski, aby dokonać konwersji temperatury
• Niektóre etykiety pokazują użytkownikowi, co jest
Dla zabawy, użyjmy dwóch różnych rodzajów widżetów wejściowych dla Celsjusza i Fahrenheita. Nigdy nie zrobiłbyś tego w prawdziwym programie (to tylko dezorientowałoby ludzi), ale jesteśmy tutaj, aby się uczyć! Kiedy skończymy układ graficzny GUI, powinien on wyglądać mniej więcej tak:
Prawdopodobnie możesz to zrobić samodzielnie, ponieważ Qt Designer jest bardzo przyjazny dla użytkownika. Ale na wypadek, gdybyś potrzebował pomocy, wyjaśnię ci kroki. Zapewni to również, że używamy tych samych nazw dla naszych komponentów, co ułatwi późniejsze przestrzeganie kodu.
Nie martw się, że komponenty są dokładnie wyrównane lub dokładnie takie same jak tutaj, o ile są mniej więcej takie same.
Tworzenie nowego GUI
Pierwszym krokiem jest stworzenie nowego projektu PyQt. Po zamknięciu otwartego interfejsu użytkownika (MyFirstGui) projektant otworzy ponownie okno Nowy formularz i możesz upewnić się, że jako typ formularza wybrano Okno główne, a następnie kliknij Utwórz. Teraz musisz zacząć dodawać widżety: pole wprowadzania Celsjusza to widżet Edycja linii, pole wprowadzania Fahrenheita to pole Spin, etykiety pod każdym polem wprowadzania temperatury są widżetami etykiet, a są dwa elementy przycisku. Będziesz musiał przewinąć w polu widżetu po lewej stronie, aby znaleźć niektóre z nich. Oto kroki, aby utworzyć GUI:
1 Znajdź widżet Przycisk Push w polu Widget. Przeciągnij go na formularz i zrobi nowy przycisk w formularzu. Następnie wykonaj następujące czynności:
• Uczyń przycisk odpowiednim rozmiarem, przeciągając uchwyty lub wprowadzając nowe liczby we właściwościach geometrii (jak w MyFirstGui).
• Zmień właściwość objectName przycisku na btnFtoC.
• Zmień właściwość tekstu przycisku na <<< Fahrenheit na Celsjusza.
• Zmień rozmiar czcionki przycisku na 12. Jeśli znajdziesz właściwość czcionki w Edytorze właściwości i kliknij mały przycisk z trzema kropkami, który wygląda tak:
Pojawi się okno dialogowe Czcionka, podobnie jak to, które prawdopodobnie widziałeś w ulubionym edytorze tekstu.
2 Przeciągnij inny przycisk Push na formularz, umieść go nad pierwszym przyciskiem, ustaw go na żądany rozmiar i zmień te ustawienia:
• Zmień właściwość objectName przycisku na btnCtoF.
• Zmień właściwość tekstu przycisku na Celsjusza na Fahrenheita >>>.
• Zmień rozmiar czcionki przycisku na 12.
3 Przeciągnij widżet Edycja linii na formularz i umieść go po lewej stronie dwóch przycisków:
• Zmień właściwość objectName widżetu Edycja linii na editCel.
4 Przeciągnij widget Spin Box na formularz i umieść go po prawej stronie dwóch przycisków:
• Zmień nazwę obiektu Spin Box na spinFahr.
5 Przeciągnij widget Etykieta na formularz i umieść go pod widżetem Edycja linii:
• Zmień właściwość tekstu etykiety na Celsjusza.
• Zmień rozmiar czcionki etykiety na 10.
6 Przeciągnij widget Etykieta na formularz i umieść go pod widżetem Spin Box:
• Zmień właściwość tekstu etykiety na Fahrenheita.
• Zmień rozmiar czcionki etykiety na 10.
Teraz umieściliśmy elementy GUI (widżety lub komponenty lub elementy sterujące) i nadaliśmy im nazwy i etykiety, które chcemy. Zapisz plik interfejsu użytkownika jako tempconv.ui, wybierając Plik> Zapisz jako w Qt Designer. Pamiętaj, aby zmienić lokalizację, w której plik jest zapisany, w miejscu, w którym normalnie zapisujesz programy Pythona. Następnie uruchom nowy plik w IDLE i wpisz podstawowy kod PyQt (lub skopiuj go z naszego pierwszego programu):
import sys
z PyQt4 import QtCore, QtGui, uic
form_class = uic.loadUiType ("tempconv.ui") [0]
class MyWindowClass (QtGui.QMainWindow, form_class):
def __init __ (self, parent = None):
QtGui.QMainWindow .__ init __ (self, parent)
self.setupUi (self)
app = QtGui.QApplication (sys.argv)
myWindow = MyWindowClass ()
myWindow.show ()
app.exec_ ()
Konwersja Celsjusza na Fahrenheita
Po pierwsze, uruchommy funkcję Celsjusza na Fahrenheita. Wzór na przeliczenie Celsjusza na Fahrenheita to
fahr = cel * 9,0 / 5 + 32
Musimy uzyskać temperaturę Celsjusza z widżetu Edycja linii edycyjnej, wykonaj obliczenia i umieść wynik w widgecie Spin Fahrenheit Spin Box. To wszystko powinno się zdarzyć, gdy użytkownik kliknie przycisk Celsjusza na Fahrenheita, więc kod, który ma zrobić, powinien znaleźć się w module obsługi zdarzeń tego przycisku. Najpierw musimy połączyć zdarzenie kliknięcia przycisku z programem obsługi zdarzeń:
self.btn_CtoF.clicked.connect (self.btn_CtoF_clicked)
Ten kod idzie w metodzie __init __ () klasy MyWindow, tak jak w naszym pierwszym programie. Następnie musimy zdefiniować procedurę obsługi zdarzeń. Aby uzyskać wartość z pola Celsjusza (widżet Edycja linii o nazwie editCel), używamy self.editCel.text (). Ta wartość jest ciągiem, więc musimy przekonwertować go na zmiennoprzecinkowy:
cel = float (self.editCel.text ())
Następnie musimy dokonać konwersji
fahr = cel * 9,0 / 5 + 32
Następnie musimy umieścić tę wartość w polu Fahrenheit, którym jest widget Spin Box o nazwie spinFahr. Jest tu jeden haczyk: pola spinowe mogą mieć tylko wartości całkowite, a nie pływające. Musimy upewnić się, że przekonwertowaliśmy wartość na int przed umieszczeniem jej w polu spinowym. Liczba w polu spinowym jest jego wartością wartości, więc kod wygląda tak:
self.spinFahr.setValue (int (fahr))
I dodajemy 0.5 do wyniku, tak że gdy użyjemy int () do konwersji liczby float na liczbę całkowitą, zostanie ona zaokrąglona do najbliższej liczby całkowitej, zamiast zaokrąglania w dół do następnej najniższej liczby całkowitej. Łącząc to wszystko daje nam to:
def btn_CtoF_clicked(self):
cel = float(self.editCel.text()) <- Pobiera wartość Celsjusza
fahr = cel * 9.0 / 5 + 32 <- Konwertuje na Fahrenheita
self.spinFahr.setValue(int(fahr + 0.5)) <- Zaokrągla i umieszcza pole Fahrenheita
app = QtGui.QApplication(sys.argv)
myWindow = MyWindowClass()
myWindow.show()
app.exec_()
Konwersja Fahrenheita na Celsjusza
Kod do konwersji w inny sposób (z Fahrenheita na Celsjusza) jest bardzo podobny. Formuła tej konwersji to
cel = (fahr - 32) * 5.0 / 9
Przechodzi w module obsługi zdarzeń z przycisku Fahrenheita do Celsjusza. Łączymy moduł obsługi zdarzeń z przyciskiem (w metodzie okna __init __ ()}:
self.btn_FtoC.clicked.connect (self.btn_FtoC_clicked)
Następnie w module obsługi zdarzeń musimy uzyskać temperaturę Fahrenheita z pola wirowania:
fahr = self.spinFahr.value ()
Ta wartość jest już liczbą całkowitą, więc nie musimy wykonywać żadnej konwersji typu. Następnie stosujemy formułę:
cel = (fahr - 32) * 5.0 / 9
Na koniec konwertujemy to na ciąg znaków i umieszczamy w polu Celsjusza:
self.editCel.setText (str (cel))
Cała rzecz powinna wyglądać następująco.
Listing 21.3 Program do konwersji temperatury
import sys
from PyQt4 import QtCore, QtGui, uic
form_class = uic.loadUiType("tempconv.ui")[0] <- Ładuje definicję interfejsu użytkownika
class MyWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.btn_CtoF.clicked.connect(self.btn_CtoF_clicked)
self.btn_FtoC.clicked.connect(self.btn_FtoC_clicked)
def btn_CtoF_clicked(self):
cel = float(self.editCel.text())
fahr = cel * 9 / 5.0 + 32
self.spinFahr.setValue(int(fahr + 0.5))
def btn_FtoC_clicked(self):
fahr = self.spinFahr.value()
cel = (fahr - 32) * 5 / 9.0
self.editCel.setText(str(cel))
app = QtGui.QApplication(sys.argv)
myWindow = MyWindowClass(None)
myWindow.show()
app.exec_()
Zapisz ten program jako TempGui.py. Możesz go uruchomić i wypróbować GUI.
Mała poprawa
Jedna rzecz, którą zauważysz po uruchomieniu programu, polega na tym, że kiedy konwertujesz temperaturę Fahrenheita na Celsjusza, odpowiedź ma dużo miejsc po przecinku, a niektóre z nich mogą zostać odcięte w polu tekstowym. Istnieje sposób na to - nazywa się to formatowaniem wydruku. Nie omówiliśmy tego jeszcze, więc możesz przejść do części 21, aby uzyskać pełne wyjaśnienie, jak to działa, lub po prostu wpisz kod, który Ci tutaj podam. Zamień ostatni wiersz procedury obsługi zdarzeń btn_FtoC_clicked na te dwie linie:
cel_text = '% .2f'% cel
self.editCel.setText (cel_text)
Spowoduje to wyświetlenie liczby z dwoma miejscami po przecinku. Hmmm
Może czas na debugowanie. Co jeśli nasi użytkownicy chcą konwertować temperatury na Antarktydzie? Albo na Plutonie
Zgniatanie błędu
Powiedzieliśmy wcześniej, że dobrym sposobem na sprawdzenie, co dzieje się w programie, jest wyświetlanie wartości niektórych zmiennych podczas działania programu. Spróbujmy tego. Ponieważ jest to wartość Fahrenheita w konwersji Celsjusza na Fahrenheita, która wydaje się nie działać, zaczniemy od tego. Dodaj ten wiersz po ostatnim wierszu modułu obsługi zdarzeń btn_CtoF_clicked w listingu 21.3:
print 'cel =', cel, 'fahr =', fahr
Teraz, gdy klikniesz przycisk Celsjusza na Fahrenheita, możesz zobaczyć zmienne cel i fahr wydrukowane w oknie powłoki IDLE. Wypróbuj go z kilkoma różnymi wartościami cel i zobacz, co się stanie. Mam coś takiego:
>>> ============================ RESTART ==================
>>>
cel = 50,0 fahr = 122,0
cel = 0,0 fahr = 32,0
cel = -10,0 fahr = 14,0
cel = -50,0 fahr = -58,0
Wygląda na to, że wartość fahr jest obliczana poprawnie. Dlaczego więc pole Fahrenheita nie wyświetla niczego poniżej 0 (lub więcej niż 99, w tym przypadku!)? Wróć do Qt Designer i kliknij widżet spinFahr, który użyliśmy do pokazywania i wprowadzania temperatury Fahrenheita. Teraz spójrz na Edytor właściwości i przewiń różne właściwości. Czy widzisz dwie właściwości zwane minimalną i maksymalną (w dolnej części listy właściwości pola wirowania)? Jakie są ich wartości? Czy wiesz, jaki jest problem?
Co jest w menu?
Nasz interfejs GUI do konwersji temperatury ma przyciski, które umożliwiają dokonywanie konwersji. Wiele programów ma również menu do wykonywania niektórych funkcji. Czasami są to te same rzeczy, które możesz zrobić, klikając przycisk, więc dlaczego chcesz mieć dwa różne sposoby na zrobienie tego samego? Niektórzy użytkownicy czują się bardziej komfortowo, używając menu niż klikając przyciski. Skomplikowane programy mają wiele funkcji, które wymagałyby wielu przycisków, tworząc bardzo zaśmiecone GUI, gdyby nie korzystały z menu. Możesz także obsługiwać menu za pomocą klawiatury, a niektórzy ludzie szybciej korzystają z menu niż zdejmują ręce z klawiatury i używają myszy. Dodajmy kilka elementów menu, aby dać naszym użytkownikom inny sposób na dokonanie konwersji temperatury. Możemy również dodać opcję menu Plik > Wyjdź, która ma prawie każdy program. PyQt zawiera sposób tworzenia i edycji menu. Jeśli spojrzysz w lewym górnym rogu formularza w Projektancie, zobaczysz coś, co mówi Wpisz tutaj. Tutaj zaczynamy tworzyć menu. W wielu programach pierwsze menu to menu Plik, więc zacznijmy od tego. Kliknij obszar, w którym napisano Wpisz tutaj, wpisz Plik, a następnie naciśnij klawisz Enter. Powinieneś zobaczyć menu Plik, a także miejsce na wpisanie kolejnych pozycji menu obok i poniżej, jak poniżej:
Dodawanie pozycji menuM
W menu Plik dodamy element menu Zakończ. Gdzie mówi Typ Wpisz poniżej menu Plik wpisz Wyjdź, a następnie naciśnij klawisz Enter.
Dodajmy teraz element menu do konwersji temperatur (jeśli użytkownik nie chce używać przycisków). W miejscu, w którym napisano Wpisz Tutaj po prawej stronie menu Plik wpisz Konwertuj. Następnie poniżej umieść dwa nowe elementy menu od C do F i od F do C. Gdy skończysz, powinno to wyglądać następująco:
Jeśli spojrzysz na Inspektora obiektów w górnym rogu okna Qt Designer, powinieneś zobaczyć coś takiego:
Możesz zobaczyć menu Plik i Konwertuj oraz elementy menu Wyjście, C do F i F do C. W terminologii PyQt pozycje menu są instancjami klasy QAction. To ma sens, ponieważ chcesz, aby niektóre działania miały miejsce po wybraniu elementu menu. Zapisz zmodyfikowany plik projektanta jako tempconv_menu.ui. Teraz, gdy masz elementy menu (lub akcje), musisz powiązać (lub połączyć) swoje zdarzenia z modułami obsługi zdarzeń. Dla elementów menu od C do F i od F do C mamy już moduły obsługi zdarzeń - te, które zrobiliśmy dla przycisków. Chcemy, aby to samo stało się z menu, jak po kliknięciu przycisków. Możemy więc po prostu połączyć elementy menu z tymi samymi modułami obsługi zdarzeń. W przypadku elementu menu (akcji) nie jest to kliknięte wydarzenie, z którym musimy się uporać, to zdarzenie wywołane. To, z czym łączymy się z programem obsługi zdarzeń, to tzw. Action_CtoF. A obsługa zdarzeń, z którą się łączymy, to obsługa zdarzeń przycisku, btn_CtoF_clicked. Kod do połączenia modułu obsługi zdarzeń dla elementu menu wygląda następująco:
self.action_CtoF.triggered.connect (self.btn_CtoF_clicked)
I jest jeszcze jeden element menu FtoC. W przypadku elementu menu Exit musimy utworzyć nową procedurę obsługi zdarzeń i powiązać ją ze zdarzeniem.
Wywołamy tę funkcję obsługi zdarzeń menuExit_selected i kod do połączenia tej obsługi zdarzeń wygląda tak:
self.actionExit.triggered.connect (self.menuExit_selected)
Rzeczywista obsługa zdarzeń dla menu Wyjście ma tylko jedną linię w ciele, która zamyka okno:
def menuExit_selected (self):
self.close (
Na koniec zmień ładowany plik UI (w trzeciej linii) na plik z zapisanymi menu, tempconv_menu.ui. Dokonując wszystkich tych zmian, kod powinien wyglądać następująco.
Listing 21.4 Pełny program konwersji temperatury z menu
import sys
from PyQt4 import QtCore, QtGui, uic
form_class = uic.loadUiType("tempconv_menu.ui")[0] <- Ładuje plik interfejsu użytkownika zawierający menu
class MyWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.btn_CtoF.clicked.connect(self.btn_CtoF_clicked)
self.btn_FtoC.clicked.connect(self.btn_FtoC_clicked)
self.action_CtoF.triggered.connect(self.btn_CtoF_clicked)
self.action_FtoC.triggered.connect(self.btn_FtoC_clicked)
self.actionExit.triggered.connect(self.menuExit_selected) <-Łączy obsługę zdarzeń menu Exit
def btn_CtoF_clicked(self):
cel = float(self.editCel.text())
fahr = cel * 9 / 5.0 + 32
self.spinFahr.setValue(int(fahr + 0.5))
def btn_FtoC_clicked(self):
fahr = self.spinFahr.value()
cel = (fahr - 32) * 5 / 9.0
self.editCel.setText(str(cel))
def menuExit_selected(self):
self.close()
app = QtGui.QApplication(sys.argv)
myWindow = MyWindowClass(None)
myWindow.show()
app.exec_()
Skróty klawiszowe
Powiedzieliśmy wcześniej, że jednym z powodów, dla których niektórzy ludzie wolą używać menu do używania przycisków, jest to, że mogą korzystać z menu za pomocą klawiatury, bez konieczności używania myszy. W tej chwili nasze menu działają z myszą, ale jeszcze nie sprawiliśmy, by działały z klawiaturą. Sposób, w jaki to robimy, polega na dodawaniu skrótów klawiszowych. Skróty klawiaturowe (zwane także klawiszami skrótów) umożliwiają wybieranie elementów menu przy użyciu tylko klawiatury. W systemach Windows i Linux aktywujesz system menu za pomocą klawisza Alt. (Porozmawiamy o tym w Mac OS za minutę.) Po naciśnięciu klawisza Alt zobaczysz pewną literę każdego podświetlonego elementu menu, zwykle z podkreśleniem. Podkreślona litera to ta, której używasz do aktywacji tego menu. Na przykład, aby przejść do menu Plik, naciśnij Alt-F. Oznacza to, że przytrzymujesz klawisz Alt, a następnie klawisz F. Gdy już to zrobisz, zobaczysz elementy w menu Plik i zobaczysz, jakie skróty klawiszowe są dla każdego elementu menu. Spróbuj tego w oknie powłoki IDLE:
Aby otworzyć nowe okno, użyj Alt-F-N. (Przytrzymaj Alt, naciśnij F, a następnie naciśnij N.). Teraz będziemy definiować klawisze skrótów w menu GUI konwersji temperatury. Aby zdefiniować skrót klawiszowy, wszystko, co musisz zrobić, to umieścić znak & przed literą, która ma być skrótem klawiszowym. Robisz to w właściwości Tytuł dla menu (jak Plik) lub we właściwości Tekst dla elementu menu (np. Wyjście). W menu Plik konwencja polega na skróceniu klawisza F; i dla Exit, ustaw X jako klawisz skrótu. Zatem Plik staje się i Plikem, a Wyjście staje się E i xit. Musimy zdecydować, które klawisze skrótu mają być używane w elementach menu Konwertuj. Użyjmy C dla Convert, C dla Celsjusza do Fahrenheita i F dla Fahrenheita do Celsjusza. Mamy więc & Konwertuj, & C na F i & F na C. Kombinacje klawiszy skrótu to Alt-C-C (dla Celsjusza do Fahrenheita) i Alt-C-F (dla Fahrenheita do Celsjusza). Po zdefiniowaniu skrótów klawiaturowych w Qt Designer nie ma nic innego do roboty - nie ma nowego kodu do pisaina. PyQt i system operacyjny dbają o podkreślenie klawisza skrótu i obsługę wejścia klawiatury. Po prostu zapisz plik UI. Możesz zapisać go pod inną nazwą, np. Tempconv_menu_hotkeys.ui. Jeśli to zrobisz, upewnij się, że zmieniłeś trzeci wiersz listingu 20.4, aby załadować ten plik interfejsu użytkownika:
form_class = uic.loadUiType ("tempconv_menu_hotkeys.ui") [0]
Krótka odpowiedź brzmi "nie". Ponieważ wszystkie komputery Mac są dostarczane z myszą (lub panelem dotykowym) od pierwszego dnia, system Mac OS zakłada, że użyjesz myszy do obsługi menu. Nie ma skrótu klawiaturowego ani systemu skrótów klawiszowych dla pozycji menu w systemie Mac OS. Istnieją skróty klawiaturowe dla wielu funkcji, a niektóre z nich odpowiadają elementom menu. Ale nie możesz bezpośrednio obsługiwać systemu menu za pomocą skrótów klawiszowych, tak jak ty może w systemie Windows. To jest dla GUI konwersji temperatury. W rozdziale 22 użyjemy PyQt do stworzenia wersji gry Wisielec.
Czego się nauczyłeś?
• PyQt
• Qt Designer
• Widżety - przyciski, tekst i tak dalej, które tworzą GUI
• Obsługa zdarzeń - dzięki czemu komponenty coś robią
• Elementy menu i klawisze skrótów
Sprawdź swoją wiedzę
1 Jakie są trzy nazwy rzeczy, takich jak przyciski, pola tekstowe itd., Które tworzą GUI?
2 Jaki jest termin litery, którą naciskasz razem z ALT, aby dostać się do menu?
3 Co należy umieścić na końcu nazwy pliku dla plików Qt Designer?
4 Jakie są pięć typów widżetów, które możesz dołączyć do GUI za pomocą PyQt?
5 Aby widget (jak przycisk) zrobił coś, musi mieć _____________ ________________.
6 Jaki znak specjalny jest używany w menu do definiowania skrótu?
7 Zawartość pola spinowego w PyQt jest zawsze __________.
Wypróbuj to
1 Zrobiłeś tekstowy program do odgadywania numerów w rozdziale 1, i stworzyłeś prostą wersję GUI tej samej gry w rozdziale 6. Spróbuj stworzyć wersję GUI gry zgadującej numer używając PyQt.
2 Czy znalazłeś problem ze skrzynką spinową, gdy nie wyświetlałoby żadnych wartości poniżej 0? (Carter znalazł ten błąd w liście 20.2.) Napraw właściwości pola spinowego, aby rozwiązać ten problem. Upewnij się, że zamocowałeś oba końce skali, aby błystka mogła wyświetlać bardzo wysokie temperatury, a także bardzo niskie. (Może twój użytkownik zamieni temperatury na Merkurym i Wenus, a także na Plutona!)
Waaaayyyy w Części 1 dowiedziałeś się o instrukcji print. To było pierwsze polecenie, które kiedykolwiek użyłeś w Pythonie. Widziałeś również (w części 5), że możesz umieścić przecinek na końcu instrukcji print, aby Python kontynuował drukowanie następnej rzeczy w tej samej linii. (Przynajmniej w Pythonie 2. Nie w Pythonie 3). Użyłeś tego do monitowania o raw_input (), dopóki nie nauczyłeś się skrótu do wprowadzenia znaku zachęty w funkcji raw_input (). W tej części przyjrzymy się formatowaniu wydruku - sposobom, aby wygląd programu wyglądał tak, jak tego chcesz. Przyjrzymy się takim rzeczom:
• Uruchamianie nowych linii (i kiedy powinieneś to robić)
• Wycinanie elementów w poziomie (i układanie elementów w kolumnach)
• Drukowanie zmiennych w środku łańcucha
• Formatowanie liczb w formacie całkowitoliczbowym, dziesiętnym lub E-notacji oraz ustawianie liczby miejsc dziesiętnych, które powinny mieć. Dowiesz się również o niektórych wbudowanych w Python metodach pracy z ciągami znaków.
Te metody mogą robić takie rzeczy jak
• Dzielenie ciągów na mniejsze części
• Łącząc ze sobą struny
• Wyszukiwanie ciągów znaków
• Wyszukiwanie w łańcuchach
• Usuwanie części strun
• Zmiana przypadku (wielkie i małe litery)
Wszystkie te rzeczy będą przydatne w programach w trybie tekstowym (nie GUI), a większość z nich znajdzie się również w GUI i programach do gier. Istnieje więcej Pythona, który może zrobić z formatowaniem wydruku, ale to wszystko, czego potrzebujesz do 99 procent twoich programów.
Nowe linie
Wielokrotnie widziałeś już instrukcję drukowania. Co się stanie, jeśli użyjesz go więcej niż raz? Wypróbuj ten krótki program:
print "Hi"
print "There"
Po uruchomieniu wynik powinien wyglądać następująco:
>>> =================== RESTART ===================
>>>
Hi
There
Dlaczego te dwie rzeczy drukowane były na różnych liniach? Dlaczego dane wyjściowe nie wyglądały tak:
HiThere
Jeśli nie powiesz inaczej, Python rozpocznie każdy wydruk na nowej linii. Po Hi, Python przesuwa się w dół o jedną linię i wraca do pierwszej kolumny, aby ją wydrukować. Python wstawia znak nowej linii między dwoma słowami. Nowa linia przypomina naciśnięcie klawisza Enter w edytorze tekstu.
Myśląc jak programista
Pamiętasz z powrotem z Części 5, że dowiedziałeś się o CR i LF (powrót karetki i posuw linii) do oznaczania końca linii tekstu? I pamiętaj, jak powiedziałem, że niektóre systemy używają jednego lub drugiego lub obu? Nowa linia to ogólna nazwa znacznika końca linii w dowolnym systemie. W systemie Windows nowa linia = CR + LF. W Linuksie, nowej linii = LF iw Mac OS X, nowa linia = CR. W ten sposób nie musisz się martwić o to, co system, na którym jesteś. Po prostu umieść nową linię w dowolnym miejscu, gdzie chcesz rozpocząć nową linię.
Wyświetlanie i przecinek
Instrukcja print automatycznie umieszcza nową linię na końcu tego, co drukuje, chyba że jej nie powiesz. A jak tego nie chcesz? Dodając przecinek
print 'Hi',
print 'There'
>>> =================== RESTART ===================
>>>
Hi There
(Ponownie, to nie zadziała w Pythonie 3). Zauważ, że między Hi a There jest spacja. Gdy używasz przecinka, aby uniemożliwić Pythonowi drukowanie nowej linii, zamiast tego drukuje spację. Jeśli chcesz wydrukować dwie rzeczy razem bez spacji, możesz użyć konkatenacji, które widziałeś wcześniej:
print 'Hi' + 'There'
>>> =================== RESTART ===================
>>>
HiThere
Pamiętaj, że konkatenacja przypomina dodawanie ciągów, ale ma specjalną nazwę, ponieważ "dodawanie" dotyczy tylko liczb.
Dodawanie naszych nowych linii
Co jeśli chcesz dodać własne znaki nowej linii? Na przykład, jeśli chcesz uzyskać dodatkowy rząd miejsca między Hi a There? Najprostszym sposobem jest dodanie dodatkowej instrukcji wyświetlania:
print "Hi"
print
print "There"
When you run it, you′ll get this:
>>> =================== RESTART ===================
>>>
Hi
There
Specjalne kody drukowania
Istnieje inny sposób dodawania znaków nowej linii. Python ma specjalne kody, które możesz dodawać do ciągów, aby drukować je w inny sposób. Te specjalne kody drukowania zaczynają się od znaku () Kod nowej linii to n. Wypróbuj to w trybie interaktywnym:
>>> print "Hello World"
Hello World
>>> print "Hello \nWorld"
Hello
World
\n sprawiło, że dwa słowa "Hello" i "World" drukowane są na różnych liniach, ponieważ między nimi dodano nową linię.
Odstępy poziome - tabulatory
Właśnie widziałeś, jak kontrolować odstępy w pionie (dodając znaki nowej linii lub używając przecinków, aby zapobiec wyświetlaniu znaków nowej linii). Teraz przyjrzymy się, jak kontrolować odstępy między obiektami na ekranie, poziomo, za pomocą zakładek. Karty są przydatne do układania elementów w kolumnach. Aby zrozumieć, w jaki sposób działają tabulatory, pomyśl, że każda linia na ekranie jest podzielona na bloki, a każdy blok ma ten sam rozmiar. Powiedzmy, że każdy blok ma osiem znaków szerokości. Po włożeniu karty przechodzisz na początek następnego blok. Najlepszym sposobem sprawdzenia, jak to działa, jest wypróbowanie. Specjalny kod dla karty to, więc spróbuj tego w trybie interaktywnym:
>>> print 'ABC\tXYZ'
ABC XYZ
Zauważ, że XYZ jest kilka znaków od ABC. W rzeczywistości XYZ to dokładnie osiem znaków od początku linii. To dlatego, że rozmiar bloku wynosi osiem. Innym sposobem, aby to powiedzieć, jest zatrzymanie tabulacji co osiem znaków. Oto przykład niektórych różnych instrukcji drukowania, z pewnymi cieniami dodanymi, aby pokazać, gdzie są tabulatory:
Możesz myśleć o ekranie (lub każdej linii) jako ułożonym w blokach po osiem spacji. Zauważ, że ponieważ sekwencja ABC wydłuża się, XYZ pozostaje w tym samym miejscu. Polecenie \t mówi Pythonowi aby uruchamił XYZ na następnym tabulatorze lub w następnym dostępnym bloku. Ale gdy sekwencja ABC staje się wystarczająco duża, aby wypełnić pierwszy blok, Python przesuwa XYZ do następnego tabulatora. Karty są przydatne do układania elementów w kolumnach, aby wszystko się układało. Użyjmy tego, a także tego, co wiemy o pętlach, aby wydrukować tabelę kwadratów i kostek. Otwórz nowe okno w IDLE i wpisz krótki program z następującej listy. Zapisz go i uruchom. (Nazwałem mój squbes.py, skrót od "kwadraty i kostki")
Listing 22.1 Program do drukowania kwadratów i kostek
print "Liczba\tKwadrat \tSześcian"
for i in range (1, 11):
print i, '\t', i**2, '\t', i**3
Kiedy go uruchomisz, powinieneś zobaczyć ładnie uporządkowane dane wyjściowe, takie jak poniżej:
>>> ====================== RESTART ======================
>>>
Liczba Kwadrat Sześcian
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
Jak wydrukować odwrotny ukośnik?
Ponieważ znak ukośnika odwrotnego () jest używany do specjalnych kodów drukowania, w jaki sposób powiesz Pythonowi, kiedy chcesz wydrukować znak \ zamiast używać go jako części kodu? Sztuka polega na tym, żeby połączyć dwa z nich:
>>> wydrukuj 'hi \\ there'
hi\there
Pierwszy \ mówi Pythonowi, że nadchodzi coś specjalnego, a drugi mówi Pythonowi, co jest wyjątkowe: znak \.
Kiedy używasz dwóch odwrotnych ukośników do wydrukowania znaku ukośnika odwrotnego, pierwszy ukośnik odwrotny nazywany jest znakiem ucieczki. Mówimy, że pierwszy ukośnik odwraca drugi, tak że drugi ukośnik odwrotny jest traktowany jak normalny znak, a nie jako znak specjalny.
Wstawianie zmiennych do łańcuchów
Do tej pory, kiedy chciałeś umieścić zmienną w środku ciągu, zrobiłeś coś takiego:
name = 'Jan Sandek'
print 'Moje imię to', name, 'i piszę ten tekst.'
Gdybyśmy uruchomili ten kod, otrzymalibyśmy to:
Moje imię to Jan Sandek i piszę ten tekst
Ale istnieje inny sposób wstawiania zmiennych do łańcuchów, co daje większą kontrolę nad tym, jak będą wyglądać, zwłaszcza liczby. Możesz użyć ciągów formatujących, które używają znaku procentu (%). Powiedzmy, że chcesz wstawić zmienną łańcuchową w środku instrukcji drukowania, tak jak to zrobiliśmy. Sposób, w jaki można to zrobić za pomocą łańcuchów formatowania, wygląda następująco:
name = 'Jan Sandek'
print 'Mam na imię% s i napisałem% ten tekst
Znak% jest używany w dwóch miejscach. Jest używany w środku napisu, aby powiedzieć, gdzie pójdzie zmienna. Następnie jest ponownie używane po łańcuchu, aby powiedzieć Pythonowi, że zmienna, którą chcesz wstawić w ciągu, będzie następna. % S oznacza, że jest to zmienna łańcuchowa, którą chcesz wstawić. Dla liczby całkowitej użyjesz% i; dla pływaka użyłbyś% f. Oto kilka przykładów:
age = 13
print 'Mam %lat.' % age
Po uruchomieniu otrzymasz następujące informacje:
Mam13 lat.
Oto kolejny przykład:
średnia = 75,6
print "Średnia na naszym teście matematycznym wynosiła% f procent." % średniej
Po uruchomieniu otrzymasz następujące informacje:
Średnia na naszym teście matematycznym wyniosła 75.600000 procent.
Nazwy %s,%f i %i nazywane są fomatami łańcuchów i są rodzajem kodu określającego wygląd zmiennej. Istnieje kilka innych rzeczy, które możesz dodać do ciągów formatowania, aby liczby były drukowane dokładnie tak, jak chcesz. Istnieje również kilka różnych ciągów formatów, których można użyć do uzyskania takich rzeczy jak notacja elektroniczna. Przyjrzymy się tym w następnych kilku sekcjach.
Formatowanie liczb
Kiedy wyświetlamy liczby, chcielibyśmy mieć kontrolę nad tym, jak wyglądają:
• Ile miejsc dziesiętnych wyświetlają
• Czy używać zwykłej lub e-notacji
• Czy dodać zera wiodące czy końcowe
• Czy wyświetlać znaki + lub - przed liczbami
Dzięki łańcuchom formatowania Python daje nam elastyczność, której potrzebujemy, aby zrobić to wszystko i wiele więcej! Na przykład, jeśli korzystasz z programu, który poinformował Cię o prognozie pogody, co wolisz zobaczyć:
Dzisiejszy Wysoki: 72,45672132, Niski 45,4985756
lub
Dzisiejszy Wysoki: 72, Niski: 45
Uzyskanie prawidłowych liczb jest ważne dla wielu programów.
Zacznijmy od przykładu. Załóżmy, że chcemy wydrukować liczbę dziesiętną z dokładnością do dwóch miejsc po przecinku. Wypróbuj to w trybie interaktywnym:
>>> dec_number = 12.3456
>>> print 'Jest %.2f stopni dzisiaj.' % dec_number
Jest 12.35 stopni dzisiaj
W środku instrukcji drukowania znajduje się nasz ciąg formatowania. Ale zamiast używać tylko %f, tym razem użyliśmy %2f. To mówi Pythonowi, aby pokazywał dwie cyfry po miejscu dziesiętnym, z formatem zmiennoprzecinkowym. (Zwróć uwagę, że Python był na tyle sprytny, by poprawnie zaokrąglić liczbę do dwóch miejsc po przecinku, zamiast po prostu odciąć dodatkowe cyfry).
Po łańcuchu drugi znak % mówi Pythonowi, że następny numer ma zostać wydrukowany. Numer jest drukowany z formatowaniem opisanym w ciągu formatowania. Jeszcze kilka przykładów uczyni to jaśniejszym
Liczby całkowite: %d lub %i
Aby wydrukować coś jako liczbę całkowitą, użyj ciągu formatującego% d lub% i (nie wiem, dlaczego są dwa, ale możesz użyć jednego z nich):
>>> liczba = 12.67
>>> print '%i' % liczba
12
Zauważ, że tym razem liczba nie została zaokrąglona. Została obcięta (co oznacza "odcięte"). Gdyby było zaokrąglone, zobaczylibyśmy 13 zamiast 12. Gdy używasz formatowania liczb całkowitych, liczba jest obcinana, a gdy używasz formatowania zmiennoprzecinkowego, liczba jest zaokrąglana. Należy zwrócić uwagę na trzy rzeczy:
Nie musisz mieć żadnego innego tekstu w łańcuchu - możesz mieć łańcuch formatu sam.
Mimo że nasza liczba był zmiennoprzecinkowa, wyświetliliśmy ją jako liczbę całkowitą. Możesz to zrobić za pomocą łańcuchów formatowania.
Python skrócił wartość do następnej najniższej liczby całkowitej. Ale różni się to od funkcji int () (którą widziałeś w rozdziale 4), ponieważ łańcuchy formatowania nie tworzą nowej wartości, takiej jak int (), ale zmieniają tylko sposób wyświetlania wartości. Właśnie teraz wydrukowaliśmy 12.67 w formacie całkowitym, a Python wydrukowano 12. Jednak wartość numeru zmiennej nie została zmieniona. Sprawdź to i zobacz:
>>> print liczba
12.67
Wartość liczby się nie zmieniła. Właśnie sprawiliśmy, że drukuje się inaczej, używając ciągu formatującego.
Liczby zmiennoprzecinkowe: %f lub %F
W przypadku liczb dziesiętnych można użyć wielkiej lub małej litery f w ciągu formatowania (%f lub %F):
>>> number = 12.3456
>>> print '%f' % number
12.345600
Jeśli użyjesz samo %f , liczba wyświetli się z sześcioma miejscami po przecinku. Jeśli dodasz .n przed f, gdzie n jest dowolną liczbą całkowitą, zaokrąglisz liczbę do tego miejsca po przecinku:
>>> print '%.2F' % number
12.35
Możesz zobaczyć, jak zaokrąglono liczbę 12.3456 do dwóch miejsc po przecinku: 12.35. Jeśli określisz więcej miejsc po przecinku niż w liczbie, Python wstawi (wypełni) liczbę zerami:
>>> print '%.8f' % number
12.34560000
Tutaj liczba miała tylko cztery miejsca po przecinku, ale poprosiliśmy o osiem, więc pozostałe cztery wypełniono zerami. Jeśli liczba jest ujemna,% f zawsze wyświetla znak -. Jeśli chcesz, aby numer zawsze wyświetlał znak, nawet jeśli jest pozytywny, użyj znaku + zaraz po znaku% (jest to przydatne do ustawiania list liczb dodatnich i ujemnych):
>>> print '% + f'% liczba
+12.34560
Jeśli chcesz, aby lista dodatnich i ujemnych liczb była wyrównana, ale nie chcesz widzieć znaku + na liczbach dodatnich, użyj spacji zamiast znaku +, zaraz po %:
>>> number2 = -98.76
>>> print '% .2f' % number2
-98.76
>>> print '% .2f' % number
12.35
Zauważ, że na wyjściu znajduje się spacja przed 12, tak że 12 i 98 ustawiają się jeden pod drugim, nawet jeśli jeden ma znak, a drugi nie.
E-notacja: %e i %E
Kiedy rozmawialiśmy o e-notacji (w Części 3), obiecałem, że pokażę ci, jak drukować liczby za pomocą e-notacji. Cóż, tutaj jest:
>>> number = 12.3456
>>> print '%e' % number
1.234560e+01
Ciąg formatu %e jest używany do drukowania notacji elektronicznej. Zawsze drukuje sześć miejsc po przecinku, chyba że powiesz inaczej. Możesz wydrukować więcej lub mniej miejsc po przecinku, używając .n po%, tak jak możesz z float
>>> number = 12.3456
>>> print '%.3e' % number
1.235e+01
>>> print '%.8e' % number
1.23456000e+01
%.3e zaokrąglił do trzech miejsc po przecinku, a%.8e dodał kilka zer, aby uzyskać dodatkowe cyfry. Możesz użyć małej lub dużej litery e, a wyjście użyje tego samego przypadku, którego użyłeś w ciągu formatowania:
>>> print '%E' % number
1.234560E+01
Automatyczne float lub e-notacja: %g i %G
Jeśli chcesz, aby Python automatycznie wybierał dla ciebie notację float lub notację E, użyj ciągu formatującego %g. Ponownie, jeśli użyjesz wielkich liter, na wyjściu otrzymasz wielką literę E:
>>> number1 = 12.3
>>> number2 = 456712345.6
>>> print '%g' % number1
12.3
>>> print '%g' % number2
4.56712e+08
Czy zauważyłeś, że Python automatycznie wybrał notację E dla dużej liczby i regularnej notacji zmiennoprzecinkowej dla mniejszej liczby?
Jak wyświetlić znak procentu?
Być może zastanawiasz się, ponieważ znak procentu (%) jest znakiem specjalnym dla łańcuchów formatowania, w jaki sposób tworzysz wydruk znaku %? Czasami Python jest na tyle sprytny, by dowiedzieć się, kiedy używasz znaku %, aby rozpocząć łańcuch formatowania i kiedy chcesz go wydrukować. Spróbuj tego:
>>> print 'Mam 90% na teście z matmy!'
Mam 90% na teście z matmy!
W tym przypadku nie było drugiego % poza łańcuchem i nie było żadnej zmiennej do sformatowania, więc Python założył, że % był po prostu kolejnym znakiem w ciągu. Ale jeśli drukujesz za pomocą łańcuchów formatów i chcesz wydrukować znak procentu, używasz dwóch znaków procentu, tak jak użyłeś dwóch odwrotnych ukośników, aby wydrukować odwrotny ukośnik. Mówimy, że pierwszy znak procentu ucieka przed drugim znakiem procentu.
>>> math = 75.4
>>> print 'Mam %.1f%% na teście ' % matmy
Mam75.4% na teście z matmy
Pierwsze% uruchamia ciąg formatujący. Dwa %% razem mówią Pythonowi, że faktycznie chcesz wydrukować znak%. Następnie masz% poza cudzysłowami, które mówią Pythonowi, że zmienna, którą chcesz wydrukować, będzie następna.
Więcej niż jeden format ciągu
Co zrobić, jeśli chcesz umieścić więcej niż jeden ciąg formatu w pojedynczej instrukcji drukowania? Oto jak to zrobić
>>> math = 75.4
>>> science = 82.1
>>> print 'Mam %.1f na matmie and %.1f w nauce' % (matma, nauka)
Możesz umieścić dowolną liczbę łańcuchów formatowania w instrukcji print, a następnie krotkę zmiennych, które chcesz wydrukować. Pamiętaj, że krotka jest jak lista, ale używa okrągłych nawiasów zamiast kwadratowych, a krotka jest niezmienna. Jest to jeden przypadek, w którym Python jest wybredny - musisz użyć krotki; nie możesz użyć listy. Jedynym wyjątkiem jest sytuacja, w której masz tylko jedną zmienną do sformatowania; to nie musi być w krotce. (Widziałeś to w większości naszych przykładów). Upewnij się, że liczba ciągów formatów (w cudzysłowach) i liczba zmiennych (poza cudzysłowami) są zgodne lub pojawi się komunikat o błędzie
Przechowywanie sformatowanych liczb
Czasami nie chcesz drukować sformatowanego numeru od razu, ale raczej przechowuj go w postaci łańcucha, aby użyć go później. To łatwe. Zamiast go drukować, po prostu przypisz go do zmiennej, takiej jak ta
>>> my_string = '%.2f' % 12.3456
>>> print my_string
12.35
>>> print 'Odpowiedź', my_string
Odpowiedź to 12.35
Zamiast bezpośrednio drukować sformatowaną liczbę, przypisaliśmy ją do zmiennej my_string. Następnie połączyliśmy my_string z innym tekstem i wydrukowaliśmy nasze zdanie. Przechowywanie sformatowanego numeru jako ciągu znaków jest bardzo przydatne dla GUI i innych programów graficznych, takich jak gry. Gdy masz już nazwę zmiennej dla sformatowanego ciągu, możesz ją wyświetlić w dowolny sposób: w polu tekstowym, przycisku, oknie dialogowym lub ekranie gry.
Formatowanie, nowy sposób
Składnia formatowania łańcuchów, o których właśnie dowiedziałeś się o pracach we wszystkich wersjach Pythona. Ale istnieje inny sposób robienia tego samego w Pythonie 2.6 i nowszych wersjach. Ponieważ używamy Pythona 2.7 w tej książce, myślałem, że przyjrzymy się także nowej drodze. Możesz to zobaczyć w kodzie Pythona, więc w ten sposób przynajmniej wiesz, co to znaczy. Możesz zdecydować, która składnia - stara lub nowa - chcesz użyć do formatowania łańcuchów.
Metoda format()
Łańcuchy Pythona (od wersji) mają metodę o nazwie format(). Działa to bardzo podobnie do formatu łańcucha % , które widziałeś powyżej. W rzeczywistości specyfikatory formatu - f, g, e itd. - są takie same. Po prostu używasz ich trochę inaczej. Najlepszym sposobem na to jest przykład. Oto stary sposób:
print ' Mam %.1f na matmie and %.1f w nauce' % (matma, nauka)
A oto nowy sposób:
print 'Mam {0:.1f} z matmy, {1:.1f} w nauce'.format(matma, nauka)
W nowy sposób, zamiast uruchamiać specyfikator formatu z %, umieszczasz go w nawiasach klamrowych. 0 lub 1 mówi Pythonowi, która zmienna z krotki zmiennych zostanie sformatowana. Pamiętaj, że liczenie Pythona rozpoczyna się od 0, więc pierwszy element w krotce (zmienna matematyka) ma indeks 0, a drugi (zmienna nauka) ma indeks 1. Następnie używasz .1f, podobnie jak w przypadku starej metody. To wszystko. Możesz zapisać sformatowany ciąg znaków w zmiennej, tak jak w starym,% formatowaniu:
distance = 149597870700
myString = 'Słońce jest {0:.4e} metrów od ziemi'.format(distance)
A ponieważ nie używasz znaku% do oznaczania ciągów formatów, nie musisz robić niczego specjalnego, jeśli chcesz wydrukować znak%
>>> print 'Mam {0:.1f}% z matmy'.format(matma)
Mam 87% z matmy
Łańcuchy "n" rzeczy
Kiedy po raz pierwszy dowiedziałeś się o łańcuchach, zauważyłeś, że możesz połączyć dwa z nich znakiem +, tak jak poniżej:
>>> print 'kot + 'pies'
kotpies
Teraz znajdziesz więcej rzeczy, które możesz zrobić za pomocą łańcuchów. Ciągi w Pythonie są naprawdę obiektami (zobacz, wszystko jest obiektem
) i mają swoje własne metody do robienia rzeczy takich jak wyszukiwanie, dzielenie i łączenie. Są one znane jako metody łańcuchowe. Metoda format (), którą właśnie widziałeś, jest jedną z metod łańcuchowych.
Dzielenie łańcuchów
Czasami trzeba podzielić długi ciąg na kilka mniejszych. Zwykle chcesz to zrobić w określonych punktach łańcucha, np. Za każdym razem, gdy pojawia się określony znak. Na przykład powszechnym sposobem przechowywania danych w pliku tekstowym jest oddzielenie ich przecinkiem. Więc możesz mieć listę nazw, która wygląda tak:
>>> name_string = 'Sam,Brad,Alex,Cameron,Toby,Gwen,Jenn,Connor'
Załóżmy, że chcesz umieścić te nazwy na liście, a każdy element będzie jedną nazwą. Musisz podzielić ten ciąg wszędzie, gdzie jest przecinek. Metoda Pythona do tego jest nazywana split() i działa w ten sposób:
>>> names = name_string.split(',')
Mówisz, jakiego znakui użyć jako znacznika podziału, i wyświetlasz z powrotem listę, która jest oryginalnym łańcuchem podzielonym na części. Jeśli wydrukujemy dane wyjściowe z tego przykładu, jeden duży ciąg nazw zostanie podzielony na pojedyncze elementy na liście
>>> print names
['Sam','Brad','Alex','Cameron','Toby','Gwen','Jenn','Connor']
>>> for name in names:
print name
Sam
Brad
Alex
Cameron
Toby
Gwen
Jenn
Connor
Możesz mieć więcej niż jedną postać jako znacznik podziału. Na przykład możesz użyć "Toby" jako znacznika podziału, a otrzymasz następującą listę:
>>> parts = name_string.split('Toby,')
>>> print parts
['Sam,Brad,Alex,Cameron', 'Gwen,Jenn,Connor']
>>> for part in parts:
print part
Sam,Brad,Alex,Cameron
Gwen,Jenn,Connor
Tym razem ciąg został podzielony na dwie części: wszystkie rzeczy po jednej stronie "Toby" i wszystkie rzeczy po drugiej stronie "Toby". Zauważ, że "Toby" nie pojawia się na liście, ponieważ znacznik podziału zostaje odrzucony. Jest jeszcze jedna rzecz do poznania. Jeśli nie podasz Pythonowi żadnego znacznika podziału, to podzielisz ten ciąg na dowolne białe znaki:
>>> names = name_string.split()
Białe znaki oznaczają dowolne spacje, znaki tabulacji lub znaki nowej linii.
Łączenie stringów
Właśnie widziałeś, jak podzielić strunę na mniejsze kawałki. Jak połączyć dwa lub więcej ciągów, aby utworzyć jeden większy ciąg? Już w Części 2 widziałeś, że możesz łączyć ciągi za pomocą operatora +. To tak, jakby dodać dwa ciągi razem, z tym wyjątkiem, że nazywa się to łączeniem. Istnieje inny sposób łączenia ciągów. Możesz użyć funkcji join(). Mówisz, jakie łańcuchy chcesz dołączyć i jakie znaki (jeśli w ogóle) chcesz wstawić między częściami, gdy są połączone. Jest to zasadniczo przeciwieństwo split(). Oto przykład w trybie interaktywnym:
>>> word_list = ['Moje', 'imię', 'to', 'Jan']
>>> long_string = ' '.join(word_list)
>>> long_string
'Moje imię to Jan'
Przyznaję, że wygląda to trochę dziwnie. Znaki, które będą przechodzić między każdym fragmentem połączonego łańcucha, przechodzą przed join(). W tym przypadku potrzebowaliśmy spacji między każdym słowem, więc użyliśmy ' ' .join (). To różni się od tego, czego oczekuje większość ludzi, ale tak właśnie działa metoda Pythona join(). Poniższy przykład sprawia, że brzmię jak pies:
>>> long_string = 'WOOF WOOF' .join (word_list)
>>> long_string
"Nazwa WOOF WOOF WOOF WOOF to WOOF WOOF Jan"
Innymi słowy, łańcuch przed join () jest używany jako klej do trzymania innych łańcuchów razem.
Wyszukiwanie ciągów znaków
Załóżmy, że chcesz stworzyć program dla swojej mamy, który przyjmuje przepisy i wyświetla je w GUI. Chcesz umieścić składniki w jednym miejscu, a instrukcje w innym. Wyobraźmy sobie, że przepis wygląda mniej więcej tak
Ciasto czekoladowe
Składniki:
2 jajka
1/2 szklanki mąki
1 łyżeczka sody oczyszczonej
1 funt czekolady
Instrukcje:
Rozgrzej piekarnik do 250C
Wymieszaj wszystkie składniki razem
Piecz przez 30 minut
Załóżmy, że linie receptury znajdują się na liście, a każda linia jest osobnym elementem na liście. Jak znaleźć sekcję "Instrukcje"? Python ma kilka metod, które ci pomogą.
Metoda startswith() informuje, czy ciąg rozpoczyna się od określonego znaku lub znaków. Przykład jest najłatwiejszym sposobem na pokazanie tego. Wypróbuj to w trybie interaktywnym:
>>> name = "Frankenstein"
>>> name.startswith('F')
True
>>> name.startswith("Frank")
True
>>> name.startswith("Flop")
False
Nazwa Frankenstein zaczyna się od litery F, więc pierwsza była prawdziwa. Nazwa Frankenstein zaczyna się od liter Frank, więc druga była prawdziwa. Nazwa Frankenstein nie zaczyna się od Flopa, więc jedno było Fałszem. Ponieważ powraca metoda startswith() wartość True lub False, możesz użyć jej w porównaniach lub instrukcjach, takich jak to:
>>> if name.startswith ("Frank"):
print "Czy mogę zadzwonić Frank?"
Istnieje podobna metoda o nazwie endswith(), która robi to, czego można się spodziewać:
>>> name = "Frankenstein"
>>> name.endswith('n')
True
>>> name.endswith('stein')
True
>>> name.endswith('stone')
False
Wróćmy teraz do problemu
Gdybyśmy chcieli znaleźć początek sekcji "Instrukcje", moglibyśmy zrobić coś takiego:
i = 0
while not lines[i].startswith("Instructions"):
i = i + 1
Ten kod będzie się zapętlał, dopóki nie znajdzie linii zaczynającej się od "Instrukcje". Pamiętaj, że linie [i] oznaczają, że jest to indeks dla linii. Zaczniesz więc od linii [0] (pierwsza linia), następnie linii [1] (druga linia) i tak dalej. Gdy zakończy się pętla while, będę równy indeksowi linii rozpoczynającej się od "Instrukcje", której szukamy.
Wyszukiwanie w dowolnym miejscu ciągu: in i index()
Metody startswith() i endswith() sprawdzają się bardzo dobrze przy wyszukiwaniu pozycji na początku lub na końcu łańcucha. Ale co, jeśli chcesz znaleźć coś w środku łańcucha? Powiedzmy, że mieliśmy kilka ciągów znaków, które miały adresy uliczne, jak poniżej:
657 Maple Lane
47 Birch Street
95 Maple Drive
Może chcemy znaleźć wszystkie adresy z "Maple" w nich. Żaden z nich nie zaczyna się ani nie kończy "Maple", ale dwa z nich zawierają słowo Maple. Jak je znajdziesz? Właściwie to już widziałeś, jak to zrobić. Kiedy rozmawialiśmy o listach, zobaczyłeś, że możesz sprawdzić, czy dany element znajduje się na liście
if someItem in my_list:
print "Znalazłem!"
Użyliśmy słowa kluczowego, aby sprawdzić, czy dany element znajduje się na liście. Słowo kluczowe in działa również w przypadku łańcuchów. Ciąg jest w zasadzie listą znaków, więc możesz to zrobić:
>>> addr1 = '657 Maple Lane'
>>> if 'Maple' in addr1:
print "Ten adres ma 'Maple' w sobie."
Gdy szukasz mniejszego ciągu, takiego jak "Klon", w większym ciągu, np. "657 Maple Lane", mniejszy ciąg nazywany jest podciągiem.
Słowo kluczowe in mówi tylko, czy podciąg znajduje się gdzieś w sprawdzanym łańcuchu. Nie mówi ci, gdzie to jest. W tym celu potrzebujesz metody index(). Podobnie jak w przypadku list, index() mówi ci, gdzie w większym ciągu zaczyna się mniejszy ciąg. Oto przykład:
>>> addr1 = '657 Maple Lane'
>>> if 'Maple' in addr1:
position = addr1.index('Maple')
print "znaleziono 'Maple' pod indeksem", position
Słowo Maple zaczyna się w pozycji 4 napisu "657 Maple Lane". Podobnie jak w przypadku list, indeksy (lub pozycje) liter w ciągu zaczynają się od 0, więc M ma indeks 4.
Zauważ, że zanim spróbowaliśmy użyć index(), najpierw sprawdziliśmy, czy podciąg "Maple" był w większym ciągu. To dlatego, że jeśli używasz indeksu (), a tego, czego szukasz, nie ma w ciągu, otrzymasz błąd. Sprawdzanie za pomocą pierwszego zapewnia, że nie wystąpi błąd. To samo robiliśmy z listami.
Usuwanie części stringa
Dość często będziesz chciał usunąć lub zdjąć część łańcucha . Zwykle będziesz chciał zdjąć coś z końca, np. Znak nowej linii lub dodatkowe spacje. Python ma metodę łańcuchową o nazwie strip(), aby to zrobić. Po prostu powiesz to, co chcesz rozebrać, tak:
>>> name = 'Jan Sandek'
>>> short_name = name.strip('de')
>>> short_name
'Jan San'
W tym przypadku usunęliśmy "dek" z końca imienia. Gdyby na końcu nie było "dek", nic by nie zostało rozebrane:
>>> name = 'Bart Simpson'
>>> short_name = name.strip('de')
>>> short_name
'Bart Simpson'
Jeśli nie powiesz strip(), co usunąć, usuniesz wszelkie białe znaki. Jak powiedzieliśmy wcześniej, zawiera spacje, tabulatory i znaki nowej linii. Więc gdybyśmy mieli dodatkowe przestrzenie do pozbycia się, moglibyśmy to zrobić:
>>> name = "Jan Sandek "
>>>> short_name = name.strip()
>>> short_name
'Jan Sandek'
Zauważ, że dodatkowe spacje po nazwisku zostały usunięte. Dobrą rzeczą jest to, że nie musisz informować strip(), ile spacji ma zostać usuniętych. Usunie wszystkie białe znaki na końcu łańcucha.
Zmiana wielkości liter
Chcę ci pokazać jeszcze dwie metody łancuchowe. Służą do zmiany wielkości liter z dużych na małe lub odwrotnie. Czasami chcesz porównać dwa ciągi, takie jak "Hello" i "hello", i chcesz wiedzieć, czy mają te same litery, nawet jeśli wielkość nie jest taka sama. Jednym ze sposobów na to jest wykonanie wszystkich liter w obu łańcuchach małymi literami, a następnie porównanie. Python ma do tego metodę łańcuchową. Nazywa lower(). Wypróbuj to w trybie interaktywnym:
>>> string1 = "Hello"
>>> string2 = string1.lower()
>>> print string2
hello
Jest podobna metoda nazwana upper():
>>> string3 = string1.upper()
>>> print string3
HELLO
Możesz tworzyć kopie oryginalnych ciągów z małymi literami (lub wielkimi literami), a następnie porównać kopie, aby sprawdzić, czy są takie same, ignorując wielkość liter.
Czego się nauczyłeś?
• Jak dostosować odstępy w pionie (dodawanie lub usuwanie znaków nowej linii)
• Jak ustawić odstępy poziome za pomocą zakładek
• Jak wyświetlać różne formaty liczb za pomocą łańcuchów formatowania
• Dwa sposoby używania ciągów formatujących - znak% i metoda format ()
• Jak podzielić łańcuchy na split () i połączyć je za pomocą join ()
• Jak przeszukiwać ciągi za pomocą startswith (), endswith (), in i index ()
• Jak usunąć rzeczy z końca łańcucha za pomocą paska ()
• Jak tworzyć ciągi znaków wielkimi literami lub wszystkimi małymi literami z górnymi () i niższymi ()
Sprawdź swoją wiedzę
1 Jeśli masz dwie oddzielne instrukcje drukowania, takie jak ta
printj "Jakie jest"
print "Twoje imię?"
jak sprawisz, że wszystko będzie drukowane na tej samej linii?
2 Jak można dodać dodatkowe puste linie podczas drukowania?
3 Jakiego specjalnego kodu drukowania używasz do wyrównywania kolumn?
4 Jakiego formatu formatu używasz do wymuszenia drukowania liczby w notacji elektronicznej?
Wypróbuj to
1 Napisz program, który poprosi o imię, wiek i ulubiony kolor osoby, a następnie wydrukuje je w jednym zdaniu. Uruchomienie programu powinno wyglądać następująco:
>>> ======================== RESTART ======================
>>>
Jak masz na imię? Sam
Ile masz lat? 12
Jaki jest Twój ulubiony kolor? Zielony
Masz na imię Sam, masz 12 lat i lubisz zieleń
2 Pamiętasz nasz program tabeli czasu z rozdziału 8 (listing 8.5)? Napisz ulepszoną wersję, która używa kart, aby upewnić się, że wszystko układa się ładnie w kolumnach.
3 Napisz program, który obliczy wszystkie ułamki 8 (na przykład 1/8, 2/8, 3/8,
do 8/8) i wyświetli je z dokładnością do trzech miejsc po przecinku.
Czy zastanawiałeś się kiedyś, jak Twoja ulubiona gra komputerowa zapamiętuje najlepsze wyniki, nawet po wyłączeniu komputera? Jak Twoja przeglądarka zapamiętuje twoje ulubione strony internetowe? Tu dowiesz się, jak to zrobić. Kilka razy rozmawialiśmy o tym, jak programy mają trzy główne aspekty: wprowadzanie, przetwarzanie i wyjście. Do tej pory dane wejściowe pochodziły głównie bezpośrednio od użytkownika, z klawiatury i myszy. Wyjście zostało wysłane bezpośrednio na ekran (lub głośniki, w przypadku dźwięku). Ale czasami musisz użyć danych wejściowych pochodzących z innych źródeł. Dość często programy muszą wykorzystywać dane wejściowe, które są gdzieś przechowywane, a nie wprowadzane podczas działania programu. Niektóre programy muszą pobierać dane z pliku na dysku twardym komputera. Na przykład, jeśli grasz w Wisielca, twój program będzie potrzebował listy słów aby wybrać tajne słowo. Ta lista słów musiałaby być gdzieś przechowywana, prawdopodobnie w pliku "listy słów", który towarzyszy programowi. Program musiałby otworzyć ten plik, przeczytać listę słów i wybrać słowo do użycia. To samo dotyczy wyjścia. Czasami wyjście programu musi być przechowywane. Wszystkie zmienne używane przez program są tymczasowe - są tracone, gdy program się kończy. Jeśli chcesz zapisać niektóre informacje do późniejszego wykorzystania, musisz je przechowywać w bardziej trwałym miejscu, jak na dysku twardym. Na przykład, jeśli chcesz zachować listę najlepszych wyników dla gry, musisz zapisać je w pliku, aby przy następnym uruchomieniu program mógł odczytać plik i wyświetlić wyniki. W tej części zobaczysz, jak otwierać pliki i jak je czytać i zapisywać (uzyskiwać z nich informacje i przechowywać w nich informacje).
Co to jest plik?
Zanim zaczniemy mówić o otwieraniu, czytaniu i zapisywaniu plików, powinniśmy porozmawiać o tym, czym jest plik. Powiedzieliśmy, że komputery przechowują informacje w formacie binarnym, który używa tylko 1-nek i 0-er. Każda 1 lub 0 jest nazywane bitem, a grupa ośmiu bitów jest nazywana bajtem. Plik jest zbiorem bajtów, który ma nazwę i jest przechowywany na dysku twardym, dysku CD, dysku DVD, dysku flash lub innym rodzaju pamięci. Pliki mogą przechowywać wiele różnych rodzajów informacji. Plik może zawierać tekst, obrazy, muzykę, programy komputerowe, listę numerów telefonów i tak dalej. Wszystko, co jest przechowywane na dysku twardym komputera, jest przechowywane jako pliki. Programy składają się z jednego lub więcej plików. System operacyjny komputera (na przykład Windows lub Mac OS X lub Linux) ma wiele, wiele plików, które musi uruchomić. Pliki mają następujące właściwości:
• Nazwa
• Typ, który wskazuje, jakie dane znajdują się w pliku (obraz, muzyka, tekst)
• Lokalizacja (gdzie plik jest przechowywany)
• Rozmiar (ile bajtów jest w pliku)
Nazwy plików
W większości systemów operacyjnych (w tym Windows) część nazwy pliku jest używana do określenia typu danych znajdujących się w pliku. Nazwy plików zwykle mają co najmniej jedną "kropkę" (symbol okresu) w nazwie. Część po kropce informuje, jakiego rodzaju jest to plik. Ta część nazywa się rozszerzeniem. Oto kilka przykładów:
• W my_letter.txt rozszerzeniem jest .txt, co oznacza "tekst", więc ten plik prawdopodobnie zawiera w sobie tekst.
• W my_song.mp3 rozszerzeniem jest .mp3, który jest rodzajem pliku dźwiękowego.
• W pliku my_program.exe rozszerzeniem jest .exe, co oznacza "plik wykonywalny". Jak już wspomniałem w rozdziale 1, "wykonywanie" to kolejne słowo do uruchomienia programu. Tak więc pliki .exe są zwykle programami, które można uruchomić.
• W my_cool_game.py rozszerzenie to .py, co zwykle oznacza program w Pythonie.
W systemie Mac OS X pliki programów (pliki zawierające program, który można uruchomić) mają rozszerzenie .app, które oznacza "aplikacja", co jest kolejnym słowem "program".
Ważną rzeczą, którą należy wiedzieć, jest to, że można nazwać plik dowolną rzeczą i użyć dowolnego rozszerzenia. Możesz utworzyć plik tekstowy (na przykład w Notatniku) i nazwać go my_notes.mp3. To nie czyni z niego pliku dźwiękowego. Nadal ma w nim tylko tekst, więc jest to naprawdę plik tekstowy. Dałeś to rozszerzenie pliku, które sprawia, że wygląda jak plik dźwiękowy, co prawdopodobnie wprowadzi w błąd ludzi i komputery. Przy nadawaniu nazwy plikowi bardzo dobrze jest użyć rozszerzenia pliku, które odpowiada rodzajowi pliku.
Lokalizacje plików
Do tej pory pracowaliśmy z plikami przechowywanymi w tej samej lokalizacji, co sam program. Nie martwiliśmy się o to, jak znaleźć plik, ponieważ znajduje się w tym samym miejscu, co program. To tak, jakbyś był w swoim pokoju, nie musisz się martwić, jak znaleźć swoją szafę - jest tam. Ale jeśli jesteś w innym pokoju, w innym domu lub w innym mieście, znalezienie szafy jest bardziej skomplikowane!
Każdy plik musi być gdzieś przechowywany, więc oprócz nazwy każdy plik ma lokalizację. Dyski twarde i inne nośniki pamięci są zorganizowane w foldery lub katalogi. Foldery i katalogi to dwie nazwy tego samego. Są sposobem grupowania plików razem. Sposób, w jaki foldery lub katalogi są uporządkowane i połączone, nazywany jest strukturą folderów lub strukturą katalogów. W systemie Windows każdy nośnik pamięci ma literę, np. C na dysku twardym, a może E na dysk flash. W systemie Mac OS X i Linux każdy nośnik pamięci ma nazwę (na przykład hda lub FLASH DRIVE). Każdą jednostkę pamięci można podzielić na wiele folderów, takich jak Muzyka, Obrazy i Programy. Foldery mogą również zawierać inne foldery, a te foldery mogą zawierać inne foldery i tak dalej.
Pierwszy poziom to Muzyka. Kolejny poziom ma Nową Muzykę i Starą Muzykę, a następny poziom to Kind of old music i Really old music.
Foldery w innych folderach są nazywane podfolderami. Jeśli używamy terminu katalogi, nazwałbyś je podkatalogami
Gdy próbujesz znaleźć plik lub folder w Eksploratorze Windows (lub innej przeglądarce plików), foldery są jak gałęzie drzewa. Korzeń to sam napęd, jak C: lub E :. Każdy główny folder jest jak główna gałąź drzewa. Foldery w każdym głównym folderze są jak mniejsze gałęzie i tak dalej. Ale kiedy trzeba uzyskać dostęp do plików z poziomu programu, pomysł drzewa nie działa. Twój program nie może kliknąć folderów i przeglądać drzewa, aby znaleźć pojedyncze pliki. Potrzebuje bardziej bezpośredniego sposobu znalezienia pliku. Na szczęście istnieje inny sposób przedstawienia struktury drzewa. Jeśli spojrzysz na pasek adresu Eksploratora Windows po kliknięciu różnych folderów i podfolderów, zobaczysz coś, co wygląda tak:
E:\Muzyka\ Stara muzyka Naprawdę stara muzyka\my_song.mp3
To się nazywa ścieżka. Ścieżka jest opisem, gdzie plik znajduje się w strukturze folderów. Ta konkretna ścieżka brzmi następująco:
1 Zacznij od napędu E :.
2 Przejdź do folderu o nazwie Muzyka.
3 W folderze Muzyka przejdź do podfolderu o nazwie Stara muzyka.
4 W podfolderze Stara Muzyka przejdź do podfolderu o nazwie Naprawdę stara muzyka.
5 W podfolderze Naprawdę stara muzyka znajduje się plik o nazwie my_song.mp3.
Możesz dostać się do dowolnego pliku na komputerze, używając ścieżki takiej jak ta. W ten sposób programy znajdują i otwierają pliki. Oto przykład:
image_file = "c: / program files / HelloWorld / examples / beachball.png"
Zawsze możesz dostać się do pliku używając jego pełnej ścieżki. Jest to nazwa, w tym wszystkie nazwy folderów bezpośrednio po drzewie do katalogu głównego (dysk, np. C :). Nazwa w tym przykładzie jest pełną ścieżką dostępu.
Slash lub backslash?
Ważne jest, aby ukośniki (\ i /) poszły we właściwy sposób. Windows zaakceptuje ukośnik (/) lub odwrotny ukośnik ( \ ) w nazwach ścieżek, ale jeśli użyjesz czegoś takiego jak c:\program.txt w programie Python, część \t spowoduje problem. Pamiętasz, że rozmawialiśmy o znakach specjalnych do formatowania wydruku, np. \t dla tabulacji. Dlatego należy unikać znaków w ścieżkach plików. Python (i Windows) będą traktować jako znak tabulacji zamiast części nazwy pliku zgodnie z przeznaczeniem. Użyj / zamiast. Inną opcją jest użycie podwójnych ukośników odwrotnych, takich jak ten
image_file "c:\\program files\HelloWorld\images\beachball.png"
Pamiętaj, że jeśli chcesz wydrukować znak, musisz umieścić inny przed nim. Działa w ten sam sposób w nazwach plików. Ale zalecam używanie / zamiast.
Czasami nie potrzebujesz całej ścieżki do pliku. Następna sekcja mówi o znalezieniu pliku, jeśli jesteś już w drodze.
Znajdujesz gdzie jesteś
Większość systemów operacyjnych (w tym Windows) ma pomysł na katalog roboczy, czasami nazywany bieżącym katalogiem roboczym lub w skrócie cwd. Jest to katalog w drzewie folderów, w którym aktualnie pracujesz. Wyobraź sobie, że zacząłeś w katalogu głównym (C :), i przeniosłeś się w dół do gałęzi Program Files do gałęzi Hello World. Twoja bieżąca lokalizacja lub bieżący katalog to C: / Program Files / Hello World.
Teraz, aby dostać się do pliku o nazwie beachball.png, musisz przejść do gałęzi Przykłady. Tak więc twoją ścieżką do uzyskania byłoby Przykłady / beachball.png. Ponieważ byłeś już na dobrej drodze, potrzebowałeś tylko reszty ścieżki, aby dostać się tam, gdzie chciałeś.
Pamiętasz, z części dotyczącej dźwięku, otworzyliśmy nasze pliki dźwiękowe jako splat.wav i tak dalej? Nie użyliśmy ścieżki. To dlatego, że kazałem ci skopiować pliki dźwiękowe do tego samego folderu, w którym zapisałeś program.
Zauważ, że mam pliki Pythona (z rozszerzeniem .py) w tym samym folderze co pliki dźwiękowe (z rozszerzeniem .wav). Gdy uruchomiony jest program w Pythonie, jego katalog roboczy znajduje się w dowolnym folderze, w którym przechowywany jest plik .py. Jeśli zapisałeś swój program w e:/ programs i uruchomił program, program ten zaczynałby się od e: /programs jako katalog roboczy. Jeśli masz plik dźwiękowy przechowywany w tym samym folderze, Twój program potrzebuje tylko nazwy pliku, aby użyć tego pliku. Nie potrzeba ścieżki, aby się tam dostać, ponieważ już tam jest. Więc możesz to zrobić:
my_sound = pygame.mixer.Sound ("splat.wav")
Zwróć uwagę, że nie musisz używać pełnej ścieżki do pliku dźwiękowego (który byłby e: /programs/splat.wav). Wystarczy użyć nazwy pliku bez ścieżki, ponieważ plik znajduje się w tym samym folderze, co program, który go używa.
Dość o ścieżkach!
To wszystko, co powiem o ścieżkach i lokalizacjach plików. Cały temat folderów i katalogów, ścieżek, katalogów roboczych i tak dalej jest taki, który niektórzy ludzie mylą, a pełne wyjaśnienie tego zajęłoby wiele stron. Ale piszemy o programowaniu, a nie o systemach operacyjnych, lokalizacjach plików lub ścieżkach, więc jeśli masz z tym problemy, możesz poprosić o pomoc rodzica, nauczyciela lub kogoś innego, kto wie o komputerach. Wszystkie inne przykłady w tej książce, które używają plików, mają je w tym samym miejscu co program, więc nie musisz się martwić o ścieżkę ani o używanie pełnych ścieżek.
Otwieranie pliku
Zanim otworzysz plik, musisz wiedzieć, co zrobisz z plikiem:
• Jeśli będziesz używać pliku jako danych wejściowych (patrząc na to, co znajduje się w pliku, nie zmieniając go), otworzysz plik do czytania.
• Jeśli utworzysz nowy plik lub zastąpisz istniejący plik czymś zupełnie nowym, otworzysz plik do zapisu.
• Jeśli będziesz dodawać do istniejącego pliku, otworzysz plik do dołączenia. (Pamiętasz z części 12, że dołączenie oznacza dodanie do czegoś.)
Kiedy otwierasz plik, tworzysz obiekt pliku w Pythonie. (Zobacz, powiedziałem ci, że wiele rzeczy w Pythonie to obiekty.) Obiekt pliku tworzysz za pomocą funkcji open() z nazwą pliku, taką jak ta:
my_file = open ('moja_nazwa_pliku.txt', 'r')
Nazwa pliku jest łańcuchem, więc potrzebuje cudzysłowów wokół niego. Część "r" oznacza, że otwierasz plik do czytania. Dowiesz się więcej na ten temat w następnej sekcji. Ważne jest, aby zrozumieć różnicę między obiektem pliku a nazwą pliku. Obiekt pliku jest tym, którego użyjesz w programie, aby uzyskać dostęp do pliku. Nazwa pliku jest tym, co system Windows (lub Linux lub Mac OS X) wywołuje plik na dysku. Robisz to samo z ludźmi. Masz różne nazwy, których używasz w różnych miejscach. Jeśli imię twojego nauczyciela to Fredek Wesoły, prawdopodobnie nazywasz go panem Wesołym. Jego przyjaciele prawdopodobnie nazywają go Fred, a jego nazwa użytkownika komputera może być fwesoly. W przypadku plików istnieje nazwa używana przez system operacyjny do przechowywania pliku na dysku (nazwa pliku), a także nazwa używana przez program podczas pracy z plikiem (obiekt pliku). Dwie nazwy - nazwa obiektu i nazwa pliku - nie muszą być takie same. Możesz wywołać obiekt, jak chcesz. Na przykład, jeśli mamy plik tekstowy z kilkoma notatkami o nazwie notes.txt, możemy to zrobić:
notes = open ('notes.txt', 'r')
Obiekt pliku Nazwa pliku
Albo możemy to zrobić:
some_crazy_stuff = open("notes.txt", 'r')
Obiekt pliku Nazwa pliku
Po otwarciu pliku i utworzeniu obiektu pliku nazwa pliku nie jest już potrzebna. Robisz wszystko w programie, używając obiektu pliku.
Czytanie pliku
Jak wspomniałem w ostatniej sekcji, otwierasz plik i tworzysz obiekt pliku za pomocą funkcji open(). Jest to jedna z wbudowanych funkcji Pythona. Aby otworzyć plik do odczytu, należy użyć "r" jako drugiego argumentu, takiego jak ten:
my_file = open ('notes.txt', 'r')
Jeśli spróbujesz otworzyć plik do czytania, który nie istnieje, pojawi się błąd. (Przecież nie możesz przeczytać czegoś, czego tam nie ma, prawda?) Python ma kilka wbudowanych funkcji do pobierania informacji z pliku do twojego programu po otwarciu pliku. Aby odczytać wiersze tekstu z pliku, możesz użyć metody readlines(), takiej jak ta:
lines = mój_plik.readlines ()
Spowoduje to odczytanie całego pliku i utworzenie listy z jednym wierszem tekstu w każdym elemencie listy. Powiedzmy, że plik notes.txt zawierał krótką listę rzeczy, które musimy zrobić dzisiaj:
Umyć samochód
Pościelić łóżko
Odebrać zasiłek
Moglibyśmy użyć programu takiego jak Notatnik do utworzenia tego pliku. W rzeczywistości, dlaczego nie tworzysz takiego pliku za pomocą Notatnika (lub ulubionego edytora tekstu) w tej chwili? Wywołaj go notes.txt i zapisz w tym samym miejscu, w którym zapisujesz programy w Pythonie. Następnie zamknij Notatnik. Jeśli otworzymy ten plik za pomocą krótkiego programu Python i przeczytamy go, kod może wyglądać tak:
Listing 23.1 Otwieranie i czytanie z pliku
my_file = open('notes.txt', 'r')
lines = my_file.readlines()
print lines
Wynik byłby taki (w zależności od tego, co umieściłeś w pliku):
>>>======================= RESTART =========================
>>>
['Umyć samochód', 'Pościelić łóżko', 'Odebrać zasiłek']
Linie tekstu zostały odczytane z pliku i zostały umieszczone na liście, którą nazwaliśmy liniami. Każdy element na liście jest łańcuchem zawierającym jedną linię z pliku. Zauważ część n na końcu pierwszych dwóch wierszy. Są to znaki nowej linii, które oddzielają linie w pliku. Właśnie wtedy nacisnęliśmy Enter podczas tworzenia pliku. Jeśli naciśniesz Enter po wpisaniu ostatniej linii, pojawi się trzecia n po trzeciej pozycji. Jest jeszcze jedna rzecz, którą musimy dodać do programu z listingu 23.1. Kiedy skończymy z plikiem, powinniśmy go zamknąć:
my_file.close()
Jeśli inny program musi użyć pliku, a nasz program go nie zamknął, inny program może nie mieć dostępu do pliku. Zasadniczo dobrym pomysłem jest zamykanie plików po zakończeniu ich używania.
Gdy plik znajdzie się w twoim programie jako lista ciągów, możesz zrobić, co zechcesz. Ta lista jest jak każda inna lista Pythonaa, dzięki czemu możesz przechodzić przez nią, sortować, dodawać elementy, usuwać elementy i tak dalej. Ciągi są jak inne ciągi, więc możesz je wydrukować, przekonwertować na int lub float (jeśli zawierają liczby), użyć ich jako etykiet w GUI lub zrobić coś innego, co zrobiłbyś za pomocą łańcucha. Czytanie jednej linii na raz metodą readlines() odczytuje wszystkie wiersze pliku, aż do końca pliku. Jeśli chcesz czytać tylko jedną linię na raz, możesz użyć metody readline(), tak jak poniżej: To spowoduje przeczytanie pierwszej linii pliku. Jeśli ponownie użyjesz readline() w tym samym programie, Python pamięta, gdzie był. Więc za drugim razem użyjesz drugiej linii pliku. Następna lista pokazuje przykład tego.
Listing 23.2 Używanie readline () więcej niż raz
my_file = open('notes.txt', 'r')
first_line = my_file.readline()
second_line = my_file.readline()
print "first line = ", first_line
print "second line = ", second_line
my_file.close()
The output of that program would look like this:
>>>================== RESTART ====================
>>>
first line = Myć samochód
second line = Pościelić łóżko
Metoda readline() odczytuje tylko jedną linię na raz, więc nie umieszcza wyników na liście. Za każdym razem, gdy używasz readline(), otrzymujesz pojedynczy ciąg.
Wracając do początku
Jeśli używałeś readline () kilka razy i chcesz zacząć od początku pliku, możesz użyć metody seek (), takiej jak ta:
first_line = my_file.readline()
second_line = my_file.readline()
my_file.seek(0)
first_line_again = my_file.readline()
Metoda seek() sprawia, że Python przechodzi do dowolnego miejsca w pliku, który powiesz. Liczba w nawiasach to liczba bajtów od początku pliku. Więc ustawienie na 0 powoduje powrót do początku pliku.
Pliki tekstowe i pliki binarne
Wszystkie przykłady otwierania plików i czytania wierszy tekstu zakładają jedno: plik ma w sobie tekst! Pamiętaj, że tekst jest tylko jednym z rzeczy, które możesz przechowywać w pliku. Programiści gromadzą wszystkie inne rodzaje plików i nazywają je plikami binarnymi.
Istnieją dwa główne typy plików, które można otworzyć:
• Pliki tekstowe - zawierają w sobie tekst, litery, cyfry, znaki interpunkcyjne i niektóre znaki specjalne, takie jak znaki nowej linii.
• Pliki binarne - nie zawierają w nich tekstu. Mogą mieć muzykę, obrazy lub jakieś dane, ale ponieważ nie mają tekstu, nie mają też linii, ponieważ nie ma znaków nowej linii.
Oznacza to, że nie możesz użyć readline() lub readlines() w pliku binarnym. Jeśli na przykład spróbujesz odczytać "linię" z pliku .wav, nie wiesz, co otrzymasz. Najprawdopodobniej dostaniesz całą masę dziwactwa, które wygląda tak:
Na początku pliku .wav to jest coś, co wygląda jak tekst, ale potem staje się szalone. Ponieważ plik .wav nie zawiera w sobie tekstu, ma dźwięk. Metody readline() i readlines() służą tylko do odczytu plików tekstowych. W większości przypadków, jeśli chcesz użyć pliku binarnego, będziesz używał czegoś takiego jak Pygame lub innego modułu do załadowania pliku:
pygame.mixer.music.load ('bg_music.mp3')
W takim przypadku Pygame dba o otwarcie pliku i odczyt danych binarnych (w tym przykładzie jest to muzyka). Ta książka nie obejmuje sposobu przetwarzania plików binarnych. Ale po prostu wiesz, jak to wygląda możesz otworzyć plik binarny, dodając b do trybu plików, w ten sposób:
my_music_file = open ('bg_music.mp3', 'rb')
Część "rb" oznacza, że otwierasz plik do odczytu w trybie binarnym.
W ostatnich kilku sekcjach nauczyłeś się, jak uzyskać informacje z pliku do swojego programu, co nazywa się odczytaniem pliku. Następnie dowiesz się, jak przekazywać informacje ze swojego programu do pliku. Nazywa się to zapisywaniem pliku.
Zapis do pliku
Jeśli chcesz trwale zapisać niektóre informacje z programu, możesz je obejrzeć na ekranie i zapisać na kartce papieru. Ale to porażka korzystania z komputera! Lepszym pomysłem jest zapisanie informacji na dysku twardym, tak aby nawet wtedy, gdy program nie działa - w rzeczywistości, nawet gdy komputer jest wyłączony - dane są nadal dostępne i można je pobrać później. Zrobiłeś to już wiele, wiele razy. Za każdym razem, gdy zapisać raport dla szkoły, obraz, utwór lub program w Pythonie, przechowujesz go na dysku twardym.
Kiedy mieliśmy tylko papier! Nie było monitorów, drukarek ani nawet klawiatur. Kod "pisałeś", dziurkując karty. Następnie zasiliłeś ten stos kart w wielką maszynę, która zamieniłaby dziurkowane otwory w sygnały elektryczne, które komputer mógł zrozumieć. Czasami uzyskanie odpowiedzi zajęło dni. Chłopcze, to było takie bolesne!
Jak wspomniałem wcześniej, istnieją dwa sposoby umieszczania rzeczy w pliku:
• Pisanie - oznacza rozpoczęcie nowego pliku lub nadpisanie istniejącego.
• Dołączanie - oznacza to dodanie do istniejącego pliku i zachowanie tego, co już istnieje.
Aby napisać lub dołączyć do pliku, musisz najpierw otworzyć plik. Używasz funkcji open(), tak jak poprzednio, z tym wyjątkiem, że drugi parametr będzie inny:
• Do czytania używasz "r" jako trybu pliku:
my_file = open ('new_notes.txt', 'r')
• Do pisania używasz "w" jako trybu pliku:
my_file = open ('new_notes.txt', 'w')
• Do dołączania używasz "a" jako trybu plików:
my_file = open ('notes.txt', 'a')
Jeśli użyjesz "a" w trybie dodawania, nazwa pliku musi być taka, która już istnieje na dysku twardym, lub pojawi się błąd. Dzieje się tak dlatego, że dołączenie służy do dodawania do istniejącego pliku.
Jeśli użyjesz "w" do trybu zapisu, istnieją dwie możliwości:
• Jeśli plik już istnieje, wszystko, co znajduje się w pliku, zostanie utracone i zastąpione tym, co tam napiszesz.
• Jeśli plik nie istnieje, zostanie utworzony nowy plik o tej nazwie, a cokolwiek napiszesz, trafi do nowego pliku.
Spójrzmy na kilka przykładów.
Dołączanie do pliku
Najpierw weźmiemy utworzony wcześniej plik notes.txt i do niego coś dołączymy. Dodajmy kolejną linię, która mówi "Wydawaj zasiłek". Gdybyście uważnie przyjrzeli się przykładowi readlines (), moglibyście zauważyć, że na końcu ostatniej linii nie ma n, nie ma nowej linii. Więc musimy dodać jeden, a następnie dodać nasz nowy ciąg. Aby napisać łańcuchy do pliku, używamy metody write (), takiej jak ta.
Listing 23.3 Korzystanie z trybu dołączania
todo_list = open('notes.txt', 'a') <- Otwórz plik , w trybie append
todo_list.write('\nSpend allowance') <- Dodajemy nasz string na końcu
todo_list.close() <- Zamykamy plik
Kiedy odczytywaliśmy pliki, powiedziałem, że powinieneś zamknąć plik, gdy skończysz. Ale jeszcze ważniejsze jest użycie close(), gdy skończysz pisać. To dlatego, że zmiany nie są zapisywane w pliku, dopóki go nie zamkniesz (). Po uruchomieniu programu w listingu 22.3 otwórz plik notes.txt za pomocą Notatnika (lub dowolnego innego edytora tekstu) i zobacz, co w nim jest. Pamiętaj, aby zamknąć Notatnik, gdy skończysz.
Zapis do pliku
Wypróbujmy teraz przykład zapisu do pliku przy użyciu trybu zapisu. Otworzymy plik, który nie znajduje się na dysku twardym. Wpisz program na tej liście i uruchom go.
Listing 23.4 Używanie trybu zapisu w nowym pliku
new_file = open ("my_new_notes.txt", "w")
new_file.write ("Zjedz kolację \n")
new_file.write ("Graj w piłkę nożną \n")
new_file.write ("Idź spać")
new_file.close ()
Skąd wiesz, że to zadziałało? Sprawdź w folderze, w którym zapisałeś program z listingu 23.4. Powinieneś zobaczyć plik o nazwie my_new_notes.txt. Możesz otworzyć ten plik w Notatniku, aby zobaczyć, co w nim jest. Powinieneś to zobaczyć:
Zjedz kolację
Graj w piłkę nożną
Idź spać
W tym programie utworzyłeś plik tekstowy i zapisałeś w nim jakiś tekst. Ten tekst jest na dysku twardym i pozostanie tam na zawsze - lub przynajmniej tak długo, jak dysk twardy będzie działał - chyba że go usuniesz. Masz więc sposób na trwałe przechowywanie danych ze swoich programów. Teraz twoje programy mogą pozostawić trwały ślad na świecie (lub przynajmniej na dysku twardym). Wszystko, co musisz zachować, gdy program się zatrzyma, a komputer zostanie wyłączony, możesz umieścić w pliku. Zobaczmy, co się stanie, jeśli użyjemy trybu zapisu na pliku, który jest już na dysku twardym. Pamiętasz nasz plik o nazwie notes.txt? Jeśli uruchomiłeś program na listingu 23.3, wygląda to tak:
Myć samochód
Pościelić łóżko
Odbierz zasiłek
Wydać zasiłek
Otwórzmy ten plik w trybie zapisu i napiszmy go, aby zobaczyć, co się stanie. Oto kod.
Listing 23.5 Używanie trybu zapisu w istniejącym pliku
the_file = open ('notes.txt', 'w')
the_file.write ("Obudź się \n")
the_file.write ("Oglądaj kreskówki")
the_file.close
Uruchom ten kod, a następnie otwórz plik notes.txt w Notatniku, aby zobaczyć, co zawiera. Powinieneś to zobaczyć:
Obudź się
Oglądaj kreskówki
Rzeczy, które były wcześniej w notes.txt, zniknęły. Został on zastąpiony przez nowe rzeczy z programu na listingu 23.5.
Zapis do pliku za pomocą print
W ostatniej sekcji napisaliśmy do pliku za pomocą write(). Możesz także użyć drukowania do zapisu do pliku. Nadal musisz otworzyć plik w trybie zapisu lub dodawania, ale potem możesz napisać do pliku za pomocą print, jak poniżej:
my_file = open ("new_file.txt", "w")
print >> my_file, "Cześć, sąiad!"
mój_plik.close()
Dwa symbole > (zwane czasem szewronami) mówią print , aby wysłał swoje wyjście do pliku zamiast na ekran. Nazywa się to wyjściem przekierowującym. Czasem wygodniej jest używać print niż write(), ponieważ print robi takie rzeczy, jak automatyczna konwersja liczb na łańcuchy, i tak dalej. Możesz zdecydować, czy użyć print, czy write (), aby umieścić tekst w pliku.
Zapisywanie rzeczy w plikach: pickle
W pierwszej części rozmawialiśmy o czytaniu i pisaniu do/z plików tekstowych. Pliki tekstowe to jeden ze sposobów przechowywania rzeczy na dysku twardym. Ale co, jeśli chcesz przechowywać coś w rodzaju listy lub obiektu? Czasami elementy na liście mogą być ciągami znaków, ale nie zawsze. A co z przechowywaniem rzeczy takich jak przedmioty? Możesz być w stanie przekonwertować wszystkie właściwości obiektu na łańcuchy i zapisać je w pliku tekstowym, ale wtedy będziesz musiał zrobić coś przeciwnego, aby przejść z pliku do obiektu. To może się skomplikować. Na szczęście Python ułatwia sposób przechowywania takich rzeczy, jak listy i obiekty. Jest to moduł Pythona zwany pickle. To zabawna nazwa, ale pomyśl o tym: marynowanie to sposób na zachowanie żywności, dzięki czemu możesz z niej korzystać później. W Pythonie "marynujesz" swoje dane, abyś mógł je zapisać na dysku i użyć później. Ma to sens!
Marynowanie
Powiedzmy, że mamy listę zawierającą różne rzeczy, takie jak:
my_list = ['Fred', 73, 'Cześć', 81.9876e-13]
Aby użyć pikli, najpierw musisz zaimportować moduł pikli:
import pickle
Następnie, aby coś "marynować", na przykład listę, używasz funkcji dump(). (Łatwo to zapamiętać, jeśli myślisz o wyrzuceniu pikli do słoika). Funkcja dump () wymaga obiektu pliku i wiesz, jak zrobić jedną z nich:
pickle_file = open ('my_pickled_list.pkl', 'w')
Otwieramy go do pisania za pomocą "w", ponieważ będziemy przechowywać coś w tym pliku. Możesz wybrać dowolne imię i rozszerzenie. Wybrałem .pkl jako rozszerzenie, skrót od "pickle". Następnie dump() naszą listę do pliku pickle:
pickle.dump (my_list, pickle_file)
Cały proces wygląda tak.
Listing 23.6 Używanie pikli do przechowywania listy do pliku
import pickle
my_list = ['Fred', 73, 'Cześć', 81.9876e-13]
pickle_file = open ('my_pickled_list.pkl', 'w')
pickle.dump (my_list, pickle_file)
pickle_file.close ()
Możesz użyć tej samej metody do przechowywania dowolnej struktury danych do pliku. Ale co z powrotem? To jest następne.
Unpickling
W prawdziwym życiu, kiedy coś marynujesz, pozostaje marynowane. Nie możesz tego cofnąć. Ale w Pythonie, gdy "zachowujesz" niektóre dane przez wytrawianie, możesz również odwrócić proces i odzyskać dane w taki sposób, w jaki było. Funkcją "rozpakowywania" jest load(). Dajesz mu obiekt pliku dla pliku, który zawiera marynowane dane, i dajesz dane z powrotem w oryginalnej postaci. Spróbujmy. Jeśli uruchomiłeś program na liście 23.6, powinieneś mieć plik o nazwie my_pickled_list.pkl w tym samym miejscu, w którym przechowujesz swoje programy. Teraz wypróbuj program na następnej liście i sprawdź, czy otrzymasz tę samą listę.
Listing 22.7 Rozpuszczanie przy użyciu load ()
import pickle
pickle_file = open('my_pickled_list.pkl', 'r')
recovered_list = pickle.load(pickle_file)
pickle_file.close()
print recovered_list
Powinieneś otrzymać wyjście, które wygląda tak:
['Fred', 73, 'Hello there', 8.1987599999999997e-012]
Wygląda na to, że nieudolna praca! Odzyskaliśmy te same rzeczy, które wybraliśmy. Zapis E wygląda trochę inaczej, ale jest to ten sam numer, co najmniej do 16 miejsc po przecinku. Różnica polega na błędzie zaokrąglania. W następnej sekcji wykorzystamy to, czego się dowiedzieliśmy, o wprowadzaniu i wyprowadzaniu plików, aby pomóc nam w stworzeniu nowej gry.
Znowu czas gry - Wisielec
Dlaczego mamy grę w rozdziale o plikach? Cóż, jedną z rzeczy, które sprawiają, że gra w Wisielca jest interesująca, jest ładna, duża lista słów, z których można wybierać puzzle. Najprostszym sposobem na to jest odczytanie go z pliku. Użyjemy również PyQt do tej gry, aby pokazać, że używanie Pygame nie jest jedynym sposobem tworzenia gier graficznych. Nie będę wyjaśniać tego programu w sposób tak szczegółowy, jak niektóre inne programy. Do tej pory powinieneś być w stanie spojrzeć na kod i dowiedzieć się, jak większość z nich działa samodzielnie. Podam ci tylko kilka wskazówek, które pomogą ci w tym.
GUI Wisielca
Główny GUI dla naszego programu Wisielec wygląda następująco:
Pokazuje wszystkie części powieszonego człowieka, ale kiedy program się uruchomi, zaczniemy od ukrycia wszystkich jego części. Gdy gracz odgadnie niewłaściwą literę, ujawnimy część ludzika. Jeśli cały ludzik zostanie pociągnięty, to koniec gry! Gdy gracz odgadnie literę, program sprawdza, czy litera znajduje się w tajnym słowie. Jeśli tak, list zostaje ujawniony. Pośrodku okna gracz widzi wszystko, co do tej pory odgadł. Gracz może również spróbować odgadnąć słowo w dowolnym momencie.
Oto podsumowanie działania programu.
Na początku program wykonuje następujące czynności:
• Ładuje listę słów z pliku
• Usuwa znaki nowej linii z końca każdej linii
• Sprawia, że wszystkie części ludzika są niewidoczne
• Losowo wybiera słowo z listy słów
• Pokazuje tę samą liczbę kresek, ile jest liter w tajnym słowie
Gdy gracz kliknie Zgadnij! przycisk, program robi te rzeczy:
• Sprawdza, czy zgadywanie jest pojedynczą literą czy słowem
• Jeśli jest to litera:
• Sprawdza tajne słowo, aby zobaczyć, czy zawiera literę
• Jeśli odgadnięcie gracza jest prawidłowe, pokazuje miejsca, w których pojawia się litera, zastępując myślnik literą
• Jeśli odgadnięcie gracza jest błędne, ujawnia część mężczyzny
• Dodaje zgadywaną literę do ekranu Poprzednie zgadywania
• Sprawdza, czy gracz ukończył słowo (odgadł wszystkie litery)
• Jeśli to słowo:
• Sprawdza, czy domysł gracza jest prawidłowy
• Jeśli tak, wyświetla okno dialogowe z informacją o wygranej! i rozpoczyna nową grę
• Sprawdzanie, czy gracz nie ma zakrętów - jeśli tak, wyświetla okno dialogowe z informacją "Utraciłeś" i pokazuje, jakie było tajne słowo
Pobieranie słów z listy słów
To jest część o plikach, więc spójrzmy na część programu, która pobiera listę słów. Kod wygląda tak:
f = open("words.txt", 'r')
self.lines = f.readlines()
for line in self.lines:
line.strip() <- Usuwa newline z każdej linii
f.close()
Plik words.txt jest tylko plikiem tekstowym, więc możemy go odczytać za pomocą readlines(). Następnie, aby wybrać słowo z listy, używamy funkcji random.choice() w następujący sposób:
self.currentword = random.choice (self.lines)
Ujawnienie ludzika
Istnieje kilka sposobów, dzięki którym moglibyśmy śledzić, które części człowieka są już ujawnione, a które ujawnić dalej. Postanowiliśmy użyć pętli. To wygląda tak:
def wrong(self):
self.pieces_shown += 1
for i in range(self.pieces_shown):
self.pieces[i].setHidden(False)
if self.pieces_shown == len(self.pieces):
message = " Przegrałeś. To było słowo " + self.currentword
QtGui.QMessageBox.warning(self,"Hangman",message)
self.new_game()
Używamy self.pieces_shown, aby śledzić, ile kawałków kata pokazujemy. Jeśli pokazane są wszystkie elementy, używamy okna dialogowego, aby powiedzieć graczowi, że przegrał.
Sprawdzanie zgadywania litery
Jedną z najtrudniejszych części tego programu jest sprawdzenie zgadywanej litery gracza, aby sprawdzić, czy pojawia się w tajnym słowie. To, co sprawia, że jest trudne, jest to, że litera może pojawić się więcej niż raz w słowie. Na przykład, jeśli tajne słowo to lever, a gracz zgaduje e, musisz ujawnić zarówno drugą, jak i czwartą literę, ponieważ obie to e. Mamy kilka funkcji, które pomagają nam to zrobić. Funkcja find_letters () wyszukuje wszystkie miejsca, w których dana litera pojawia się w słowie, i zwraca listę tych pozycji. Na przykład, dla litery e i dźwigni słowa, powróci [1, 3], ponieważ litera e pojawia się przy indeksie 1 i indeksie 3 w ciągu. (Pamiętaj, że indeksy zaczynają się od 0.) Oto kod:
def find_letters(letter, a_string):
locations = []
start = 0
while a_string.find(letter, start, len(a_string)) != -1: <- Sprawdza, gdzie pojawia się litera
location = a_string.find(letter, start, len(a_string))
locations.append(location)
start = location + 1
return locations
Funkcja replace_letters() pobiera listę z find_letters() i zastępuje myślniki w tych pozycjach poprawną literą. W naszym przykładzie (litera e w "lever") zastąpiłaby ----- opcją -e-e-. Pokazuje gracza, w którym na słowie pojawiają się poprawnie odgadnięte litery, a resztę pozostawia jako kreski. Oto kod:
def replace_letters(string, locations, letter):
new_string = ''
for i in range (0, len(string)):
if i in locations:
new_string = new_string + letter
else:
new_string = new_string + string[i]
return new_string
Następnie, gdy gracz zgaduje literę, używamy dwóch zdefiniowanych przez nas funkcji: find_letters () i replace_letters ():
if len(guess) == 1: <-Czy zgadujemy jedną literę?
if guess in self.currentword: <- Sprawdza, czy litera jest słowem
locations = find_letters(guess, self.currentword) <- Sprawdza, gdzie pojawia się litera
self.word.setText(replace_letters(str(self.word.text()),
locations,guess))
if str(self.word.text()) == self.currentword:
self.win()
else:
self.wrong()
Całkowity program składa się z około 95 linii kodu oraz kilku pustych linii, aby wszystko wyglądało ładnie. Listing 23.8 pokazuje cały program, z kilkoma notatkami wyjaśniającymi różne sekcje. Kod znajduje się w folderze przykładów Wisielca na komputerze, jeśli korzystasz z instalatora, a także na stronie internetowej. Zawiera hangman.py, hangman.ui i words.txt. Pamiętaj, jak wspomnieliśmy w części 20, jeśli jesteś na Macu, musisz otworzyć hangman.ui w Qt Designer i odznaczyć właściwość nativeMenuBar dla obiektu paska menu.
Listing 23.8 Cały program hangman.py
import sys
from PyQt4 import QtCore, QtGui, uic
import random
form_class = uic.loadUiType("hangman.ui")[0]
def find_letters(letter, a_string):
locations = []
start = 0
while a_string.find(letter, start, len(a_string)) != -1:
location = a_string.find(letter, start, len(a_string))
locations.append(location)
start = location + 1
return locations
def replace_letters(string, locations, letter):
new_string = ''
for i in range (0, len(string)):
if i in locations:
new_string = new_string + letter
else:
new_string = new_string + string[i]
return new_string
def dashes(word):
letters = "abcdefghijklmnopqrstuvwxyz"
new_string = ''
for i in word:
if i in letters:
new_string += "-"
else:
new_string += i
return new_string
class MyWidget(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.btn_guess.clicked.connect(self.btn_guess_clicked)
self.actionExit.triggered.connect(self.menuExit_selected)
self.pieces = [self.head, self.body, self.leftarm, self.leftleg,
self.rightarm, self.rightleg]
self.gallows = [self.line1, self.line2, self.line3, self.line4] <- Części szubienicy
self.pieces_shown = 0
self.currentword = ""
f=open("words.txt", 'r')
self.lines = f.readlines()
f.close()
self.new_game()
def new_game(self):
self.guesses.setText("")
self.currentword = random.choice(self.lines) <- Losowo wybierz słowo z listy
self.currentword = self.currentword.strip()
for i in self.pieces:
i.setFrameShadow(QtGui.QFrame.Plain)
i.setHidden(True)
for i in self.gallows:
i.setFrameShadow(QtGui.QFrame.Plain)
self.word.setText(dashes(self.currentword)) <- Wywołuje funkcję zastępowania liter myślnikami
self.pieces_shown = 0
def btn_guess_clicked(self):
guess = str(self.guessBox.text())
|
if str(self.guesses.text()) != "":
self.guesses.setText(str(self.guesses.text())+", "+guess)
else:
self.guesses.setText(guess)
if len(guess) == 1:
if guess in self.currentword:
locations = find_letters(guess, self.currentword)
self.word.setText(replace_letters(str(self.word.text()),
locations,guess))
if str(self.word.text()) == self.currentword:
self.win()
else:
self.wrong()
else:
if guess == self.currentword:
self.win()
else:
self.wrong()
self.guessBox.setText(**)
def win(self):
QtGui.QMessageBox.information(self,"Hangman","You win!")
self.new_game()
def wrong(self):
self.pieces_shown += 1
for i in range(self.pieces_shown):
self.pieces[i].setHidden(False)
if self.pieces_shown == len(self.pieces):
message = "You lose. The word was " + self.currentword
QtGui.QMessageBox.warning(self,"Hangman", message)
self.new_game()
def menuExit_selected(self):
self.close()
app = QtGui.QApplication(sys.argv)
myapp = MyWidget(None)
myapp.show()
app.exec_()
Dla uproszczenia nasz program Hangman używa tylko małych liter. Lista słów, którą udostępniamy, ma tylko małe litery, a użytkownik musi wpisać jej przypuszczenia małymi literami. Funkcja dashes () b zastępuje litery myślnikami na początku nowej gry. Ale nie zastępuje interpunkcji, jak apostrofy. Więc jeśli słowo nie brzmi, gracz zobaczy - - - - - "-. Zachęcam do samodzielnego tworzenia tego programu. Możesz zbudować GUI w Qt Designer. Nie ma znaczenia, czy nie wygląda dokładnie tak samo, jak wersja, którą tutaj mam. Upewnij się tylko, że spojrzysz na kod, aby zobaczyć, jakich nazw używać do składników. Nazwy w kodzie muszą pasować do nazw w pliku .ui. Wpisz kod, jeśli możesz. Uruchom program i zobacz, jak to działa. A jeśli spróbujesz czegoś innego, spróbuj! Baw się dobrze, baw się z nim i eksperymentuj. To jedna z najbardziej zabawnych i satysfakcjonujących części programowania, i to właśnie nauczysz się najbardziej.
Czego się nauczyłeś?
• Czym jest plik
• Jak otwierać i zamykać pliki
• Różne sposoby otwierania pliku: czytanie, pisanie i dołączanie
• Różne sposoby zapisywania rzeczy do pliku: write () lub print >>
• Jak używać pikli do zapisywania list i obiektów (i innych struktur danych Pythona) do pliku
• Dużo o folderach (zwanych także katalogami), lokalizacjach plików i ścieżkach
Stworzyliśmy również grę Wisielec, która wykorzystywała dane z pliku, aby uzyskać listę słów.
Sprawdź swoją wiedzę
1 Rodzaj obiektu w Pythonie, który jest używany do pracy z plikami, nazywa się _______.
2 Jak utworzyć obiekt pliku?
3 Jaka jest różnica między obiektem pliku a nazwą pliku?
4 Co należy zrobić z plikiem po zakończeniu czytania lub pisania?
5 Co się stanie, jeśli otworzysz plik w trybie dołączania, a następnie napiszesz coś do pliku?
6 Co się stanie, jeśli otworzysz plik w trybie zapisu, a następnie napiszesz coś do pliku?
7 Jak zacząć czytać początek pliku po przeczytaniu jego części?
8 Jaka funkcja pickle jest używana do zapisania obiektu Python do pliku?
9 Jaka metoda piklowania jest używana do "usunięcia" obiektu - aby pobrać go z pliku pikli i umieścić go z powrotem w zmiennej Pythona?
Wypróbuj to
1 Zrób program do tworzenia głupich zdań. Każde zdanie powinno mieć co najmniej cztery części, takie jak ta:
__________ ___________ ____________ _____________
(przymiotnik) (rzeczownik) (fraza czasownikowa) (wyrażenie przysłówkowe)
Program powinien utworzyć zdanie, losowo wybierając przymiotnik, rzeczownik, frazę czasownika i frazę przysłówkową. Słowa będą przechowywane w plikach, a do ich tworzenia możesz użyć Notatnika. Najprostszym sposobem na działanie tego programu jest posiadanie jednego pliku dla każdej z czterech grup słów, ale możesz to zrobić, jak chcesz. Oto kilka pomysłów na rozpoczęcie działalności, ale jestem pewien, że wymyślisz własne:
• Przymiotniki: szalony, głupi, nieśmiały, głupkowaty, zły, leniwy, uparty, fioletowy
• Rzeczowniki: małpa, słoń, rowerzysta, nauczyciel, autor, hokeista
• Zwroty czasowników: grałem na ukulele, tańczyłem dżig, czesali włosy, trzepotali uszami
• Wyrażenia przysłówkowe: na stole, w sklepie spożywczym, pod prysznicem, po śniadaniu, z miotłą
Oto kolejny przykładowy przykład: "Leniwy autor przeczesał włosy miotłą".
2 Napisz program, który prosi użytkownika o podanie jej imienia, wieku, ulubionego koloru i ulubionego jedzenia. Niech program zapisze wszystkie cztery elementy do pliku tekstowego, każdy w osobnej linii.
3 Zrób to samo, co w pytaniu nr 2, ale użyj pikli, aby zapisać dane w pliku. (Podpowiedź: będzie to łatwe, jeśli umieścisz dane na liście).
Jedną z najbardziej zabawnych rzeczy w grach jest to, że nigdy nie wiesz, co się stanie. Gry są nieprzewidywalne. Są przypadkowe. To ta losowość czyni je interesującymi. Jak już widzieliście, komputery mogą symulować losowe zachowanie. W naszym programie o odgadywanie liczby (w Części 1) użyliśmy losowego modułu do wygenerowania losowej liczby całkowitej, którą użytkownik musiał odgadnąć. Komputery mogą również symulować losowe zachowanie rzutu kostką lub tasowanie talii kart. Umożliwia to tworzenie gier komputerowych z kartami lub kostkami (lub innymi przypadkowo zachowującymi się obiektami). Na przykład prawie wszyscy próbowali grać w pasjansa w systemie Windows, który jest grą karcianą, w której program losowo tasuje karty przed każdą grą. Popularny jest również komputerowy backgammon, który wykorzystuje dwie kości. W tej części dowiesz się, jak używać losowego modułu do tworzenia wygenerowanych komputerowo kości i talii kart, z którymi możesz grać w gry. Przyjrzymy się również, w jaki sposób można wykorzystać wygenerowane komputerowo zdarzenia losowe do zbadania idei prawdopodobieństwa, czyli tego, jak prawdopodobnie coś się wydarzy.
Co jest losowość?
Zanim zaczniemy mówić o tym, jak sprawić, by programy miały losowe zachowanie, powinieneś zrozumieć, co tak naprawdę oznacza "losowy". Weźmy przykład rzucania monetą. Jeśli wyrzucisz monetę w powietrze i pozwoli jej wylądować, wyląduje ona zarówno jako orzeł lub może jako reszka. W przypadku zwykłej monety szanse na zdobycie orła są takie same jak szanse na zdobycie reszki. Czasem dostaniesz reszkę, czasem orła. Przy każdym rzucie nie wiesz, co dostaniesz. Ponieważ wyniku rzutu nie można przewidzieć, mówimy, że jest losowy. Rzucanie monetą jest przykładem zdarzenia losowego. Jeśli rzucisz monetą wiele razy, prawdopodobnie otrzymasz mniej więcej tyle samo reszek co orłów. Ale nigdy tak naprawdę nie możesz być pewien. Jeśli rzucisz monetą 4 razy, możesz zdobyć 2 reszki i 2 orły. Ale możesz zdobyć 3 reszki i 1 orła, 1 reszkę i 3 orły lub nawet 4 reszki (lub orły) z rzędu. Jeśli rzucisz monetą 100 razy, możesz zdobyć 50 reszek. Ale możesz zdobyć 20, 44, 67 lub nawet 100 rzutów z góry! To bardzo mało prawdopodobne, ale może się zdarzyć. Chodzi o to, że każde zdarzenie jest losowe. Chociaż może istnieć jakiś wzór, jeśli wykonałeś wiele rzutów, każdy rzut ma taką samą szansę na zdobycie reszki lub orła. Innym sposobem powiedzenia tego jest to, że moneta nie ma pamięci. Więc nawet jeśli rzuciłeś 99 reszek z rzędu i uważasz, że uzyskanie 100 reszek z rzędu jest prawie niemożliwe, następny rzut nadal ma 50 procent szans na to, że stanie się reszką. To właśnie oznacza przypadkowe środki. Zdarzenie losowe to zdarzenie z dwoma lub więcej możliwymi wynikami, w którym nie można przewidzieć, który wynik się wydarzy. Wynikiem może być kolejność kart w potasowanej talii lub liczba miejsc, które pokażą się, gdy rzucisz kośćmi lub po której stronie moneta wyląduje.
Rzut kostką
Prawie każdy grał w grę przy użyciu kości. Niezależnie od tego, czy jest to Monopol, czy jakaś inna gra, toczenie kości jest jednym z najczęstszych sposobów generowania losowych zdarzeń w grze. Symulacje kości w programie są bardzo łatwe, a moduł random Pythona ma kilka sposobów, aby to zrobić. Jedną z nich jest funkcja randint(), która wybiera losową liczbę całkowitą. Ponieważ liczba plam po bokach kości jest liczbą całkowitą (1, 2, 3, 4, 5 i 6), przetoczenie pojedynczej kostki można by symulować w ten sposób:
import random
sides = [1, 2, 3, 4, 5, 6]
die_1 = random.choice(sides)
Zrobiłoby to dokładnie to samo, co poprzedni przykład. Funkcja choice () losowo wybiera element z listy. W tym przypadku lista zawiera liczby od 1 do 6.
Więcej niż jedna kostka
Co zrobić, jeśli chcesz symulować rzucanie dwóch kości? Jeśli chcesz dodać dwie kości, aby uzyskać sumę, możesz pomyśleć o zrobieniu tego w ten sposób:
two_dice = random.randint (2, 12)
Przecież suma dwóch kości może wynosić od 2 do 12, prawda? No tak i nie. Otrzymasz losową liczbę od 2 do 12, ale nie w taki sam sposób, jak zsumowanie dwóch losowych liczb od 1 do 6. To, co robi ta linia kodu, to rzucanie jedną dużą, 11-stronną kostką, a nie dwiema 6-stronnymi kośćmi. Ale jaka jest różnica? To wchodzi w temat zwany prawdopodobieństwem. Najłatwiej zobaczyć różnicę, wypróbować i zobaczyć. Rzućmy kostką wiele razy i obserwujmy, ile razy pojawia się każda suma. Zrobimy to za pomocą pętli i listy. Pętla rzuci kośćmi, a lista będzie śledzić, ile razy pojawia się każda suma. Zacznijmy od pojedynczej 11-stronnej kostki, jak pokazano na tej liście.
Listing 24.1 Toczenie pojedynczej 11-stronnej kostki 1000 razy
import random
totals = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] <- Lista ma 13 pozycji, z indeksem od 0 do 12 (1)
for i in range(1000):
dice_total = random.randint(2, 12)
totals[dice_total] += 1 <- Dodaje 1 do liczby całkowitej (2)
for i in range (2, 13):
print "total", i, "came up", totals[i], "times"
(1) Listing ma indeksy od 0 do 12, ale nie użyjemy dwóch pierwszych, ponieważ nie obchodzi nas suma 0 lub 1 - nigdy się nie zdarzą. (2) Kiedy otrzymamy wynik, dodajemy 1 do tego elementu listy. Jeśli suma wynosi 7, dodajemy jedną do sumy [7]. Tak więc sumy [2] to liczba 2s, którą otrzymaliśmy, sumy [3] to liczba 3s, którą otrzymaliśmy, i tak dalej.
Jeśli uruchomisz ten kod, powinieneś otrzymać coś takiego:
total 2 came up 95 times
total 3 came up 81 times
total 4 came up 85 times
total 5 came up 86 times
total 6 came up 100 times
total 7 came up 85 times
total 8 came up 94 times
total 9 came up 98 times
total 10 came up 93 times
total 11 came up 84 times
total 12 came up 99 times
Jeśli spojrzysz na sumy, zobaczysz, że wszystkie liczby pojawiły się mniej więcej tyle samo, między 80 a 100. Nie pojawiły się dokładnie tyle samo razy, ponieważ liczby są losowe, ale są zamknij i nie ma wyraźnego wzorca, że niektóre liczby pojawiają się znacznie częściej niż inne. Spróbuj uruchomić program kilka razy, aby się upewnić. Lub spróbuj zwiększyć liczbę pętli do 10 000 lub 100 000. Teraz spróbujmy tego samego za pomocą dwóch 6-stronnych kości. Poniższy kod to robi.
Listing 24.2 Toczenie dwóch 6-stronnych kości 1000 razy
import random
totals = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for i in range(1000):
die_1 = random.randint(1, 6)
die_2 = random.randint(1, 6)
dice_total = die_1 + die_2
totals[dice_total] += 1
for i in range (2, 13):
print "total", i, "came up", totals[i], "times"
Jeśli uruchomisz kod , powinieneś uzyskać dane wyjściowe wyglądające mniej więcej tak:
total 2 came up 22 times
total 3 came up 61 times
total 4 came up 93 times
total 5 came up 111 times
total 6 came up 141 times
total 7 came up 163 times
total 8 came up 134 times
total 9 came up 117 times
total 10 came up 74 times
total 11 came up 62 times
total 12 came up 22 times
Zauważ, że najwyższa i najniższa liczba pojawiła się rzadziej, a środkowe liczby, takie jak 6 i 7, pojawiły się najczęściej. To różni się od tego, co stało się z pojedynczą 11-stronną kością. Jeśli zrobimy to wiele razy, a następnie obliczymy procent czasu, w którym wystąpi pewna suma, wygląda to tak:
Jeśli wykreślimy wykres tych liczb, wygląda to tak:
Dlaczego się różnią? Powód dotyczy dość dużego tematu prawdopodobieństwa. Zasadniczo bardziej prawdopodobne jest, że środkowe liczby pojawią się z dwoma kośćmi, ponieważ istnieje więcej sposobów, w jakie mogą się zdarzyć środkowe sumy przy dwóch kościach. Kiedy rzucisz dwoma kośćmi, może się zdarzyć wiele różnych kombinacji. Oto ich lista z ich sumami:
Istnieje 36 możliwych kombinacji. Teraz sprawdź, ile razy pojawia się każda suma:
• Całkowita liczba 2 pojawia się 1 raz.
• Całkowita liczba 3 pojawia się 2 razy.
• Łącznie 4 pojawia się 3 razy.
• Łącznie 5 pojawia się 4 razy.
• Łącznie 6 pojawia się 5 razy.
• Całkowita liczba 7 pojawia się 6 razy.
• Łącznie 8 pojawia się 5 razy.
• Łącznie 9 pojawia się 4 razy.
• Łącznie 10 pojawia się 3 razy.
• Łącznie 11 pojawia się 2 razy.
• Łącznie 12 pojawia się 1 raz.
Oznacza to, że istnieje więcej sposobów rzucenia 7 niż 2. Dla 7 możesz rzucić 1 + 6, 2 + 5, 3 + 4, 4 + 3, 5 + 2 lub 6 + 1. W przypadku 2 jedynym sposobem uzyskania tego jest rzucenie 1 + 1. Więc ma sens, że jeśli rzucimy kostką kilka razy, powinniśmy oczekiwać więcej 7-ek niż 2-jek. I to właśnie mamy z naszego programu z dwoma kostkami. Używanie programów komputerowych do generowania zdarzeń losowych jest naprawdę dobrym sposobem na eksperymentowanie z prawdopodobieństwem i zobaczenie, co dzieje się w wielu próbach. To by ci zajęło długi czas, aby rzucić prawdziwą parę kostek 1000 razy i zapisać wyniki. Ale program komputerowy może zrobić to samo w ułamku sekundy!
Dziesięć z rzędubr>
Zanim przejdziemy dalej, zróbmy jeszcze jeden eksperyment z prawdopodobieństwem. Kilka stron temu rozmawialiśmy o rzuceniu monety i o tym, jak prawdopodobne byłoby zdobycie kilku reszek z rzędu. Dlaczego nie próbujemy eksperymentu, aby zobaczyć, jak często otrzymujemy 10 reszek z rzędu? Nie zdarzy się to zbyt często, więc będziemy musieli wykonać wiele rzutów monetą, zanim to zobaczymy. Dlaczego nie spróbujemy 1,000,000! Z prawdziwą monetą, która zajęłaby…długi czas.
Gdybyś mógł wykonać jeden rzut monetą co 5 sekund, byłoby to 12 na minutę lub 720 na godzinę. Jeśli możesz robić rzuty monetą przez 12 godzin dziennie (w końcu wciąż musisz jeść i spać), możesz zrobić około 8 640 rzutów dziennie. Wykonanie miliona rzutów monetą zajęłoby około 115 dni (około 4 miesięcy). Ale z komputerem możemy to zrobić w kilka sekund. (Dobra, może kilka minut, ponieważ najpierw musimy reszki z rzędu.) Jednym ze sposobów jest użycie licznika. Licznik jest zmienną używaną do policzenia czegoś. Potrzebujemy dwóch liczników. Jeden będzie dotyczył liczby reszek, które rzuciliśmy z rzędu. Nazwijmy to heads_in_row. Drugi to tyle razy, ile razy otrzymamy 10 reszek z rzędu. Nazwijmy to dziesięć_ heads_in_row. Oto, co zrobi program:
• Za każdym razem, gdy dostajemy reszkę, licznik heads_in_row wzrośnie o 1.
• Gdy tylko otrzymamy orła, licznik heads_in_row powróci do 0.
• Kiedy licznik heads_in_row osiągnie 10, zwiększymy licznik ten_heads_in_row o 1 i ustawimy licznik heads_in_row z powrotem na 0, aby zacząć od nowa.
• Na koniec wydrukujemy komunikat mówiący, ile razy mamy 10 głów z rzędu.
Oto kod do tego.
Listing 24.3 Szukam 10 reszek z rzędu
from random import *
coin = ["Heads", "Tails"]
heads_in_row = 0
ten_heads_in_row = 0
for i in range (1000000): <- Odwraca monetę
heads_in_row += 1
else:
heads_in_row = 0
if heads_in_row == 10:
ten_heads_in_row += 1 <- Masz 10 reszek z rzędu, przyrosty licznika
heads_in_row = 0
print " Mamy 10 reszek z rzędu ", ten_heads_in_row, "razy."
Kiedy uruchomiłem ten program :
Mamy 10 reszek z rzędu 510 razy
Uruchomiłem program kilka razy, a jego liczba zawsze wynosiła około 500. Oznacza to, że w milionie rzutów monetami powinniśmy spodziewać się 10 reszek z rzędu około 500 razy lub mniej więcej raz na 2000 rzutów (1 000 000/500 = 2000).
Tworzenie talii kart
Innym przypadkowym wydarzeniem, które jest często używane w grach, jest rysowanie karty. To losowe, ponieważ talia jest tasowana, więc nie wiesz, która karta nadchodzi. I za każdym razem, gdy talia jest tasowana, kolejność jest inna. Przy rzucaniu kostkami i monetami mówiliśmy, że każde rzucie ma takie samo prawdopodobieństwo, ponieważ moneta (lub kostka) nie ma pamięci. Ale nie dotyczy to kart. W miarę dobierania kart z talii pozostaje mniej i mniej kart (w większości gier w każdym razie). Zmienia to prawdopodobieństwo wylosowania każdej z pozostałych kart.
Na przykład, kiedy zaczynasz z pełną talią, szanse na dobranie 4 serc wynoszą 1/52 lub około 2 procent. Dzieje się tak, ponieważ w talii znajdują się 52 karty i tylko 4 serca. Jeśli nadal rysujesz (i jeszcze nie narysowałeś 4 serc), gdy jesteś w połowie talii, szanse na uzyskanie 4 serc wynoszą 1/26 lub około 4 procent. Zanim dotrzesz do ostatniej karty, jeśli nadal nie narysowałeś 4 serc, szanse na to są 1/1 lub 100 procent. Jest pewne, że narysujesz następne 4 Serca, ponieważ jest to jedyna karta, która pozostała. Powodem, dla którego wam to wszystko mówię, jest pokazanie, że jeśli zamierzamy stworzyć grę komputerową przy użyciu talii kart, musimy śledzić, które karty zostały usunięte z talii, gdy idziemy dalej. Dobrym sposobem na zrobienie tego jest lista. Możemy zacząć od listy wszystkich 52 kart w talii i użyj funkcji random.choice() do losowego wybierania kart z listy. Gdy wybieramy każdą kartę, możemy ją usunąć z listy (talii) za pomocą remove().
Tasowanie talii
W prawdziwej grze karcianej tasujemy talię, co oznacza, że miksujemy karty, aby były w losowej kolejności. W ten sposób możemy po prostu wziąć górną karta, a będzie losowa. Ale dzięki funkcji random.choice() i tak będziemy wybierać losowo z listy. Nie musimy brać "górnej" karty, więc nie ma sensu "tasować" talii. Będziemy losowo wybierać kartę z dowolnego miejsca w talii. To jest jak wachlowanie kart i powiedzenie "Wybierz kartę, dowolną kartę!" To byłoby dość czasochłonne, aby wykonać kolejną turę w grze karcianej, ale to bardzo proste w programie komputerowym.
Obiekt karty
Będziemy używać listy do działania jako nasza "talia" kart. Ale co z samymi kartami? Jak powinniśmy przechowywać każdy z nich? Jako strinf? Liczba całkowita? Co musimy wiedzieć o każdej karcie?
W przypadku gier karcianych są to trzy rzeczy, które zazwyczaj musimy wiedzieć o karcie:
• Kolor - karo, kier, pik lub trefl.
• Ranga - as, 2, 3,
10, walet, królowa, król.
• Wartość - dla ponumerowanych kart (od 2 do 10) jest to zazwyczaj taka sama liczba jak ich ranga. Dla Waleta, Królowej i Króla zwykle jest to 10,
W przypadku asa może to być 1, 11 lub inna wartość, w zależności od gry
Musimy więc trzymać się tych trzech rzeczy i musimy trzymać je razem w jakimś pojemniku. Lista będzie działać, ale musimy pamiętać, który element był. Innym sposobem jest stworzenie obiektu "karty", który ma takie atrybuty:
card.suit
card.rank
card.value
To właśnie zrobimy. Dodamy również kilka dodatkowych atrybutów o nazwie suit_id i rank_id:
• suit_id to liczba od 1 do 4 dla koloru, gdzie 1 = karo, 2 = kier, 3 = pik, 4 = trefl
• rank_id to liczba od 1 do 13, gdzie
1 = As
2 = 2
3 = 3
…
10 = 10
11 = Jack
12 = Królowa
13 = Król
Powodem dodania tych dwóch atrybutów jest to, że możemy łatwo użyć zagnieżdżonej pętli for, aby utworzyć talię 52 kart. Możemy mieć wewnętrzną pętlę dla rangi (od 1 do 13) i zewnętrzną pętlę dla garnituru (od 1 do 4). Metoda __init __ () dla obiektu karty przyjmie suit_id i rank_id i utworzy inne atrybuty koloru, rangi i wartości. Ułatwia to również porównanie rangi dwóch kart, aby zobaczyć, która ma wyższą rangę. Powinniśmy dodać jeszcze dwa atrybuty, aby nasz obiekt był łatwy w użyciu w programie. Gdy program będzie musiał wydrukować kartę, będzie chciał wydrukować coś w rodzaju "4H" lub "4 serc". Dla kart twarzy będzie to coś w rodzaju "JD" lub "Jack of Diamonds". dodaj atrybuty short_name i long_name, aby program mógł łatwo wydrukować krótki lub długi opis karty. Zróbmy klasę dla karty do gry. Kod jest pokazany na następnej liście.
Listing 24.4 Klasa kart
class Card:
def __init__(self, suit_id, rank_id):
self.rank_id = rank_id
self.suit_id = suit_id
if self.rank_id == 1:
self.rank = "Ace"
self.value = 1
elif self.rank_id == 11:
self.rank = "Jack"
self.value = 10
elif self.rank_id == 12:
self.rank = "Queen"
self.value = 10
elif self.rank_id == 13:
self.rank = "King"
self.value = 10
elif 2 <= self.rank_id <= 10:
self.rank = str(self.rank_id)
self.value = self.rank_id
else:
self.rank = "RankError" <- (1) Wykonuje sprawdzanie błędów
self.value = -1
if self.suit_id == 1:
self.suit = "Diamonds"
elif self.suit_id == 2:
self.suit = "Hearts"
elif self.suit_id == 3:
self.suit = "Spades"
elif self.suit_id == 4:
self.suit = "Clubs"
else:
self.suit = "SuitError" <- (1) Wykonuje sprawdzanie błędów
self.short_name = self.rank[0] + self.suit[0]
if self.rank == '10':
self.short_name = self.rank + self.suit[0]
self.long_name = self.rank + " of " + self.suit
Sprawdzanie błędów w kodzie (1) zapewnia, że pozycja_id i suit_id znajdują się w zakresie i że są liczbami całkowitymi. Jeśli nie, zobaczysz coś takiego jak "7 of SuitError" lub "RankError of Clubs" podczas wyświetlania karty w programie. Linia, która ustawia short_name, przyjmuje po prostu liczbę lub pierwszą literę rangi (6 lub Jack) i pierwszą literę koloru (Karo) i umieszcza je razem. Dla Króla Kier, nazwa krótka byłaby KH. Dla 6 pików będzie to 6S. Listing 23.4 nie jest kompletnym programem. To tylko definicja klasy dla naszej klasy kart. Ponieważ jest to coś, czego możemy używać wielokrotnie w różnych programach, może powinniśmy zrobić z niego moduł. Zapisz kod w listingu 23.4 jako cards.py. Teraz musimy zrobić kilka kart - w rzeczywistości cała talia byłaby przyjemna! Aby przetestować naszą klasę kart, stwórzmy program do tworzenia talii 52 kart, a następnie wybierz losowo 5 kart i wyświetl ich atrybuty. Oto kod do tego.
Listing 24.5 Tworzenie talii kart
import random
from cards import Card <- Importuje nasz moduł kart
deck = []
for suit_id in range(1, 5):
for rank_id in range(1, 14):
deck.append(Card(suit_id, rank_id))
hand = []
for cards in range(0, 5):
a = random.choice(deck)
hand.append(a)
deck.remove(a)
print
for card in hand:
print card.short_name, '=' ,card.long_name, " Value:", card.value
(1) Wewnętrzna pętla przechodzi przez każdą kartę w kolorze, a zewnętrzna pętla przechodzi przez każdy kolor (13 kart * 4 kolory = 52 karty). (2) Następnie kod wybiera pięć kart z talii i wkłada je do ręki. Usuwa również karty z talii. Jeśli uruchomisz kod w liście 23.5, powinieneś otrzymać coś takiego:
7D = 7 wartości karo: 7
9H = 9 wartości kier: 9
KH = Król Kier Wartość: 10
6S = 6 wartości pików: 6
KC = Król Trefl Wartość: 10
Jeśli uruchomisz go ponownie, powinieneś otrzymać pięć różnych kart. Bez względu na to, ile razy go uruchomisz, nigdy nie powinieneś mieć tej samej karty dwa razy w jednej ręce.
Teraz możemy stworzyć talię kart i losowo dobrać z niej karty, aby dodać je do ręki. Wygląda na to, że mamy podstawowe rzeczy, których potrzebujemy, aby stworzyć grę karcianą! W następnej sekcji stworzymy grę karcianą, w którą możesz grać przeciwko komputerowi.
Szalone ósemki
Być może słyszałeś o grze karcianej o nazwie Crazy Eights. Może nawet grałeś. Jedną z rzeczy w grach karcianych na komputerze jest to, że trudno jest mieć wielu graczy. To dlatego, że w większości gier karcianych nie powinieneś oglądać kart innych graczy. Jeśli wszyscy patrzą na ten sam komputer, wszyscy zobaczą karty innych osób. Tak więc najlepszymi grami karcianymi do grania na komputerze są te, w których można grać tylko z dwoma graczami - z komputerem. Crazy Eights jest jedną z tych gier, które dobrze współpracują z dwoma graczami, dlatego zamierzamy stworzyć grę Crazy Eights, w której użytkownik gra przeciwko komputerowi. Oto zasady naszego programu. Jest to gra dla dwóch graczy. Każdy gracz otrzymuje pięć kart. Pozostałe karty są układane zakryte, a następnie jedna karta jest odwracana do góry, aby rozpocząć stos kart odrzuconych. Celem gry jest pozbycie się wszystkich kart przed wszystkimi innymi i zanim skończy się talia:
1 W każdej turze gracz musi wykonać jedną z następujących czynności:
• Zagraj kartę tego samego koloru co karta do góry.
• Zagraj w kartę o tej samej wartości co karta w górę.
• Zagraj w 8.
2 Jeśli gracz zagra 8, może "sprawdzić kolor", co oznacza, że może wybrać kolor, który następny gracz próbuje dopasować.
3 Jeśli gracz nie może zagrać żadnej ze swoich kart, musi podnieść kartę z talii i dodać ją do swojej ręki.
4 Jeśli gracz pozbędzie się wszystkich swoich kart, wygrywa tę grę i otrzymuje punkty w zależności od tego, co pozostały gracz ma w swojej ręce:
• 50 punktów za każde 8
• 10 punktów za każdą figurę karcianą
• Wartość nominalna dla każdej innej karty
• 1 punkt za każdego asa
5 Jeśli talia się skończy i nikt nie może zagrać, gra się kończy. W takim przypadku obaj gracze otrzymują punkty za pozostałe karty innego gracza.
6 Możesz grać do pewnej sumy punktów, lub po prostu grać, aż będziesz zmęczony, a wygrywa ten, który ma najwięcej punktów.
Pierwszą rzeczą, którą powinniśmy zrobić, jest zmodyfikowanie niektórych naszych obiektów kart. Wartości punktowe w Crazy Eights są w większości takie same jak wcześniej, z wyjątkiem 8, która jest warta 50 punktów zamiast 8 punktów. Możemy zmienić metodę __init__ w naszej klasie kart, aby uzyskać 8-emek o wartości 50 punktów, ale to wpłynęłoby na każdą inną grę, która może korzystać z modułu kart. Lepiej byłoby dokonać zmiany w programie głównym i pozostawić definicję klasy w spokoju. Oto jeden sposób, w jaki możemy to zrobić:
deck = []
for suit in range(1, 5):
for rank in range(1, 14):
new_card = Card(suit, rank)
if new_card.rank == 8:
new_card.value = 50
deck.append(new_card)
Tutaj, przed dodaniem nowej karty do talii, sprawdzamy, czy jest to 8. Jeśli tak, ustawiamy jej wartość na 50. Teraz jesteśmy gotowi, aby rozpocząć samą grę. Oto kilka rzeczy, które nasz program będzie musiał wykonać:
• Śledź kartę odkrytą.
• Uzyskaj wybór gracza co zrobić (zagraj kartę lub wyciągnij kartę).
• Jeśli gracz próbuje zagrać kartę, upewnij się, że gra jest ważna:
• Karta musi być ważną kartą.
• Karta musi znajdować się w ręce gracza.
• Karta musi pasować do rangi lub koloru odkrytej karty lub być 8.
• Jeśli gracz zagra 8, poproś o nowy kolor (i upewnij się, że wybór jest prawidłowy).
• Zagraj w kolejkę komputera (o tym wkrótce).
• Określ, kiedy gra się kończy.
• Odlicz punkty.
W pozostałej części przejdziemy kolejno przez te wymagania. Niektóre z nich będą potrzebować tylko jednej lub dwóch linii kodu, a niektóre będą nieco dłuższe. Dla dłuższych stworzymy funkcje, które możemy wywołać z głównej pętli.
Główna pętla
Zanim przejdziemy do szczegółów, ustalmy, jak będzie wyglądać główna pętla programu. Zasadniczo musimy zmieniać na zmianę obroty między graczem a komputerem, aż ktoś wygra lub oba zostaną zablokowane. Kod będzie wyglądał mniej więcej tak.
Listing 24.6 Główna pętla Crazy Eights
init_cards()
while not game_done:
blocked = 0
player_turn() <- Zwrot gracza
if len(p_hand) == 0: <- Ręka gracza (p_hand) nie ma żadnych kart, więc gracz
wygrywa
game_done = True
print
print "You won!"
if not game_done:
computer_turn() <- Skręt komputera
if len(c_hand) == 0: <- Ręka komputera (c_hand) nie ma żadnych kart, więc komputer wygrywa
game_done = True
print
print "Komputer wygrywa!"
if blocked >= 2: <- (1) Obaj gracze są zablokowani, więc gra się kończy
game_done = True
print "Both players blocked. GAME OVER."
Część głównej pętli zastanawia się, kiedy gra się skończy. Może się skończyć, gdy gracz lub komputer nie ma kart. Może się również skończyć, jeśli żaden z nich nie ma kart, ale oba są zablokowane (to znaczy, że nie mają ważnych zagrań). Zablokowana zmienna jest ustawiana w kodzie dla tury gracza (jeśli gracz jest zablokowany) i skrętu komputera (jeśli komputer jest zablokowany). b Czekamy na zablokowanie = 2, aby upewnić się, że zarówno odtwarzacz, jak i komputer są zablokowane. Pamiętaj, że listing 23.6 nie jest kompletnym programem, więc jeśli spróbujesz go uruchomić, pojawi się błąd. To tylko główna pętla. Nadal potrzebujemy wszystkich innych części, aby program był kompletny. Ten kod dotyczy pojedynczej gry. Jeśli chcemy nadal grać w więcej gier, możemy zawinąć całość w inną zewnętrzną pętlę while:
done = False
p_total = c_total = 0
while not done:
[play a game... see listing 23.6]
play_again = raw_input("Zagrać ponownie (Y/N)? ")
if play_again.lower().startswith('y'):
done = False
else:
done = True
Daje nam to główną strukturę programu. Teraz musimy dodać poszczególne elementy, aby zrobić to, czego potrzebujemy.
Myśląc jak programista
Opisane powyżej podejście nazywa się programowaniem metodą zstępującą.W tym miejscu zaczynasz od zarysu tego, co jest potrzebne, a następnie wypełniasz szczegółami. Innym sposobem na to jest oddolne. W tej metodzie najpierw utworzyłbyś wszystkie poszczególne części, na przykład kolej gracza, turę komputera itd., A następnie zestawiłeś je razem jak budynek jak bloki. Oba podejścia mają zalety i wady. Podejmowanie decyzji o wyborze jednego nad drugim nie jest tematem tego tekstu . Pomyślałem jednak, że powinieneś wiedzieć, że istnieją różne sposoby radzenia sobie z budowaniem programu
Karta odkryta
Gdy rozdanie zostanie rozdane po raz pierwszy, jedna karta z talii zostaje odkryta, aby rozpocząć stos kart odrzuconych. Gdy jakikolwiek gracz zagrywa kartę, trafia odkrytą na stos kart odrzuconych. Karta pokazana na stosie kart odrzuconych w dowolnym momencie jest nazywana kartą podniesioną. Moglibyśmy to śledzić, tworząc listę stosów odrzuconych, w taki sam sposób, w jaki stworzyliśmy listę "dłoni" w naszym kodzie testowym w listingu 24.5. Ale tak naprawdę nie obchodzą nas wszystkie karty na stosie kart odrzuconych. Dbamy tylko o ostatnią dodaną do niego kartę. Możemy więc użyć pojedynczej instancji obiektu Card, aby go śledzić. Gdy gracz lub komputer zagrają kartę, zrobimy coś takiego:
hand.remove (selected_card)
up_card = selected_card
Aktywny kolor
Zazwyczaj aktywny kolor (ten, który gracz lub komputer próbuje dopasować) jest taki sam jak kolor karty wyższej. Ale jest wyjątek. Kiedy zagrałeś 8, gracz wywołuje kolor. Jeśli więc zagra 8 Karo, może nazwać Trefle jako kolor. Oznacza to, że następna gra musi pasować do Trefli, nawet jeśli pokazuje Karo (8 Karo). Oznacza to, że musimy śledzić aktywny stos, ponieważ może się różnić od pokazanego koloru. Możemy użyć zmiennej active_suit, aby to zrobić:
active_suit = card.suit
Za każdym razem, gdy zagrasz kartę, zaktualizujemy aktywny kolor, a gdy gracz zagra 8, wybierze nowy aktywny stosr.
Zwrot gracza
Kiedy przyjdzie kolej na gracza, pierwszą rzeczą, którą musimy zrobić, jest wybór tego, co robić. Może zagrać kartę ze swojej ręki (jeśli to możliwe) lub dobrać ją z talii. Gdybyśmy tworzyli wersję GUI tego programu, gracz powinien kliknąć kartę, którą chciał zagrać, lub kliknąć talię do narysowania. Ale tworzymy tekstową wersję programu, więc będzie musiał wpisać wybór, a następnie będziemy musieli sprawdzić, co wpisał i dowiedzieć się, co chce zrobić i czy dane wejściowe są poprawne .
Aby zorientować się, jakiego rodzaju dane gracz będzie musiał dostarczyć, przyjrzymy się przykładowej grze.
Crazy Eights
Your hand: 4S, 7D, KC, 10D, QS Up Card: 6C
What would you like to do? Type a card name or "Draw" to take a card: KC
You played the KC (King of Clubs)
Computer plays 8S (8 of spades) and changes suit to Diamonds
Your hand: 4S, 7D, 10D, QS Up Card: 8S Suit: Diamonds
What would you like to do? Type a card name or "Draw" to take a card: 10D
You played 10D (10 of Diamonds)
Computer plays QD (Queen of Diamonds)
Your hand: 4S, 7D QS Up card: QD
What would you like to do? Type a card name or "Draw" to take a card: 7D
You played 7D (7 of Diamonds)
Computer plays 9D (9 of Diamonds)
Your hand: 4S, QS Up card: 9D
What would you like to do? Type a card name or "Draw" to take a card: QM
That is not a valid card. Try again: QD
You do not have that card in your hand. Try again: QS
That is not a legal play. You must match suit, match rank, play an 8, or draw a card
Try again: Draw
You drew 3C
Computer draws a card
Your hand: 4S, QS, 3C Up card: 9D
What would you like to do? Type a card name or "Draw" to take a card: Draw
You drew 8C
Computer plays 2D
Your hand: 4S, QS, 3C, 8C Up card: 2D
What would you like to do? Type a card name or "Draw" to take a card: 8C
You played 8C (8 of Clubs)
Your hand: 4S, QS, 3C Pick a suit: S
You picked spades
Computer draws a card
Your hand: 4S, QS, 3C Up card: 8C Suit: Spades
What would you like to do? Type a card name or "Draw" to take a card: QS
You played QS (Queen of Spades)
To nie jest kompletna gra, ale masz pomysł. Gracz musi wpisać rzeczy takie jak QS lub Draw, aby poinformować program o swoim wyborze. Program musi sprawdzić, czy to, co wpisał gracz, ma sens. Użyjemy niektórych metod łańcuchowych (z części 21), aby nam w tym pomóc.
Wyświetlanie ręki
Zanim zapytamy gracza, co chce zrobić, powinniśmy pokazać mu, jakie karty są w jego ręce i jaką kartę ma. Oto kod do tego:
print "\nYour hand: ",
for card in p_hand:
print card.short_name,
print " Up card: ", up_card.short_name
Jeśli rozegrano 8, musimy również powiedzieć mu, czym jest aktywny kombinezon. Dodajmy więc kilka kolejnych linii, jak pokazano poniżej.
print "\nYour hand: ",
for card in p_hand:
print card.short_name,
print " Up card: ", up_card.short_name
if up_card.rank == '8':
print" Suit is", active_suit
Podobnie jak w przypadku listingu 24.6, listingu 24.7 nie jest kompletnym programem. Nadal budujemy części potrzebne do stworzenia kompletnego programu. Ale gdy kod w listingu 24.7 działa (jako część kompletnego programu), daje wynik taki jak poniżej:
Twoja ręka: karta 4S, QS, 3C Up: 8C Kolor: pik
Gdybyś chciał użyć długich nazw kart zamiast krótkich nazw, wynik wyglądałby mniej więcej tak:
Twoja ręka: 4 Kiery, Królowa Pik, 3 Trefle
Karta górna: 8 Koloru Trefl: Pik
W naszym przykładzie będziemy używać nazw skróconych
Jeśli rozegrano 8, musimy również powiedzieć mu, czym jest aktywny kombinezon. Dodajmy więc kilka kolejnych linii, jak pokazano poniżej
Listing 24.7 Wyświetlanie tego, co jest w ręce gracza
print "\nYour hand: ",
for card in p_hand:
print card.short_name,
print " Up card: ", up_card.short_name
if up_card.rank == '8':
print" Suit is", active_suit
Uzyskanie wyboru gracza
Teraz musimy zapytać gracza, co chce zrobić, i przetworzyć jego odpowiedź. Ma dwie główne możliwości:
• Zagraj w kartę
• Narysuj kartę
Jeśli zdecyduje się zagrać kartę, musimy upewnić się, że gra jest ważna. Powiedzieliśmy wcześniej, że musimy sprawdzić trzy rzeczy:
• Czy jego wybór jest ważną kartą? (Czy próbował grać w 4 Pianki?)
• Czy karta jest w jego ręce?
• Czy wybrana karta jest legalna? (Czy pasuje do rangi lub koloru karty do góry, czy jest to 8?)
Ale jeśli się nad tym zastanowić, jego ręka może mieć tylko ważne karty. Jeśli więc sprawdzimy, czy karta jest w jego ręce, nie musimy się martwić o sprawdzenie, czy karta jest prawidłowa. Nie może mieć 4 Pianek w ręku, ponieważ nigdy nie istniały w talii. Spójrzmy więc na kod, który pozwoli graczowi na wybór i zatwierdzenie go. Jest to pokazane na listingu 23.8.
Walidacja oznacza upewnienie się, że coś jest ważne, co oznacza, że jest dozwolone lub ma sens.
Listing 24.8 Uzyskanie wyboru gracza
print "What would you like to do? ",
response = raw_input ("Type a card to play or 'Draw' to take a card: " )
valid_play = False
while not valid_play: <- Stara się, aż gracz wprowadzi coś ważnego
selected_card = None
while selected_card == None:
if response.lower() == 'draw':
valid_play = True
if len(deck) > 0:
card = random.choice(deck)
p_hand.append(card)
deck.remove(card)
print "You drew", card.short_name
else:
print "There are no cards left in the deck"
blocked += 1
return <- Mam "draw", więc wraca do głównej pętli
else:
for card in p_hand:
if response.upper() == card.short_name: <- Sprawdza, czy wybrana karta znajduje się w ręce gracza -
kontynuuje próbę, aż się pojawi (lub losuje)
selected_card = card
if selected_card == None:
response = raw_input("You don't have that card. Try again:")
if selected_card.rank == '8': <- Gra na 8 jest zawsze legalna
valid_play = True
is_eight = True
elif selected_card.suit == active_suit: <- Sprawdza, czy wybrana karta pasuje do koloru karty
valid_play = True
elif selected_card.rank == up_card.rank: <- Sprawdza, czy wybrana karta pasuje do rangi karty
valid_play = True
if not valid_play:
response = raw_input("That's not a legal play. Try again: ")
(Ponownie, nie jest to kompletny, uruchamialny program.) (1) W tym momencie mamy wybór, który jest ważny: albo rysunek, albo gra w ważną kartę. Jeśli gracz dobiera, dodajemy kartę do jego ręki, o ile w talii są karty. Jeśli grasz kartą, musimy usunąć kartę z ręki i uczynić ją kartą:
p_hand.remove (selected_card)
up_card = selected_card
active_suit = up_card.suit
drukuj "Grałeś", selected_card.short_name
Jeśli zagrana karta wynosiła 8, gracz musi nam powiedzieć, jaki kolor chce dalej. Ponieważ funkcja player_turn () staje się nieco dłuższa, sprawimy, że nowy garnitur stanie się osobną funkcją o nazwie get_new_suit (). Następna lista pokazuje kod tej funkcji.
Listing 23.9 Zdobycie nowego koloru, gdy gracz gra 8
def get_new_suit():
global active_suit
got_suit = False
while not got_suit:
suit = raw_input("Pick a suit: ")
if suit.lower() == 'd':
active_suit = "Diamonds"
got_suit = True
elif suit.lower() == 's':
active_suit = "Spades"
got_suit = True
elif suit.lower() == 'h':
active_suit = "Hearts"
got_suit = True
elif suit.lower() == 'c':
active_suit = "Clubs"
got_suit = True
else:
print"Not a valid suit. Try again. ",
print "You picked", active_suit
To wszystko, czego potrzebujemy do tury gracza. W następnej sekcji sprawimy, że komputer będzie wystarczająco inteligentny, aby grać w Crazy Eights. Skręt komputera Po kolei gracza komputer musi zagrać, więc musimy powiedzieć programowi, jak grać w Crazy Eights. Musi przestrzegać tych samych zasad, co gracz, ale program musi zdecydować, którą kartę zagrać. Musimy konkretnie powiedzieć, jak radzić sobie ze wszystkimi możliwymi sytuacjami:
• Grając w 8 (i wybierając nowy kolor)
• Odtwarzanie innej karty
• Rysowanie
Aby uczynić to trochę prostszym, powiemy komputerowi, aby zawsze grał w 8, jeśli taki ma. To może nie być najlepsza strategia, ale prosta. Jeśli komputer gra 8, musi wybrać nowy garnitur. Najprostszym sposobem na to jest policzenie liczby kart każdego koloru w ręce komputera i wybranie koloru, który ma najwięcej. Ponownie, nie jest to idealna strategia, ale jest to jedna z najprostszych do kodu. Jeśli w ręce komputera nie ma 8, program przejdzie przez wszystkie karty i zobaczy, które z nich są możliwe do odtworzenia. Spośród tych kart wybierze tę z najwyższą wartością i zagra tę. Jeśli nie ma możliwości zagrania karty, komputer narysuje. Jeśli komputer próbuje narysować i nie ma żadnych kart w talii, komputer jest zablokowany, tak jak gracz ludzki. Oto kod na kolejkę komputera z kilkoma notatkami wyjaśniającymi.
Listing 24.10 Tura komputera
def computer_turn():
global c_hand, deck, up_card, active_suit, blocked
options = []
for card in c_hand:
if card.rank == '8': <- Gra w 8
c_hand.remove(card)
up_card = card
print " Computer played ", card.short_name
#suit totals: [diamonds, hearts, spades, clubs] <- Liczy karty w każdym kolorze; najlepiej pasujące
do "długiego garnitur"
suit_totals = [0, 0, 0, 0]
for suit in range(1, 5):
for card in c_hand:
if card.suit_id == suit:
suit_totals[suit-1] += 1
long_suit = 0
for i in range (4):
if suit_totals[i] > long_suit:
long_suit = i
if long_suit == 0: active_suit = "Karo"
if long_suit == 1: active_suit = "Kier"
if long_suit == 2: active_suit = "Pik"
if long_suit == 3: active_suit = "Trefl"
print " Computer changed suit to ", active_suit
return <- Kończy turę komputera; powrót do głównej pętli
else:
if card.suit == active_suit:
options.append(card)
elif card.rank == up_card.rank:
options.append(card)
if len(options) > 0:
best_play = options[0]
for card in options:
if card.value > best_play.value:
best_play = card
c_hand.remove(best_play)
up_card = best_play
active_suit = up_card.suit
print " Computer played ", best_play.short_name
else:
if len(deck) >0:
next_card = random.choice(deck)
c_hand.append(next_card)
deck.remove(next_card)
print " Computer drew a card"
else:
print" Computer is blocked"
blocked += 1
print "Computer has %i cards left" % (len(c_hand))
Prawie skończyliśmy - wystarczy dodać jeszcze kilka rzeczy. Być może zauważyłeś, że skręt komputera został zdefiniowany jako funkcja i użyliśmy niektórych zmiennych globalnych w tej funkcji. Moglibyśmy również przekazać zmienne do funkcji, ale korzystanie z globali działa równie dobrze i jest bardziej podobne do świata rzeczywistego, gdzie talia jest "globalna" - każdy może sięgnąć i wziąć z niej kartę. Zwrot gracza jest także funkcją, ale nie pokazaliśmy pierwszej części tej definicji funkcji. Wyglądałoby to tak:
Wygląda to tak:
def player_turn():
global deck, p_hand, blocked, up_card, active_suit
valid_play = False
is_eight = False
print "\nYour hand: ",
for card in p_hand:
print card.short_name,
print " Up card: ", up_card.short_name
if up_card.rank == '8':
print" Suit is", active_suit
print "What would you like to do? ",
response = raw_input("Type a card to play or 'Draw' to take a card: ")
Potrzebujemy jeszcze jednej rzeczy. Musimy śledzić, kto wygrywa!
Zachowując wynik
Ostatnią rzeczą, której potrzebujemy, aby nasza gra była kompletna, jest punktowanie. Kiedy gra się kończy, musimy śledzić, ile punktów zwycięzca otrzymuje za karty pozostające w ręce przegranego. Powinniśmy wyświetlać punkty za tę grę, a także sumę wszystkich gier. Po dodaniu tych rzeczy główna pętla będzie wyglądać mniej więcej tak
Listing 24..11 Dodano główną pętlę z punktacją
done = False
p_total = c_total = 0
while not done:
game_done = False
blocked = 0 <- (1) Ustawia talię i ręce gracza i komputera
init_cards()
while not game_done:
player_turn()
if len(p_hand) == 0: <- Gracz wygrywa
game_done = True
print
print "Wygrałeś!"
# display game score here
p_points = 0
for card in c_hand:
p_points += card.value
p_total += p_points <- Dodaje punkty z tej gry do całości
print "You got %i points for computer's hand" % p_points
if not game_done:
computer_turn()
if len(c_hand) == 0: <- Wygrywa komputer
game_done = True
print
print "Computer won!"
# display game score here
c_points = 0
for card in p_hand:
c_points += card.value
c_total += c_points <- Dodaje punkty z tej gry do całości
print "Computer got %i points for your hand" % c_points
if blocked >= 2:
game_done = True
print "Both players blocked. GAME OVER."
player_points = 0
for card in c_hand:
p_points += card.value
p_total += p_points
c_points = 0
for card in p_hand:
c_points += card.value
c_total += c_points
print "You got %i points for computer's hand" % p_points
print "Computer got %i points for your hand" % c_points
play_again = raw_input("Play again (Y/N)? ")
if play_again.lower().startswith('y'):
done = False
print "\nSo far, you have %i points" % p_total
print "and the computer has %i points.\n" % c_total
else:
done = True
print "\n Final Score:"
print "You: %i Computer: %i" % (p_total, c_total)
(1) Funkcja init_cards () (nie pokazana tutaj) ustawia talię i tworzy rękę gracza (5 kart), rękę komputera (5 kart) i pierwszą kartę. Listing 23.11 nadal nie jest kompletnym programem, więc wystąpi błąd, jeśli spróbujesz go uruchomić. Ale jeśli już śledzisz, masz już prawie cały program w swoim edytorze. Pełna lista Crazy Eights jest zbyt długa, aby ją tutaj wydrukować (jest to około 200 wierszy kodu, plus puste wiersze i komentarze), ale można ją znaleźć w folderze Przykłady, jeśli użyłeś instalatora książki. Jest także na stronie internetowej (www.helloworldbook2.com). Możesz użyć IDLE do edycji i uruchamiania tego programu.
Czego się nauczyłeś?
• Jakie losowości i zdarzenia losowe są
• Trochę o prawdopodobieństwie
• Jak używać losowego modułu do generowania zdarzeń losowych w programie
• Jak symulować rzut monetą lub rzutem kostką
• Jak symulować rysowanie kart z tasowanej talii
• Jak grać w Crazy Eights (jeśli jeszcze nie wiesz)
Sprawdź swoją wiedzę
1 Opisz, czym jest "zdarzenie losowe". Podaj dwa przykłady.
2 Dlaczego walcowanie jednej 11-stronnej kostki o liczbach od 2 do 12 różni się od walcowania pary
6-stronnych kości, które dają sumy od 2 do 12?
3 Jakie są dwa sposoby symulacji rzutu kostką w Pythonie?
4 Jakiej zmiennej Python użyliśmy dla pojedynczej karty?
5 Jaką zmienną Pythona używaliśmy dla talii kart?
6 Jakiej metody użyliśmy, aby usunąć kartę z talii, gdy jest wylosowana, lub z ręki, kiedy jest zagrana?
Wypróbuj to
1 Wypróbuj eksperyment "10 z rzędu", używając programu z listy 23.3, ale spróbuj różnych kwot dla "z rzędu". Jak często dostajesz pięć z rzędu? Jak około sześciu, siedmiu, ośmiu i tak dalej? Czy widzisz wzór?
Czy widziałeś kiedyś "wirtualnego zwierzaka": te małe zabawki z małym wyświetlaczem i kilkoma przyciskami do karmienia zwierząt domowych, gdy są głodne, pozwalając im spać, gdy jest zmęczony, bawiąc się nim, kiedy się nudzi i tak dalej? Wirtualne zwierzę ma takie same cechy jak prawdziwe, żywe zwierzę. To przykład symulacji komputerowej - wirtualne urządzenie dla zwierząt to mały komputer. W ostatniej częsci dowiedziałeś się o zdarzeniach losowych i jak je wygenerować w programie. W pewnym sensie była to swego rodzaju symulacja. Symulacja polega na stworzeniu komputerowego modelu czegoś z prawdziwego świata. Stworzyliśmy modele komputerowe monet, kości i talii kart. W tej części dowiesz się więcej o używaniu programów komputerowych do symulacji świata rzeczywistego.
Modelowanie świata rzeczywistego
Istnieje wiele powodów, aby używać komputera do symulacji lub modelowania świata rzeczywistego. Czasami eksperymentowanie nie jest praktyczne ze względu na czas, odległość, niebezpieczeństwo lub inne przyczyny. Na przykład w ostatniej części symulowaliśmy przerzucanie monety milion razy. Większość z nas nie ma czasu na zrobienie tego prawdziwą monetą, ale symulacja komputerowa zrobiła to w kilka sekund. Czasami naukowcy chcą dowiedzieć się "Co jeśli
?" Co jeśli asteroida uderzy w Księżyc? Nie możesz rozbić prawdziwej asteroidy na Księżyc, ale symulacja komputerowa może nam powiedzieć, co się stanie. Czy Księżyc poszybowałby w kosmos? Czy spadnie na Ziemię? Jak zmieni się jego orbita? Kiedy piloci i astronauci uczą się latać samolotami i statkami kosmicznymi, nie zawsze mogą ćwiczyć na prawdziwym. To byłoby bardzo drogie! (A czy chciałbyś być pasażerem pilota-studenta?) Używają więc symulatorów, które dają im wszystkie te same elementy sterujące, co prawdziwy samolot lub statek kosmiczny. W symulacji możesz zrobić wiele rzeczy:
• Wypróbuj eksperyment lub przećwicz umiejętność bez posiadania jakiegokolwiek sprzętu (z wyjątkiem komputera) i bez narażania kogokolwiek na niebezpieczeństwo
• Przyspieszenie lub spowolnienie czasu
• Wykonuj wiele eksperymentów jednocześnie
• Wypróbuj rzeczy, które byłyby kosztowne, niebezpieczne lub niemożliwe w rzeczywistym świecie
Pierwszą symulacją, którą zamierzamy wykonać, jest gra grawitacyjna. Spróbujemy wylądować statek kosmiczny na Księżycu, ale mamy tylko pewną ilość paliwa, więc musimy uważać, jak używamy naszych silników odrzutowych. Jest to bardzo prosta wersja gry zręcznościowej o nazwie Lunar Lander, która była popularna wiele lat temu.
Lunar Lander
Zaczniemy od naszego statku kosmicznego w pewnej odległości ponad powierzchnią Księżyca. Grawitacja Księżyca zacznie go ściągać, a my będziemy musieli użyć silników odrzutowych, aby spowolnić zejście i wykonać miękkie lądowanie. Po prawej stronie możesz zobaczyć, jak będzie wyglądał program.
Mały szary pasek po lewej stronie to przepustnica. Przeciągasz go w górę lub w dół za pomocą myszy, aby kontrolować ciąg silników. Wskaźnik poziomu paliwa informuje o ilości pozostałego paliwa, a tekst zawiera informacje o prędkości, przyspieszeniu, wysokości i ciągu.
Symulacja lądowania
Aby symulować lądowanie statku kosmicznego, musisz zrozumieć, jak siła grawitacji i siła równowagi silnika statku kosmicznego działają przeciwko sobie. Dla naszej symulacji założymy, że siła grawitacji jest stała. To nie do końca prawda, ale dopóki statek kosmiczny nie jest zbyt daleko od Księżyca, grawitacja jest prawie stała - wystarczająco bliska naszej symulacji.
Słowo prędkość oznacza prawie to samo, co prędkość, z wyjątkiem tego ,że prędkość obejmuje kierunek, a prędkość nie. Na przykład "pięćdziesiąt kilometrów na godzinę "opisuje prędkość, podczas gdy" pięćdziesiąt mil na godzinę na północ " opisuje szybkość. Wiele osób używa słowa szybkość, gdy naprawdę ma na myśli prędkość, i odwrotnie. W naszym programie musimy wiedzieć czy statek kosmiczny idzie w górę, czy w dół, więc użyjemy prędkości. Przyspieszenie oznacza, jak szybko zmienia się prędkość.
Przyspieszenie dodatnie oznacza, że prędkość wzrasta, a przyspieszenie ujemne oznacza, że prędkość maleje.
Siła silników zależy od ilości spalanego paliwa. Czasami będzie większa niż siła grawitacji, czasami mniejsza. Gdy silniki są wyłączone, ich siła wynosi 0 i pozostaje nam tylko siła grawitacji. Aby uzyskać całkowitą lub netto siłę na statku kosmicznym, dodajemy tylko dwie siły. Ponieważ są w przeciwnych kierunkach, jeden będzie pozytywny, a drugi negatywny. Kiedy już mamy siłę netto na statku kosmicznym, możemy określić jego prędkość i pozycję za pomocą wzoru. Nasza symulacja będzie musiała śledzić następujące rzeczy:
• Wysokość statku kosmicznego nad Księżycem oraz jego prędkość i przyspieszenie.
• Masa statku kosmicznego (która zmienia się w miarę zużywania paliwa).
• Nacisk lub siła silników. Im więcej używamy ciągu, tym szybciej spalimy paliwo.
• Ilość paliwa na statku kosmicznym. Gdy spalamy paliwo za pomocą naszych silników odrzutowych, statek kosmiczny stanie się lżejszy, ale jeśli zabraknie nam paliwa, nie będzie już pchnięcia.
• Siła grawitacji na statku kosmicznym. To zależy od wielkości Księżyca i masy statku kosmicznego i paliwa.
Powraca Pygame
Ponownie użyjemy Pygame do przeprowadzenia tej symulacji. Tik zegara Pygame będzie naszą jednostką czasu. Za każdy tik sprawdzimy siłę netto na statku kosmicznym i zaktualizujemy wysokość, prędkość, przyspieszenie i pozostające paliwo. Następnie użyjemy tych informacji do aktualizacji grafiki i tekstu. Ponieważ animacja jest bardzo prosta, nie użyjemy ikonki dla statku kosmicznego. Ale użyjemy jednego dla przepustnicy (szary prostokąt), ponieważ ułatwia to przeciągnięcie myszą. Wskaźnik paliwa to tylko kilka prostokątów narysowanych za pomocą metody draw.rect() Pygame. Tekst jest tworzony za pomocą obiektów pygame.font, tak jak w przypadku PyPong. Kod będzie zawierał sekcje, które wykonują następujące czynności:
• Zainicjuj grę - ustaw okno Pygame, załaduj obrazy i ustaw niektóre wartości początkowe dla zmiennych
• Zdefiniuj klasę ikonki przepustnicy
• Oblicz wysokość, prędkość, przyspieszenie i zużycie paliwa
• Wyświetl informacje
• Zaktualizuj wskaźnik paliwa
• Wyświetl płomienie rakiet (które zmieniają rozmiar w zależności od ciągu)
• Wymieszaj wszystko na ekranie, sprawdź zdarzenia myszy, zaktualizuj pozycję przepustnicy i sprawdź, czy statek wylądował - będzie to główna pętla zdarzeń Pygame
• Wyświetlaj "Game Over" i końcowe statystyki
Listing 25.1 pokazuje kod Lunar Lander . Spójrz na kod i notatki i upewnij się, że rozumiesz, jak wszystko działa. Nie przejmuj się formułami wysokości, prędkości i przyspieszenia. Dowiesz się wszystkiego o fizyce w szkole średniej, zdasz egzamin, a potem szybko go zapomnisz (chyba że pójdziesz do pracy w NASA). A może ten program pomoże Ci zapamiętać!
Listing 25.1 Lunar Lander
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([400,600])
screen.fill([0, 0, 0])
ship = pygame.image.load('lunarlander.png')
moon = pygame.image.load('moonsurface.png')
ground = 540 <- Lądowisko to y = 540
start = 90
clock = pygame.time.Clock()
ship_mass = 5000.0
fuel = 5000.0
velocity = -100.0
gravity = 10
height = 2000
thrust = 0
delta_v = 0
y_pos = 90
held_down = False
class ThrottleClass(pygame.sprite.Sprite):
def __init__(self, location = [0,0]):
pygame.sprite.Sprite.__init__(self)
image_surface = pygame.surface.Surface([30, 10])
image_surface.fill([128,128,128])
self.image = image_surface.convert()
self.rect = self.image.get_rect()
self.rect.left, self.rect.centery = location
def calculate_velocity():
global thrust, fuel, velocity, delta_v, height, y_pos
delta_t = 1/fps <-Zaznacz jest jedną ramką pętli Pygame
thrust = (500 - myThrottle.rect.centery) * 5.0 <-Przekręca pozycję y sprite przepustnicy do wielkości ciągu
fuel -= thrust /(10 * fps) <-Odejmuje paliwo w zależności od ciągu
if fuel < 0: fuel = 0.0
if fuel < 0.1: thrust = 0.0
delta_v = delta_t * (-gravity + 200 * thrust / (ship_mass + fuel))// Formuła fizyki
velocity = velocity + delta_v
delta_h = velocity * delta_t
height = height + delta_h
y_pos = ground - (height * (ground - start) / 2000) - 90<-Konwertuje wysokość na pozycję y Pygame
def display_stats():
v_str = "velocity: %i m/s" % velocity
h_str = "height: %.1f" % height
t_str = "thrust: %i" % thrust
a_str = "acceleration: %.1f" % (delta_v * fps)
f_str = "fuel: %i" % fuel
v_font = pygame.font.Font(None, 26)
v_surf = v_font.render(v_str, 1, (255, 255, 255))
screen.blit(v_surf, [10, 50])
a_font = pygame.font.Font(None, 26)
a_surf = a_font.render(a_str, 1, (255, 255, 255))
screen.blit(a_surf, [10, 100])
h_font = pygame.font.Font(None, 26)
h_surf = h_font.render(h_str, 1, (255, 255, 255))
screen.blit(h_surf, [10, 150])
t_font = pygame.font.Font(None, 26)
t_surf = t_font.render(t_str, 1, (255, 255, 255))
screen.blit(t_surf, [10, 200])
f_font = pygame.font.Font(None, 26)
f_surf = f_font.render(f_str, 1, (255, 255, 255))
screen.blit(f_surf, [60, 300])
def display_flames():
flame_size = thrust / 15
for i in range (2):
startx = 252 - 10 + i * 19
starty = y_pos + 83
pygame.draw.polygon(screen, [255, 109, 14], [(startx, starty),
(startx + 4, starty + flame_size),
(startx + 8, starty)], 0)
def display_final():
final1 = "Game over"
final2 = "You landed at %.1f m/s" % velocity
if velocity > -5:
final3 = "Nice landing!"
final4 = "I hear NASA is hiring!"
elif velocity > -15:
final3 = "Ouch! A bit rough, but you survived."
final4 = "You'll do better next time."
else:
final3 = "Yikes! You crashed a 30 Billion dollar ship."
final4 = "How are you getting home?"
pygame.draw.rect(screen, [0, 0, 0], [5, 5, 350, 280],0)
f1_font = pygame.font.Font(None, 70)
f1_surf = f1_font.render(final1, 1, (255, 255, 255))
screen.blit(f1_surf, [20, 50])
f2_font = pygame.font.Font(None, 40)
f2_surf = f2_font.render(final2, 1, (255, 255, 255))
screen.blit(f2_surf, [20, 110])
f3_font = pygame.font.Font(None, 26)
f3_surf = f3_font.render(final3, 1, (255, 255, 255))
screen.blit(f3_surf, [20, 150])
f4_font = pygame.font.Font(None, 26)
f4_surf = f4_font.render(final4, 1, (255, 255, 255))
screen.blit(f4_surf, [20, 180])
pygame.display.flip()
myThrottle = ThrottleClass([15, 500]) <-Tworzy obiekt przepustnicy
running = True
while running: <-Początek głównej pętli zdarzeń Pygame
clock.tick(30)
fps = clock.get_fps()
if fps < 1: fps = 30
if height > 0.01:
calculate_velocity()
screen.fill([0, 0, 0])
display_stats()
pygame.draw.rect(screen, [0, 0, 255], [80, 350, 24, 100], 2) <-Zarys wskaźnika paliwa
fuelbar = 96 * fuel / 5000
pygame.draw.rect(screen, [0,255,0],
[84,448-fuelbar,18, fuelbar], 0)
pygame.draw.rect(screen, [255, 0, 0],
[25, 300, 10, 200],0)
screen.blit(moon, [0, 500, 400, 100]) <- Księżyc
pygame.draw.rect(screen, [60, 60, 60],
[220, 535, 70, 5],0)
screen.blit(myThrottle.image, myThrottle.rect) <-Uchwyt oporowy
display_flames()
screen.blit(ship, [230, y_pos, 50, 90]) <- Statek
instruct1 = "Land softly without running out of fuel"
instruct2 = "Good landing: < 15m/s Great landing: < 5m/s"
inst1_font = pygame.font.Font(None, 24)
inst1_surf = inst1_font.render(instruct1, 1, (255, 255, 255))
screen.blit(inst1_surf, [50, 550])
inst2_font = pygame.font.Font(None, 24)
inst2_surf = inst1_font.render(instruct2, 1, (255, 255, 255))
screen.blit(inst2_surf, [20, 575])
pygame.display.flip()
else: <- Koniec gry. Wyświetla wynik końcowy
display_final()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
held_down = True
elif event.type == pygame.MOUSEBUTTONUP:
held_down = False
elif event.type == pygame.MOUSEMOTION:
if held_down:
myThrottle.rect.centery = event.pos[1]
if myThrottle.rect.centery < 300:
myThrottle.rect.centery = 300
if myThrottle.rect.centery > 500:
myThrottle.rect.centery = 500
pygame.quit()
Wypróbuj program. Może dowiesz się, że jesteś dobrym pilotem statku kosmicznego! Jeśli uważasz, że jest to zbyt łatwe, możesz zmodyfikować kod, aby uczynić grawitację silniejszą, uczynić statek cięższym (bardziej masywnym), dać sobie mniej paliwa lub ustawić inną początkową wysokość lub prędkość. Jesteś programistą, więc możesz zdecydować, jak powinna działać gra. Symulacja Lunar Lander dotyczy głównie grawitacji. W dalszej części omówimy inny ważny czynnik w symulacjach - czas. A my stworzymy symulację, która wymaga śledzenia czasu.
Trzymaj czas
Czas jest ważnym czynnikiem w wielu symulacjach. Czasami chcesz przyspieszyć czas lub sprawić, że wszystko stanie się szybciej niż w świecie rzeczywistym, więc nie musisz czekać tak długo, aby dowiedzieć się, co się dzieje. Czasami chcesz spowolnić proces, dzięki czemu możesz lepiej przyjrzeć się rzeczom, które normalnie zdarzają się szybciej niż widać. Czasami chcesz, aby program zachowywał się w czasie rzeczywistym - aby działał tak, jak w prawdziwym świecie. We wszystkich przypadkach potrzebny jest jakiś zegar do pomiaru czasu w programie. Każdy komputer ma wbudowany zegar, którego można użyć do pomiaru czasu. Widziałeś już kilka przykładów wykorzystania i pomiaru czasu:
• W części 8 użyliśmy funkcji time.sleep(), aby ustawić minutnik.
• W naszych programach Pygame używaliśmy zarówno funkcji Time.delay, jak i Clock.tick Pygame, aby kontrolować szybkość animacji lub szybkość klatek. Użyliśmy również get_fps(), aby sprawdzić, jak szybko animacja była uruchomiona, co jest sposobem pomiaru czasu (średni czas dla każdej klatki).
Do tej pory zawsze śledziliśmy czas, gdy program był uruchomiony, ale czasami trzeba śledzić czas, nawet gdy program nie jest uruchomiony. Jeśli zrobiłeś program Virtual Pet w Pythonie, nie chciałbyś, aby cały czas działał. Chcesz się nim pobawić przez chwilę, a następnie zatrzymać i wrócić do niego później. Gdy byłeś nieobecny, spodziewałbyś się, że twoje zwierzę zmęczy się lub głoduje albo pójdzie spać. Program musi wiedzieć, ile czasu upłynęło od ostatniego uruchomienia. Jednym ze sposobów na to jest zapisanie przez program małego fragmentu informacji - aktualnego czasu - do pliku tuż przed jego zamknięciem. Następnie przy następnym uruchomieniu może odczytać plik, aby uzyskać poprzedni czas, sprawdzić aktualny czas i porównać dwa, aby zobaczyć, ile czasu minęło od ostatniego uruchomienia programu. Python ma specjalny rodzaj obiektu do pracy z czasami i datami. Idziemy aby dowiedzieć się trochę o obiektach Python w dacie i godzinie w następnej sekcji.
Po zapisaniu bieżącego czasu do pliku w celu późniejszego odczytania, to jest znacznikiem czasowym.
Obiekty czasu
Pythonowe klasy obiektów daty i czasu są zdefiniowane w ich własnym module datetime. Moduł datetime ma klasy do pracy z datami, czasami i różnicą lub różnicą między dwiema datami lub czasami
Słowo delta oznacza "różnicę". Jest to litera alfabetu greckiego i wygląda tak: Δ (trójkąt). Litery alfabetu greckiego są często używane w nauce i matematyce jako skrót dla pewnych ilości. Delta jest używana dla różnicy między dwiema wartościami.
Pierwszym rodzajem obiektu, którego będziemy używać, jest obiekt datetime. (Tak, klasa ma taką samą nazwę jak moduł.) Obiekt datetime zawiera rok, miesiąc, dzień, godzinę, minutę i sekundę. Tworzysz taki (postępuj zgodnie z instrukcjami w trybie interaktywnym):
>>> data importu
>>> when = datetime.datetime (2012, 10, 24, 10, 45, 56)
Zobaczmy, co mamy:
>> print when
2012-10-24 10:45:56
Stworzyliśmy obiekt datetime, nazwany when, który zawiera wartości daty i godziny. Podczas tworzenia obiektu datetime, kolejność parametrów (liczby w nawiasach) to rok, miesiąc, dzień, godzina, minuta, sekunda. Ale jeśli tego nie pamiętasz, możesz je umieścić dowolną kolejność, o ile chcesz powiedzieć Pythonowi, który jest taki, jak ten:
>>> when = datetime.datetime(hour=10, year=2012, minute=45, month=10,second=56, day=24)
Jest kilka innych rzeczy, które możesz zrobić z obiektami datetime. Możesz uzyskać poszczególne elementy, takie jak rok, dzień lub minuta. Możesz także uzyskać sformatowany ciąg daty i godziny. Wypróbuj je w trybie interaktywnym:
>>> print when.year
2012
>>> print when.day
24 <- Pobiera poszczególne części obiektu datetime
>>> print when.ctime() <- Wyświetla wersję tekstową daty i godziny
Wed Oct 24 10:45:56 2012
Obiekt datetime ma zarówno datę, jak i godzinę. Jeśli zależy Ci tylko na dacie, istnieje również klasa daty, która ma tylko rok, miesiąc i dzień. Jeśli zależy ci tylko na czasie, istnieje klasa czasu, która ma tylko godzinę, minutę i sekundę. Oto jak wyglądają:
>>> today = datetime.date(2012, 10, 24)
>>> some_time = datetime.time(10, 45, 56)
>>> print today
2012-10-24
>>> print some_time
10:45:56
Podobnie jak w przypadku obiektu datetime, możesz przekazać parametry w innej kolejności, jeśli określisz, która jest która:
>>> today = datetime.date(month=10, day=24, year=2012)
>>> some_time = datetime.time(second=56, hour=10, minute=45)
Istnieje również sposób na rozbicie obiektu datetime na obiekt daty i obiekt czasu:
>>> today = when.date()
>>> some_time = when.time()
Możesz połączyć datę i czas, aby utworzyć obiekt datetime, używając metody Combine () klasy datetime w module datetime:
>>> when = datetime. datetime. combine(today, some_time)
Teraz, gdy już widzieliście, czym jest obiekt datetime i niektóre z jego właściwości, przyjrzymy się, w jaki sposób można porównać dwa z nich, aby znaleźć różnicę między nimi (ile czasu upłynęło między jednym a drugim).
Różnica między dwoma czasami
Dość często w symulacjach musisz wiedzieć, ile czasu minęło. Na przykład w programie Virtual Pet może zaistnieć potrzeba sprawdzenia, ile czasu upłynęło od chwili, gdy zwierzę zostało nakarmione, aby dowiedzieć się, jak bardzo jest głodny. Moduł datetime ma klasę obiektu, która pomoże ci określić różnicę między dwiema datami lub czasami. Klasa nazywa się timedelta. Pamiętaj, że delta oznacza "różnicę". Tak więc timedelta jest różnicą między dwoma czasami. Aby utworzyć timedelta i obliczyć różnicę między dwoma czasami, po prostu je odejmujesz, tak jak poniżej:
>>> import datetime
>>> yesterday = datetime.datetime(2012, 10, 23)
>>> tomorrow = datetime.datetime(2012, 10, 25) <- Pobiera różnicę dwóch dat
>>> print difference
2 days, 0:00:00 <- Jutro i wczoraj są od siebie o 2 dni
>>> print type(difference)
Zauważ, że kiedy odjęliśmy dwa obiekty datetime, to nie otrzymaliśmy innej daty i godziny, a raczej obiekt timedelta. Python robi to automatycznie.
Małe kawałki czasu
Do tej pory szukaliśmy czasu mierzonego w pełnych sekundach. Ale obiekty czasu (data, godzina, data i godzina) są bardziej precyzyjne. Mogą mierzyć do mikrosekundy, co stanowi jedną milionową sekundy. Aby to zobaczyć, wypróbuj metodę now (), która daje aktualny czas zegara komputera:
>>> print datetime.datetime.now ()
2012-10-24 21: 25: 44.343000
Zauważ, że czas nie ma tylko sekund, ma ułamki sekundy:
44.343000
Ostatnie trzy cyfry na moim komputerze będą zawsze równe 0, ponieważ zegar mojego systemu operacyjnego będzie się mieścić tylko w milisekundach (tysięczne części sekundy). Ale to wystarczająco dużo dla mnie! Ważne jest, aby wiedzieć, że chociaż wygląda jak zmiennoprzecinkowe, sekundy są faktycznie przechowywane jako liczba sekund (liczba całkowita) i liczba mikrosekund (liczba całkowita): 44 sekundy i 343 000 mikrosekund. Aby uczynić to float, potrzebujesz małej formuły. Zakładając, że masz obiekt czasu o nazwie some_time i chcesz, aby liczba sekund była zmienna, oto jak wygląda formuła:
seconds_float = some_time.second + some_time.microsecond / float (1000000)
Funkcja float ) służy do upewnienia się, że nie zostaniesz złapany przez getcha z podziałem całkowitoliczbowym. Możesz użyć metody now() i obiektu timedelta, aby przetestować szybkość pisania. Program na listingu 25.2 wyświetla komunikat losowy, a użytkownik musi wpisać tę samą wiadomość. Program sprawdza, jak długo trwa wpisanie i następnie oblicza szybkość pisania. Wypróbuj.
Listing 25.2 Różnice czasu pomiaru - test prędkości pisania
import time, datetime, random <- Używa modułu czasu dla funkcji sleep()
messages = [
"Of all the trees we could've hit, we had to get one that hits back.",
"If he doesn't stop trying to save your life he's going to kill you.",
"It is our choices that show what we truly are, far more than our abilities.",
"I am a wizard, not a baboon brandishing a stick.",
"Greatness inspires envy, envy engenders spite, spite spawns lies.",
"In dreams, we enter a world that's entirely our own.",
"It is my belief that the truth is generally preferable to lies.",
"Dawn seemed to follow midnight with indecent haste."
]
print "Typing speed test. Type the following message. I will time you." <-Używa modułu czasu dla funkcji sleep()
time.sleep(2)
print "\nReady..."
time.sleep(1)
print "\nSet..."
time.sleep(1)
print "\nGo:"
44.343000
seconds_float = some_time.second + some_time.microsecond / float(1000000)
message = random.choice(messages) <-Wybiera wiadomość z listy
print "\n " + message
start_time = datetime.datetime.now() <-Start zegara
typing = raw_input('>')
end_time = datetime.datetime.now() <-Stop zegara
diff = end_time - start_time
typing_time = diff.seconds + diff.microseconds / float(1000000) <- Oblicza czas, który upłynął
cps = len(message) / typing_time
wpm = cps * 60 / 5.0 <- Dla szybkości pisania 1 słowo = 5 znaków
print "\nYou typed %i characters in %.1f seconds." % (len(message),
typing_time)
print "That's %.2f chars per sec, or %.1f words per minute" %(cps, wpm)
if typing == message:
print "You didn't make any mistakes."
else:
print "But, you made at least one mistake."
Jest jeszcze jedna rzecz, którą powinieneś wiedzieć o obiektach timedelta. W przeciwieństwie do obiektów datetime, które mają rok, miesiąc, dzień, godzinę, minutę, sekundę (i mikrosekundy), obiekt timedelta ma tylko dni, sekundy i mikrosekundy. Jeśli chcesz miesiące lub lata, musisz je obliczyć na podstawie liczby dni. Jeśli chcesz minuty lub godziny, musisz je obliczyć z sekund.
Zapisanie czasu do pliku
Jak już wspomnieliśmy na początku , czasami trzeba zapisać wartość czasu w pliku (na dysku twardym), aby można go było zapisać, nawet jeśli program nie działa. Jeśli zapiszesz czas now() za każdym razem, gdy program się zakończy, możesz sprawdzić czas, w którym program zaczyna się od nowa i drukuje wiadomość w ten sposób:
Minęły 2 dni, 7 godzin, 23 minuty od ostatniego użycia tego programu.
Oczywiście większość programów tego nie robi, ale niektóre programy muszą wiedzieć, jak długo są bezczynne lub nie działają. Jednym z przykładów jest program Virtual Pet. Podobnie jak popularne breloki do wirtualnych zwierząt, które były popularne kilka lat temu, możesz chcieć, aby program śledziłnawet wtedy, gdy go nie używasz. Na przykład, jeśli zakończysz program i wrócisz do niego dwa dni później, twój wirtualny zwierzak powinien być bardzo głodny! Jedynym sposobem, aby program wiedział, jak głodny powinien być zwierzak, jest ustalenie, ile czasu upłynęło od ostatniego podania wirtualnego zwierzaka. Obejmuje to czas zamknięcia programu. Istnieje kilka sposobów na zaoszczędzenie czasu na plik. Możesz po prostu napisać łańcuch do pliku, tak jak poniżej:
timeFile.write ("2012-10-24 14:23:37")
Następnie, gdy chcesz odczytać znacznik czasu, użyjesz niektórych metod łańcuchowych, takich jak split(), aby podzielić łańcuch na różne części, takie jak dzień, miesiąc, rok i godzina, minuta, sekunda. To powinno działać dobrze.
Innym sposobem jest użycie modułu pickle, który widziałeś w części 22. Moduł pickle umożliwia zapisanie dowolnego pliku do pliku, w tym obiektów. Ponieważ będziemy używać obiektów datetime, aby śledzić czas, powinno być całkiem łatwe użycie pikli do zapisania ich w pliku i odczytania ich ponownie. Wypróbujmy bardzo prosty przykład, który drukuje komunikat informujący o ostatnim uruchomieniu programu. Będzie musiał wykonać następujące czynności:
• Będzie szukać pliku pickle aby go otworzyć. Python ma moduł o nazwie os (skrót od "system operacyjny"), który może nam powiedzieć, czy plik istnieje. Metoda, której będziemy używać, nazywa się isfile().
• Jeśli plik istnieje, zakładamy, że program działał wcześniej, a my dowiemy się, kiedy ostatnio go uruchomiono (od czasu w pliku pikiet).
• Następnie napiszemy nowy plik pikiet z aktualnym czasem.
• Jeśli program jest uruchamiany po raz pierwszy, nie będzie pliku do pobrania, więc wyświetlimy komunikat informujący o utworzeniu nowego pliku pikiet.
Następujący listing ma kod. Wypróbuj i zobacz, jak to działa.
Listing 25.3 Zapisywanie czasu do pliku za pomocą pickle
import datetime, pickle
import os
first_time = True
if os.path.isfile("last_run.pkl"): <- Sprawdza, czy istnieje plik pickle
pickle_file = open("last_run.pkl", 'r') <- Otwiera plik pickle do czytania (jeśli istnieje)
last_time = pickle.load(pickle_file) <- Usuwa obiekt datetime
pickle_file.close()
print "The last time this program was run was ", last_time
first_time = False
pickle_file = open("last_run.pkl", 'w') <- Otwiera (lub tworzy) plik pikiety do pisania
pickle.dump(datetime.datetime.now(), pickle_file) <- Pobudza obiekt datetime bieżącego czasu
pickle_file.close()
if first_time:
print "Stworono nowy pli pickle ."
Teraz mamy wszystkie elementy potrzebne do stworzenia prostego programu Virtual Pet, który zrobimy w następnej sekcji.
Wirtualne zwierzątko
Zrobimy bardzo uproszczony program Virtual Pet, który, jak wskazaliśmy, jest rodzajem symulacji. Możesz kupić wirtualne zabawki dla zwierząt (takie jak breloczek z małym ekranem). Istnieją również strony internetowe, takie jak Neopets i Webkinz, które są formami wirtualnych zwierząt. Wszystkie te są oczywiście symulacjami. Naśladują zachowanie żywej istoty i stają się głodni, samotni, zmęczeni i tak dalej. Aby utrzymać ich szczęśliwymi i zdrowymi, musisz je karmić, bawić się z nimi lub zabierać je do lekarza.
Nasz wirtualny zwierzak będzie o wiele prostszy i mniej realistyczny niż te, które możesz kupić lub grać online, ponieważ chcę dać ci podstawowy pomysł, a nie chcę, aby kod stał się zbyt skomplikowany. Ale możesz wziąć naszą prostą wersję i rozszerzyć lub ulepszyć ją tak, jak chcesz.
Oto funkcje naszego programu:
• Zwierzę domowe będzie miało cztery różne czynności, które możesz wykonać: nakarm je, spaceruj z nim, baw się nim lub zanieś do lekarza
• Zwierzę domowe może się obudzić lub spać
• Zwierzę domowe z czasem będzie głodniejsze. Możesz zmniejszyć głód poprzez karmienie.
• Zwierzę domowe będzie głodniejsze wolniej, gdy śpi.
• Jeśli zwierzę śpi i wykonujesz jakąś czynność, obudzi się.
• Jeśli zwierzę stanie się zbyt głodne, jego szczęście zmniejszy się.
• Jeśli zwierzę stanie się bardzo, bardzo głodne, jego zdrowie zmniejszy się.
• Chodzenie zwierzęcia zwiększa zarówno jego szczęście, jak i zdrowie.
• Zabawa ze zwierzakiem zwiększy jego szczęście.
• Zabranie zwierzęcia do lekarza zwiększy jego zdrowie.
• Zwierzę domowe będzie miało sześć różnych grafik:
• Jedną do spania
• Jedną na przebudzenie, ale nie robienie niczego
• Jedna do spacerowania
• Jedną do gry
• Jedną do jedzenia
• Jedną za pójście do lekarza
Grafika wykorzysta prostą animację. W następnych kilku sekcjach zobaczysz, jak to zrobić wszystko idzie w jednym programie.
GUI
Stworzyliśmy GUI PyQt dla naszego programu Virtual Pet. Posiada przyciski (właściwie ikony na pasku narzędzi) do wykonywania czynności. Posiada paski postępu dla ważnych statystyk. Jak widać, jest też miejsce, aby pokazać grafikę tego, co robi zwierzę. Zauważ, że pasek tytułu okna mówi Virtual Pet. Jak ustawić tytuł okna? Utwórz nowy formularz w aplikacji Qt Designer i kliknij obiekt MainWindow w Inspektorze obiektów. Następnie w Edytorze właściwości znajdź właściwość o nazwie windowTitle i zmień ją na Virtual Pet (lub cokolwiek chcesz pokazać na pasku tytułu). Grupa przycisków dla działań jest rodzajem widgetu PyQt o nazwie Toolbar. Pasek narzędzi ma w nim akcje, podobnie jak menu, ale różnica w stosunku do paska narzędzi polega na tym, że każda akcja ma powiązaną z nim ikonę. Aby dodać pasek narzędzi, kliknij prawym przyciskiem myszy główne okno i wybierz Dodaj pasek narzędzi. Spowoduje to utworzenie paska narzędzi w górnej części okna, ale będzie on bardzo mały. Znajdź pasek narzędzi w Inspektorze obiektów, kliknij go, a następnie spójrz w Edytorze właściwości na właściwość minimumSize. Ustaw minimalny rozmiar do 100 dla szerokości i 50 dla wysokości. Aby dodać akcje (ikony) do paska narzędzi, kliknij zakładkę Edytor akcji w prawym dolnym rogu Qt Designer.
Kliknij prawym przyciskiem myszy dowolne miejsce w okienku edytora akcji i wybierz opcję Nowy. Otrzymasz okno dialogowe do dodania nowej akcji. Jedyne, co musisz wpisać, to Tekst, a Qt Designer wypełni nazwę obiektu. Następnie znajdź małe pudełko na środku z trzema kropkami (…) i kliknij strzałkę w dół po prawej stronie. Wybierz Wybierz plik i wybierz plik obrazu jaki chcesz użyć na przycisku paska narzędzi. Jest jeszcze jeden krok do dodania nowej ikony paska narzędzi. Po utworzeniu nowej akcji zobaczysz ją na liście w edytorze akcji. Teraz musisz przeciągnąć go na pasek narzędzi. Gdy to zrobisz, grafika wybrana dla nowej akcji pojawi się jako nowa ikona na pasku narzędzi. Qt Designer automatycznie skaluje obraz, aby pasował do paska narzędzi. Liczniki zdrowia to typ widżetu o nazwie Pasek postępu. Główną grafiką jest przycisk Push (tak jak wcześniej), którego właściwości są ustawione w określony sposób, więc nie wygląda jak zwykły przycisk, ale wyświetla obraz. Dodatkowe bity tekstu to widżety etykiet. Możesz stworzyć GUI w ten sposób za pomocą PyQt Designer. Lub możesz załadować ten, który zrobiliśmy (z folderu przykładów) do Qt Designer i zbadać widżety i ich właściwości.
Algorytm
Aby móc napisać kod dla programu Virtual Pet, musimy dokładniej określić zachowanie zwierzęcia. Oto algorytm, którego będziemy używać:
• Podzielimy "dzień" zwierzęcia na 60 części, które będziemy nazywać taktami. Każdy takt będzie miał 5 sekund czasu rzeczywistego, więc "wirtualny dzień" zwierzęcia będzie wynosił 5 minut naszego czasu.
• Zwierzę domowe będzie obudzone przez 48 taktów, a następnie będzie chciało spać przez 12 taktów. Możesz go obudzić, ale może być zrzędliwy!
• Głód, szczęście i zdrowie będą w skali od 0 do 8.
• Po przebudzeniu głód zwiększa się o 1 jednostkę na każdy takt, a szczęście zmniejsza się o 1 jednostkę na każde 2 takty (chyba że chodzi o chodzenie lub zabawę).
• Podczas snu głód zwiększa się o 1 jednostkę na każde 3 takt
• Podczas jedzenia głód zmniejsza się o 2 jednostki na każdy takt.
• Podczas gry szczęście zwiększa się o 1 jednostkę na każdy takt.
• Podczas chodzenia szczęście i zdrowie zwiększają 1 jednostkę na każde 2 takty.
• Kiedy u lekarza, zdrowie wzrasta o 1 jednostkę na każdy takt.
• Jeśli głód wynosi 7, zdrowie zmniejsza się o 1 jednostkę na każde 2 takty.
• Jeśli głód wyniesie 8, zdrowie zmniejsza się o 1 jednostkę za każdy takt.
• Jeśli budzisz się podczas snu, szczęście zmniejsza się o 4 jednostki.
• Gdy program nie działa, zwierzę jest albo obudzone (nic nie robi), albo śpi.
• Po ponownym uruchomieniu programu zliczymy ile ticków minęło i zaktualizuj statystyki dla każdego minionego taktu.
Może się wydawać, że ma wiele reguł, ale w rzeczywistości kodowanie jest bardzo łatwe. W rzeczywistości możesz nawet dodać kilka własnych zachowań, aby uczynić je bardziej interesującym. Kod, z kilkoma wyjaśnieniami, nadchodzi.
Prosta animacja
Do animacji nie zawsze potrzebujesz Pygame. Możesz zrobić prostą animację w PyQt, używając czegoś, co nazywa się timer. Timer to coś, co często tworzy wydarzenie. Następnie piszesz program obsługi zdarzeń, aby coś się stało, gdy zegar się wyłączy.
Przypomina to pisanie programu obsługi zdarzeń dla akcji użytkownika, na przykład kliknięcie przycisku, z wyjątkiem tego, że zdarzenie timera jest generowane przez program, a nie przez użytkownika. Typ zdarzenia generowanego przez timer po jego wygaśnięciu jest zdarzeniem przekroczenia limitu czasu. Nasz GUI Virtual Pet używa dwóch timerów: jednego dla animacji i jednego dla taktów. Animacja zostanie zaktualizowana co pół sekundy (0,5 sekundy), a zaznaczenie nastąpi co 5 sekund. Gdy zegar animacji zgaśnie, zmienimy wyświetlany obraz zwierzęcia. Każde działanie (jedzenie, odtwarzanie itd.) Będzie miało swój własny zestaw obrazów do animacji, a każdy zestaw będzie przechowywany na liście. Animacja przejdzie przez wszystkie obrazy na liście. Program określi, której listy użyć, w zależności od tego, co się dzieje.
Spróbuj, spróbuj ponownie
Będziemy używać innej nowej rzeczy w tym programie. Nazywa się blokiem try-except. Jeśli program zamierza zrobić coś, co może spowodować błąd, dobrze jest mieć jakiś sposób na złapanie błędu i radzenie sobie z nim, zamiast po prostu zatrzymać program. Robi to blok try-except.
Na przykład, jeśli spróbujesz otworzyć plik, a plik nie istnieje, pojawi się błąd. Jeśli nie poradzisz sobie z tym błędem, program zatrzyma się w tym momencie. Ale może chcesz poprosić użytkownika o ponowne wpisanie nazwy pliku, na wypadek gdyby popełniła literówkę. Blok try-except pozwala złapać błąd i kontynuować. Oto jak to wygląda, używając przykładu otwierania pliku:
try:
file = open ("somefile.txt", "r")
except:
print "Nie można otworzyć pliku. Czy chcesz ponownie wprowadzić nazwę pliku?"
Rzecz, którą chcesz wypróbować (która może spowodować błąd), przechodzi do bloku try. W tym przypadku próbuje otworzyć plik. Jeśli tak się stanie bez błędu, część ecept zostanie pominięta. Jeśli kod w bloku try powoduje błąd, kod w bloku except działa. Kod w bloku except informuje program, co zrobić, jeśli wystąpił błąd. Możesz myśleć o tym w ten sposób:
try:
aby to zrobić (nie rób nic innego …)
except:
jeśli wystąpił błąd, zrób to
Instrukcje try-except są sposobem Pythona na robienie tego, co ogólnie nazywa się obsługą błędów. Obsługa błędów umożliwia pisanie kodu, w którym może dojść do błędów - nawet w przypadku rzeczy, które normalnie zatrzymałyby program - aby program nadal działał. My nie będziemy mówić o obsłudze błędów szczegółowo, ale chciałem pokazać podstawy, ponieważ zobaczysz je w kodzie Virtual Pet. Spójrzmy na kod pokazany na listingu 25.4. Notatki wyjaśniają większość tego, co się dzieje. Ten jest nieco długi. Spróbuj go uruchomić, a następnie spójrz na kod i upewnij się, że rozumiesz, jak to działa.
Listing 25.4 VirtualPet.py
import sys, pickle,datetime
from PyQt4 import QtCore, QtGui, uic
formclass, baseclass = uic.loadUiType("mainwindow.ui")
class MyForm(baseclass, formclass):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.doctor = False
self.walking = False
self.sleeping = False
self.playing = False
self.eating = False
self.time_cycle = 0
self.hunger = 0
self.happiness = 8
self.health = 8
self.forceAwake = False
self.sleepImages = ["sleep1.gif","sleep2.gif","sleep3.gif",
"sleep4.gif"]
self.eatImages = ["eat1.gif", "eat2.gif"]
self.walkImages = ["walk1.gif", "walk2.gif", "walk3.gif",
"walk4.gif"]
self.playImages = ["play1.gif", "play2.gif"]
self.doctorImages = ["doc1.gif", "doc2.gif"]
self.nothingImages = ["pet1.gif", "pet2.gif", "pet3.gif"]
self.imageList = self.nothingImages
self.imageIndex = 0
self.actionStop.triggered.connect(self.stop_Click)
self.actionFeed.triggered.connect(self.feed_Click)
self.actionWalk.triggered.connect(self.walk_Click)
self.actionPlay.triggered.connect(self.play_Click)
self.actionDoctor.triggered.connect(self.doctor_Click)
self.myTimer1 = QtCore.QTimer(self)
self.myTimer1.start(500)
self.myTimer1.timeout.connect(self.animation_timer)
self.myTimer2 = QtCore.QTimer(self)
self.myTimer2.start(5000)
self.myTimer2.timeout.connect(self.tick_timer)
filehandle = True
try:
file = open("savedata_vp.pkl", "r")
except:
filehandle = False
if filehandle:
save_list = pickle.load(file) <- Czyta z pliku pickle, jeśli jest otwarty
file.close()
else:
save_list = [8, 8, 0, datetime.datetime.now(), 0] <- /Używa wartości domyślnych, jeśli plik pickle nie - jest otwarty
self.happiness = save_list[0]
self.health = save_list[1]
self.hunger = save_list[2]
timestamp_then = save_list[3]
self.time_cycle = save_list[4]
difference = datetime.datetime.now() - timestamp_then
ticks = difference.seconds / 50
for i in range(0, ticks):
self.time_cycle += 1
if self.time_cycle == 60:
self.time_cycle = 0
if self.time_cycle <= 48: <- Budzenie
self.sleeping = False
if self.hunger < 8:
self.hunger += 1
else: <- Spanie
self.sleeping = True
if self.hunger < 8 and self.time_cycle % 3 == 0:
self.hunger += 1
if self.hunger == 7 and (self.time_cycle % 2 ==0) \
and self.health > 0:
self.health -= 1
if self.hunger == 8 and self.health > 0:
self.health -=1
if self.sleeping:
self.imageList = self.sleepImages
else:
self.imageList = self.nothingImages
def sleep_test(self):
if self.sleeping:
result = (QtGui.QMessageBox.warning(self, 'WARNING', <-Typ okna dialogowego
"Are you sure you want to wake your pet up? He'll be unhappy about it!",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, <-Przyciski do pokazania
QtGui.QMessageBox.No)) <- Przycisk domyślny
if result == QtGui.QMessageBox.Yes:
self.sleeping = False
self.happiness -= 4
self.forceAwake = True
return True
else:
return False
else:
return True
def doctor_Click(self):
if self.sleep_test():
self.imageList = self.doctorImages
self.doctor = True
self.walking = False
self.eating = False
self.playing = False
def feed_Click(self):
if self.sleep_test():
self.imageList = self.eatImages
self.eating = True
self.walking = False
self.playing = False
self.doctor = False
def play_Click(self):
if self.sleep_test():
self.imageList = self.playImages
self.playing = True
self.walking = False
self.eating = False
self.doctor = False
def walk_Click(self):
if self.sleep_test():
self.imageList = self.walkImages
self.walking = True
self.eating = False
self.playing = False
self.doctor = False
def stop_Click(self):
if not self.sleeping:
self.imageList = self.nothingImages
self.walking = False
self.eating = False
self.playing = False
self.doctor = False
def animation_timer(self):
if self.sleeping and not self.forceAwake:
self.imageList = self.sleepImages
self.imageIndex += 1
if self.imageIndex >= len(self.imageList):
self.imageIndex = 0
icon = QtGui.QIcon()
current_image = self.imageList[self.imageIndex]
icon.addPixmap(QtGui.QPixmap(current_image),
QtGui.QIcon.Disabled, QtGui.QIcon.Off)
self.petPic.setIcon(icon)
self.progressBar_1.setProperty("value", (8-self.hunger)*(100/8.0))
self.progressBar_2.setProperty("value", self.happiness*(100/8.0))
self.progressBar_3.setProperty("value", self.health*(100/8.0))
def tick_timer(self): <- Początek głównego 5-sekundowego programu obsługi zdarzeń
self.time_cycle += 1
if self.time_cycle == 60:
self.time_cycle = 0
if self.time_cycle <= 48 or self.forceAwake:
self.sleeping = False
else:
self.sleeping = True
if self.time_cycle == 0:
self.forceAwake = False
if self.doctor:
self.health += 1
self.hunger += 1
elif self.walking and (self.time_cycle % 2 == 0):
self.happiness += 1
self.health += 1
self.hunger += 1
elif self.playing:
self.happiness += 1
self.hunger += 1
elif self.eating:
self.hunger -= 2
elif self.sleeping:
if self.time_cycle % 3 == 0:
self.hunger += 1
else:
self.hunger += 1
if self.time_cycle % 2 == 0:
self.happiness -= 1
if self.hunger > 8: self.hunger = 8
if self.hunger < 0: self.hunger = 0
if self.hunger == 7 and (self.time_cycle % 2 ==0) :
self.health -= 1
if self.hunger == 8:
self.health -=1
if self.health > 8: self.health = 8
if self.health < 0: self.health = 0
if self.happiness > 8: self.happiness = 8
if self.happiness < 0: self.happiness = 0
self.progressBar_1.setProperty("value", (8-self.hunger)*(100/8.0))
self.progressBar_2.setProperty("value", self.happiness*(100/8.0))
self.progressBar_3.setProperty("value", self.health*(100/8.0))
def closeEvent(self, event):
file = open("savedata_vp.pkl", "w")
save_list = [self.happiness, self.health, self.hunger, \ <-Znak kontynuacji linii
datetime.datetime.now(), self.time_cycle]
pickle.dump(save_list, file)
event.accept()
def menuExit_selected(self):
self.close()
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
app.exec_()
Funkcja sleep_test () używa okna dialogowego PyQt "komunikat ostrzegawczy". Kilka parametrów informuje, które przyciski mają być wyświetlane, a który z nich jest domyślny. Notatki w wykazie 24.4 wyjaśniają to. Gdy pojawi się okno dialogowe (gdy próbujesz obudzić zwierzaka), wygląda to tak:
Nie martw się, jeśli nie rozumiesz całego tego kodu. Jeśli chcesz, możesz dowiedzieć się więcej o PyQt samodzielnie. Dobrym miejscem do rozpoczęcia jest strona internetowa PyQt: www.riverbankcomputing.co.uk/software/pyqt/intro.
W tej części tylko zarysowaliśmy powierzchnię tego, co można zrobić za pomocą symulacji komputerowych. Widziałeś podstawowe idee symulowania rzeczywistych warunków, takich jak grawitacja i czas, ale symulacje komputerowe są szeroko stosowane w nauce, inżynierii, medycynie, finansach i wielu innych dziedzinach. Wiele z nich jest bardzo złożonych, a ich uruchomienie nawet na najszybszych komputerach zajmuje dni lub tygodnie. Ale nawet mały wirtualny zwierzak w pęku kluczy twojego przyjaciela jest rodzajem symulacji, a czasami najciekawsze są najprostsze symulacje.
Czego się nauczyłeś?
• Jakie są symulacje komputerowe i dlaczego są używane
• Jak symulować grawitację, przyspieszenie i siłę
• Jak śledzić i symulować czas
• Jak zapisywać znaczniki czasu w pliku za pomocą pikli
• Trochę o obsłudze błędów (try-except)
• Jak używać zegarów do generowania okresowych zdarzeń
Sprawdź swoją wiedzę
1 Wymień trzy powody wykorzystania symulacji komputerowych.
2 Wymień trzy rodzaje symulacji komputerowych, które widziałeś lub które znasz.
3 Jaki obiekt jest używany do przechowywania różnicy między dwiema datami lub czasami?
Wypróbuj to
1 Dodaj test "poza orbitą" do programu Lunar Lander. Jeśli statek wychodzi z górnej części okna, a prędkość przekracza + 100 m / s, zatrzymaj program i wyświetl komunikat w następujący sposób: "Uciekłeś przed grawitacją Księżyca. Bez lądowania dzisiaj! "
2 Dodaj opcję dla użytkownika, aby ponownie zagrał Lunar Lander po wylądowaniu statku, bez konieczności ponownego uruchamiania programu.
3 Dodaj przycisk pauzy do GUI Virtual Pet. Powinno to zatrzymać lub "zamrozić" czas zwierzęcia, które powinno pozostać zamrożone nawet wtedy, gdy program nie jest uruchomiony. (Wskazówka: oznacza to, że prawdopodobnie musisz zapisać stan "wstrzymanego" w pliku pikiet.)
Wcześniej napisałeś grę Narciarz (miejmy nadzieję!) I uruchomiłeś ją. W kodzie było kilka notatek, ale nie daliśmy żadnych innych wyjaśnień. Wpisanie kodu i uruchomienie go, nawet jeśli nie rozumiesz go całkowicie, może być świetnym sposobem na ogólne nauczenie się programowania lub nauki konkretnego języka. Ale teraz, gdy wiesz więcej o Pythonie, może jesteś trochę ciekawy, jak działa program Narciarz. W tej części omówimy to szczegółowo.
Narciarz
Najpierw zaprogramujemy narciarza. Kiedy grałeś w program Narciarz, prawdopodobnie zauważyłeś, że narciarz porusza się tylko w przód i w dół po ekranie. Nie porusza się w górę i w dół. Złudzenie jazdy na nartach "w dół" wzgórza tworzy sceneria (drzewa i flagi) przewijająca się w przeszłość. Narciarz zjeżdżający ze wzgórza ma pięć różnych obrazów: jeden do jazdy w dół, dwa do skrętu w lewo (trochę i dużo) i dwa do skrętu w prawo (trochę i dużo). Na początku programu stworzyliśmy listę tych obrazów i umieściliśmy je na liście w określonej kolejności:
skier_images = ["skier_down.png",
"skier_right1.png", "skier_right2.png",
"skier_left2.png", "skier_left1.png"]
Zobaczysz, dlaczego to zamówienie ma znaczenie. Aby śledzić drogę narciarza, używamy zmiennej o nazwie angle. Ma wartości od -2 do +2 w następujący sposób:
• -2 = Skręt ostry w lewo
• -1 = toczenie trochę w lewo
• 0 = Idąc prosto w dół
• +1 = Obrót trochę w prawo
• +2 = Skręt w prawo
(Zauważ, że prawy i lewy odnoszą się do ekranu po prawej i lewej stronie, jak je widzimy, nie narciarz jest po prawej i lewej stronie). Używamy wartości kąta, aby wiedzieć, którego obrazu użyć. W rzeczywistości możemy bezpośrednio użyć wartości kąta jako indeksu do listy obrazów:
• skier_images [0] to ten, w którym idzie prosto w dół
• skier_images [1] to ten, w którym trochę się kręci
• skier_images [2] to ten, w którym skręca ostro w prawo
Teraz przychodzi trudna część. Pamiętasz , kiedy mówiliśmy o listach, że powiedzieliśmy, że indeks listy negatywnej zawinie i zacznie odliczać wstecz od końca listy? Więc w tym przypadku
• skier_images [-1] to ten, w którym skręca trochę w lewo (zwykle nazywano go skier_images [4]).
• skier_images [-2] to ten, w którym skręca ostro w lewo (zwykle nazywano go skier_images [3]).
Teraz możesz zobaczyć, dlaczego uporządkowaliśmy obrazy na liście w określonej kolejności:
• angle = +2 (ostry obrót w prawo) = skier_images [2]
• angle = +1 (skręcając trochę w prawo) = skier_images [1]
• angle = 0 (przejście w dół) = skier_images [0]
• angle = -1 (skręcając trochę w lewo) = skier_images [-1] (znany również jako
• angle = -2 (skręt ostry w lewo) = skier_images [-2] (znany również jako narciarz_images [3]
Tworzymy klasę dla narciarza, który jest Duszkiem Pygame. Narciarz ma zawsze 100 pikseli od góry okna , i zaczynamy go w środku okna, od lewej do prawej, która wynosi x = 320, ponieważ okno ma szerokość 640 pikseli, więc jego początkowa pozycja to [320, 100]. Pierwsza część narciarza definicja klasy wygląda tak:
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image =
pygame.image.load("skier_down.png")
self.rect = self.image.get_rect()
self.rect.center = [320, 100]
self.angle = 0
Wykonujemy klasową metodę obracania narciarza, który zmienia kąt, ładuje prawidłowy obraz, a także ustawia prędkość narciarza. Prędkość ma składniki x i y. Przesuwamy tylko sprite narciarza w lewo i w prawo (prędkość x). Ale prędkość y określa szybkość przewijania scenerii (jak szybko "schodzi" w dół wzgórza). Kiedy idzie prosto w dół, jego prędkość w dół jest szybsza; a kiedy się obraca, jego prędkość w dół jest wolniejsza. Formuła prędkości wygląda tak:
speed = [self.angle, 6 - abs (self.angle) * 2]
Abs w tej linii kodu otrzymuje bezwzględną wartość kąta. Oznacza to, że ignorujemy znak (+ lub -). Dla prędkości w dół, nie obchodzi nas, w którym kierunku skręca narciarz, musimy tylko wiedzieć, ile się obraca. Cała metoda obracania wygląda tak:
def turn(self, direction):
self.angle = self.angle + direction
if self.angle < -2: self.angle = -2
if self.angle > 2: self.angle = 2
center = self.rect.center
self.image = pygame.image.load(skier_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle, 6 - abs(self.angle) * 2]
return speed
Potrzebujemy również metody przesunięcia narciarza w tę i z powrotem. Dzięki temu upewni się, że nie minie krawędzi okna:
def move(self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 20: self.rect.centerx = 20
if self.rect.centerx > 620: self.rect.centerx = 620
Używamy klawiszy strzałek, aby sterować narciarzem w lewo i prawo, więc dodamy nasz kod inicjujący Pygame i kod pętli zdarzeń, który daje nam działający program, który ma tylko narciarza. Jest to pokazane w poniższym listingu .
Listing 26.1 Budowanie gry Narciarz - tylko narciarz
import pygame, sys, random
skier_images = ["skier_down.png",
"skier_right1.png", "skier_right2.png",
"skier_left2.png", "skier_left1.png"]
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("skier_down.png")
self.rect = self.image.get_rect()
self.rect.center = [320, 100]
self.angle = 0
def turn(self, direction):
self.angle = self.angle + direction
if self.angle < -2: self.angle = -2
if self.angle > 2: self.angle = 2
center = self.rect.center
self.image = pygame.image.load(skier_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle, 6 - abs(self.angle) * 2]
return speed
def move(self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 20: self.rect.centerx = 20
if self.rect.centerx > 620: self.rect.centerx = 620
def animate():
screen.fill([255, 255, 255])
screen.blit(skier.image, skier.rect)
pygame.display.flip()
pygame.init()
screen = pygame.display.set_mode([640,640])
clock = pygame.time.Clock()
skier = SkierClass()
speed = [0, 6]
running = True
while running:
clock.tick(30)
for event in pygame.event.get(): <- Sprawdź, czy naciśnięto klawisze
if event.type == pygame.QUIT: running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: <- Lewa strzałka skręca w lewo
speed = skier.turn(-1)
elif event.key == pygame.K_RIGHT: <-Prawa strzałka skręca w prawo
speed = skier.turn(1)
skier.move(speed)
animate()
pygame.quit()
Jeśli uruchomisz aukcję 26.1, zobaczysz tylko narciarza (bez wyniku, bez przeszkód), a będziesz mógł go obrócić w lewo i prawo.
Przeszkody
Następną rzeczą, jaką zrobimy, jest sprawdzenie, jak tworzyć przeszkody - drzewa i flagi. W tej części, aby zachować prostotę, zaczniemy od nowa - bez narciarza, tylko przeszkody. Umieścimy kod narciarza razem z kodem przeszkody na końcu. Okno gry dla narciarzy wynosi 640 x 640 pikseli. Aby zachować prostotę i zapobiegać mając zbyt blisko siebie przeszkody, dzielimy okno na siatkę 10 x 10. Na siatce znajduje się 100 pól. Każde miejsce na siatce ma rozmiar 64 x 64 pikseli. Ponieważ nasze duchy przeszkód nie są tak duże, będzie między nimi trochę miejsca, nawet jeśli znajdują się w sąsiednich polach na siatce.
Tworzenie indywidualnych przeszkód
Najpierw musimy stworzyć indywidualne przeszkody. Tworzymy klasę do tego, którą nazywamy ObstacleClass. Tak jak narciarz, to jest Duszek Pygame:
class ObstacleClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, type):
pygame.sprite.Sprite.__init__(self)
self.image_file = image_file
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.center = location
self.type = type
self.passed = False
Tworzenie mapy przeszkód
Utwórzmy teraz przeszkody o wartości jednego ekranu - wystarczającej do wypełnienia jednej siatki 10 x 10, która wypełnia ekran 640 x 640 pikseli. Losowo posypujemy 10 przeszkód (flag i drzew) na 100 kwadratach siatki. Każda przeszkoda może być flagą lub drzewem. Moglibyśmy skończyć z 2 flagami i 8 drzewami, 7 flag i 3 drzewa lub dowolna kombinacja, która sumuje się do 10. Są losowo wybierane. Lokalizacje na siatce są również losowe. Jedyne, na co musimy uważać, to że nie próbujemy umieszczać dwóch przeszkód w tym samym miejscu. Śledzimy więc, z jakich lokalizacji korzystaliśmy. Zmienne lokalizacje to lista lokalizacji, które już wykorzystaliśmy. Umieszczając nową przeszkodę w określonym miejscu, najpierw sprawdzamy, czy jest już taka w tej lokalizacji:
def create_map():
global obstacles
locations = []
for i in range(10): <- 10 przeszkód na ekran
row = random.randint(0, 9)
col = random.randint(0, 9)
location = [col * 64 + 32, row * 64 + 32 + 640] <- (x,y) położenia dla przeszkody
if not (location in locations): <-Upewnij się, że nie mamy 2 przeszkód w tym samym miejscu
locations.append(location)
type = random.choice(["tree", "flag"])
if type == "tree": img = "skier_tree.png"
elif type == "flag": img = "skier_flag.png"
obstacle = ObstacleClass(img, location, type)
obstacles.add(obstacle)
Kiedy gra się zaczyna, nie chcemy, aby ekran był pełen przeszkód. Chcemy, aby zaczynał się pusty, a przeszkody zaczęły pojawiać się od dołu. Tworzymy więc każdy ekran scenerii "poniżej" dolnej części okna. Aby to zrobić, dodajemy 640 (wysokość naszego okna) do wartości y każdej przeszkody. Kiedy gra się zaczyna, chcemy, aby przeszkody zaczęły się przewijać. Aby to zrobić, zmieniamy pozycję y każdej przeszkody. Ile to zmieniamy, zależy od widocznej prędkości narciarza w dół wzgórza. Umieszczamy to w metodzie update (), która jest częścią ObstacleClass:
def update(self):
global speed
self.rect.centery -= speed[1]
Zmienna prędkość to prędkość narciarza, która jest zmienną globalną. prędkość ma zarówno prędkość x i y narciarza, więc używamy indeksu [1], aby uzyskać tylko prędkość y (pionową). Ponieważ nasz pierwszy ekran z przeszkodami przenosi go na ekran, musimy stworzyć więcej z nich, kolejny ekran, na dole. Skąd wiemy, kiedy to jest? Mamy zmienną o nazwie map_position, która śledzi przewijanie scenerii. Robimy to w głównej pętli:
running = True
while running:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
map_position += speed[1] <-Śledź, jak daleko przewinęła się mapa
if map_position >= 640:
create_map()
map_position = 0
Mamy funkcję animate (), podobnie jak w naszym kodzie tylko narciarzy, aby przerysować wszystko. W sumie kod tylko przeszkody wygląda tak.
Listing 26.2 Budowanie gry narciarz - tylko przeszkody
import pygame, sys, random
class ObstacleClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, type):
pygame.sprite.Sprite.__init__(self)
self.image_file = image_file
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.center = location
self.type = type
self.passed = False
def update(self):
global speed
self.rect.centery -= speed[1]
def create_map():
global obstacles
locations = []
for i in range(10): <- 10 przeszkód na ekran
row = random.randint(0, 9)
col = random.randint(0, 9)
location = [col * 64 + 32, row * 64 + 32 + 640]
if not (location in locations): <- Zapobiegaj 2 przeszkodom w tym samym miejscu
locations.append(location)
type = random.choice(["tree", "flag"])
if type == "tree": img = "skier_tree.png"
elif type == "flag": img = "skier_flag.png"
obstacle = ObstacleClass(img, location, type)
obstacles.add(obstacle)
def animate():
screen.fill([255, 255, 255])
obstacles.draw(screen)
pygame.display.flip()
pygame.init()
screen = pygame.display.set_mode([640,640])
clock = pygame.time.Clock()
speed = [0, 6]
obstacles = pygame.sprite.Group()
map_position = 0
create_map()
running = True
while running:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
map_position += speed[1] <-Śledź, jak daleko przewinęły się przeszkody
if map_position >= 640:
create_map() <- Utwórz nowy blok przeszkód na dole
map_position = 0
obstacles.update()
animate()
pygame.quit()
Jeśli uruchomisz listing 26.2, powinieneś zobaczyć drzewa i flagi przewijające się w górę ekranu
Jeśli gra działa przez długi czas, w końcu tworzymy dużą liczbę przeszkody sprite. Może to spowodować, że nasz program zwolni lub zabraknie pamięci w pewnym momencie. Więc musimy trochę posprzątać. Śledź, jak daleko przewinęły się przeszkody Utwórz nowy blok przeszkód na dole. W metodzie update () dla klasy przeszkód dodajemy test, aby sprawdzić, czy przeszkoda zniknęła z górnej części ekranu. Jeśli tak, pozbywamy się go. Pygame ma wbudowaną metodę do tego celu, zwaną kill (). Nowa metoda update () wygląda tak:
def update(self):
global speed
self.rect.centery -= speed[1]
if self.rect.centery < -32: <- Sprawdź, czy ikonka jest poza górną częścią ekranu
self.kill() <- Pozbądź się tego
Teraz jesteśmy gotowi połączyć narciarza i przeszkody:
• Potrzebujemy zarówno SkierClass, jak i ObstacleClass.
• Nasza funkcja animacji () musi przyciągać zarówno narciarza, jak i przeszkody.
• Nasz kod inicjujący musi utworzyć narciarza i mapę początkową.
• Główna pętla musi obejmować obsługę zdarzeń narciarza i tworzenie nowych bloków przeszkód.
Zasadniczo jest to połączenie listingu 26.1 i aukcji 26.2. Wynik jest pokazany na liście 26.3.
Listing 26.3 Narciarz i przeszkody razem
import pygame, sys, random
skier_images = ["skier_down.png", "skier_right1.png", "skier_right2.png",
"skier_left2.png", "skier_left1.png"]
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("skier_down.png")
self.rect = self.image.get_rect()
self.rect.center = [320, 100]
self.angle = 0
def turn(self, direction):
self.angle = self.angle + direction
if self.angle < -2: self.angle = -2
if self.angle > 2: self.angle = 2
center = self.rect.center
self.image = pygame.image.load(skier_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle, 6 - abs(self.angle) * 2]
return speed
def move(self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 20: self.rect.centerx = 20
if self.rect.centerx > 620: self.rect.centerx = 620
class ObstacleClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, type):
pygame.sprite.Sprite.__init__(self)
self.image_file = image_file
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.center = location
self.type = type
self.passed = False
def update(self):
global speed
self.rect.centery -= speed[1]
if self.rect.centery < -32:
self.kill()
def create_map():
global obstacles
locations = []
for i in range(10):
row = random.randint(0, 9)
col = random.randint(0, 9)
location = [col * 64 + 32, row * 64 + 32 + 640]
if not (location in locations):
locations.append(location)
type = random.choice(["tree", "flag"])
if type == "tree": img = "skier_tree.png"
elif type == "flag": img = "skier_flag.png"
obstacle = ObstacleClass(img, location, type)
obstacles.add(obstacle)
def animate():
screen.fill([255, 255, 255])
obstacles.draw(screen)
screen.blit(skier.image, skier.rect)
pygame.display.flip()
pygame.init()
screen = pygame.display.set_mode([640,640])
clock = pygame.time.Clock()
points = 0
speed = [0, 6]
skier = SkierClass() <-Stwórz narciarza
obstacles = pygame.sprite.Group()
create_map()
map_position = 0
running = True
while running:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed = skier.turn(-1)
elif event.key == pygame.K_RIGHT:
speed = skier.turn(1)
skier.move(speed)
map_position += speed[1]
if map_position >= 640:
create_map()
map_position = 0
obstacles.update()
animate()
pygame.quit()
Jeśli uruchomisz listing 26.3, będziesz mógł skierować narciarza w dół wzgórza, a zobaczysz przeszkody przewijające się w przeszłości. Zauważysz również, że prędkość narciarza, zarówno w prawo, jak iw dół, zależy od tego, w którą stronę się odwrócił. Zbliżamy się. Ostatnie dwa potrzebne nam elementy to:
? Wykrywanie, kiedy narciarz uderza w drzewo lub podnosi flagę
? Aby śledzić wynik i wyświetlać go
Widziałeś, jak wykonać wykrywanie kolizji . Kod w listingu 26.3 już umieszcza duszki przeszkód w grupie sprite, więc możemy użyć funkcji spritecollide(), aby wykryć, kiedy sprite narciarza uderza w drzewo lub ikonkę flagi. Następnie musimy dowiedzieć się, co to jest (drzewo lub flaga) i postępować właściwie:
? Jeśli jest to drzewo, zmień obraz narciarza na obraz "zderzenia" i odlicz 100 punktów od wyniku.
• Jeśli jest to flaga, dodaj 10 punktów do wyniku i usuń flagę z ekranu.
Kod do zrobienia w głównej pętli wygląda tak:
hit = pygame.sprite.spritecollide(skier, obstacles, False) <-Sprawdź kolizje
if hit:
if hit[0].type == "tree" and not hit[0].passed:
points = points - 100
skier.image = pygame.image.load("skier_crash.png")
animate()
pygame.time.delay(1000)
skier.image = pygame.image.load("skier_down.png")
skier.angle = 0
speed = [0, 6]
hit[0].passed = True <- Pamiętaj, że już uderzyliśmy w to drzewo
elif hit[0].type == "flag" and not hit[0].passed:
points += 10
hit[0].kill() <- Usuń flagę
Czego się nauczyłeś?
• Jak działają wszystkie części programu Narciarz
• Jak utworzyć przewijane tło
Wypróbuj to
1 Spróbuj zmodyfikować narciarza, aby stawał się trudniejszy w miarę kontynuowania gry. Oto kilka sugestii, co można spróbować:
• Zwiększ prędkość, gdy gra trwa.
• Dodaj więcej drzew w dół wzgórza.
• Dodaj "lód", co utrudnia obracanie.
2 Program SkiFree, który był inspiracją dla Narciarza, miał Obrzydliwego Bałwana, który pojawił się przypadkowo i gonił narciarza. Jeśli czeka Cię prawdziwe wyzwanie, spróbuj dodać coś takiego do programu Narciarz. Musisz znaleźć lub utworzyć nowy obraz ikonki i dowiedzieć się, jak zmodyfikować kod, aby uzyskać pożądane zachowanie.
Omówiliśmy, jak tworzyć własne gry. Jedną z rzeczy, o których jeszcze nie mówiliśmy, jest sztuczna inteligencja gry (AI). Prawie każda gra od czasów Pac-Mana ma jakąś formę sztucznej inteligencji, która atakuje gracza, i ta część pokaże jak samemu to zrobić.
Bitwa Pythona
AI, które stworzymy, będzie częścią gry o nazwie Python Battle. Python Battle to prosta gra z prostymi zasadami. W każdej turze możesz poruszać się do przodu, obracać się w kierunku innego kierunku lub atakować. Gdy jeden bot atakuje innego, bot, który został zaatakowany traci jeden "punkt zdrowia". Pierwszy bot, który straci wszystkie swoje punkty życia, traci grę. Boty mogą atakować tylko plac bezpośrednio przed nimi. Ale Python Battle ma jeden zwrot: to gra rozgrywana przez roboty. Musisz kodować strategię lub AI, aby kontrolować swojego bota, a następnie uruchomić Python Battle, aby zobaczyć, jak dobrze radzi sobie z innym AI. Oczywiście kod AI i sama Python Battle są napisane w Pythonie. Zwróć uwagę, że Python Battle powinien być dołączony do twojego komputera, jeśli uruchomiłeś instalatora naszej książki. Włączyłem trzy programy AI do wypróbowania: CircleAI (dyski w kółkach wokół pola gry), RandomAI (ruchy i obroty losowo) oraz NullAI (nic nie robi). Spróbujmy uruchomić je przeciwko sobie, aby zobaczyć, kto wygra.
Uruchamianie Bitwy Pythona
Wykonaj następujące kroki:
1 Upewnij się, że skrypty AI, których chcesz użyć, znajdują się w tym samym folderze co PythonBattle.py.
2 Uruchom PythonBattle.py.
3 Zobaczysz monit:
Wprowadź nazwę skryptu AI, którego chcesz użyć. Pozostaw rozszerzenie .py poza końcem. Na przykład, jeśli chcesz przetestować CircleAI.py, wpisz polecenie circleai.
4 Zrób to samo dla niebieskiej sztucznej inteligencji.
5 Obserwuj bitwę, aby zobaczyć, kto wygra!
6 Zamknij okno Pygame na końcu.
Zasady gry
Teraz, gdy obejrzałeś kilka bitew Pythona, przyjrzyjmy się bliżej, jak działa gra. W każdej turze robot może wykonać jedną z sześciu rzeczy:
• Przejdź do przodu o jedno miejsce
• Przejdź do tyłu o jedno miejsce
• Skręć w lewo
• Skręć w prawo
• ? Zaatakuj miejsce bezpośrednio przed nim
• Nie ruszaj się
Ponadto robot może patrzeć na tablicę w dowolnym momencie. Celem gry jest skuteczne zaatakowanie wroga 10 razy. Czy podczas oglądania gry CircleAI i RandomAI grałeś przeciwko sobie, czy zauważyłeś czerwone i niebieskie kwadraty? Kiedy robot przejeżdża przez kwadrat, ten kwadrat zmienia kolor na taki sam jak bot (czerwony lub niebieski). Po 1000 turach, jeśli żaden z robotów nie zaatakował drugiego, lub roboty są związane w punktach zdrowia, wygrywa ten, kto ma najwięcej kwadratów w swoim kolorze.
Tworzenie Robota Bitewnego Pythona
Zróbmy robota, który spróbuje pokonać CircleAI i RandomAI. Pierwszym krokiem w tworzeniu robota jest opracowanie strategii. Dla naszego pierwszego Robota Pythonowego powinniśmy zacząć od prostej strategii:
1 Jeśli stanę naprzeciw wroga, powinienem go zaatakować.
2 Jeśli stoję twarzą do ściany, powinienem się odwrócić.
3 W przeciwnym razie powinienem jechać naprzód.
Chociaż nie jest to najbardziej zaawansowana strategia, może po prostu pokonać CircleAI. Jeśli tak nie jest, zawsze możemy cofnąć się i nieco go ulepszyć. Drugim krokiem jest rozpoczęcie kodowania robota. Utwórz nowy plik Pythona (zadzwonię do mojego better_than_circleai.py) i wpisz ten kod:
class AI:
def __init__(self):
pass
def turn(self):
pass
To jest podstawowy kod, od którego muszą zaczynać się wszystkie roboty. Funkcja __init __ () jest wywoływana, gdy AI zostanie utworzona na początku gry. Funkcja turn () jest wywoływana co rundę i decyduje o tym, co robi robot. Klasa musi być nazywana AI lub Python Battle nie będzie wiedział, gdzie znaleźć kod AI. Kolejnym krokiem w kodowaniu robota jest dodanie kodu, który sprawia, że bot realizuje naszą strategię. Użyjesz tych funkcji, aby robot się poruszał:
• self.robot.lookInFront ()
• self.robot.turnRight ()
• self.robot.turnLeft ()
• self.robot.goForth ()
• self.robot.attack ()
Metody te muszą być nazywane self.robot.xx (), ponieważ self odnosi się do AI, a nie robota, który kontroluje AI, a obiekt AI nie porusza się ani nie atakuje. Obiekt AI jest odpowiedzialny za powiedzenie robotowi, co ma robić, a obiekt robota zajmuje się ruchem i atakowaniem. Zacznijmy pisać metodę turn (). Usuń hasło i dodaj to do swojego kodu:
self.robot.goForth ()
Jeśli teraz przetestujesz robota, zobaczysz, że stara się iść do przodu w każdej turze. To szybko powoduje uderzenie w ścianę boiska. Jeśli przeciwnik przeszkodzi, robot po prostu przestaje się poruszać. Możesz to naprawić używając self.robot.lookInFront (). Ta funkcja zwraca "bota", jeśli na wprost znajduje się robot, który możesz zaatakować. Zmień funkcję turn (), aby wyglądała następująco:
if self.robot.lookInFront() == "bot":
self.robot.attack()
else:
self.robot.goForth()
Teraz, jeśli coś stanie na drodze twojemu robotowi, robot atakuje. Ale jeśli robot uderzy w ścianę, nadal się zatrzymuje. self.robot.lookInFront () zwraca "ścianę", jeśli stoisz przy ścianie. Dodaj to do swojej funkcji turn () między self.robot.attack () a innymi:
elif self.robot.lookInFront () == "wall":
self.robot.turnRight ()
Teraz, jeśli uruchomisz kod, robot zacznie krążyć! Gdy trafi w ścianę, skręca w prawo, a kiedy uderza w następną ścianę, ponownie skręca w prawo i tak dalej. Chcesz, aby bot obrócił się dookoła, gdy uderzy w ścianę, i potrzebuje dwóch prawych obrotów, aby obrócić się dookoła. Tak więc, gdy robot uderza w ścianę, musi skręcić w prawo. Następnie w następnej rundzie musi ponownie skręcić w prawo. Zasadniczo, bot musi pamiętać, że jest w trakcie zawracania. Możesz to zrobić, podając AI nową właściwość (zmienną), aby śledzić, co robi. Dodajmy nową linię do funkcji __init __ ():
self.currentlyDoing = "forward"
To powie robotowi, że po uruchomieniu musi iść do przodu. Gdy robot znajduje się w środku zawracania, możesz to zmienić, aby powiedzieć "turnRight", aby przypomnieć robotowi, że musi skręcić w prawo. Po zmodyfikowaniu funkcji turn () końcowy kod wygląda tak.
Listing 27.1 Ukończony robot AI
class AI:
def __init__(self):
self.currentlyDoing = "forward"
def turn(self):
if self.robot.lookInFront() == "bot":
self.robot.attack()
elif self.robot.lookInFront() == "wall":
self.robot.turnRight()
self.currentlyDoing = "turnRight"
elif self.currentlyDoing == "turnRight":
self.robot.turnRight()
self.currentlyDoing = "forward"
else:
self.robot.goForth()
Jeśli to uruchomisz, możesz zauważyć, że sztuczna inteligencja ma pewne wady. Spróbujmy wprowadzić zmiany, aby nasz robot pokonał CircleAI.
Bardziej skomplikowany robot
Nasz pierwszy robot był całkiem prosty i nie wygrał z CircleAI. Aby pokonać wszystkie inne roboty, potrzebujemy naprawdę dobrej strategii. Naprawdę dobra strategia to coś więcej niż "jazda w kółko, dopóki wróg nie ruszy przede mną". Naprawdę dobra strategia wymaga użycia każdego dostępnego polecenia. Przede wszystkim naprawdę dobra strategia wymaga wielu przemyśleń, jak to zadziała. Jest kilka metod, o których nie wspomniałem w ostatniej sekcji, które mogą nam pomóc w dążeniu do stworzenia zwycięskiej strategii:
• self.robot.goBack () - Całkiem oczywiste: roboty mogą się cofać.
• self.robot.checkSpace (spacja) - pozwala spojrzeć na dowolne miejsce na planszy. na przykład self.robot.checkSpace ((3,3)) mówi, co znajduje się w przestrzeni (3,3). Jeśli nic tam nie ma, zwraca "puste". W przeciwnym razie zwraca "bota" (jeśli jest tam wróg), "ja" (jeśli jest tam twój robot) lub "ściana" (jeśli przestrzeń jest poza zasięgiem).
• self.robot.locateEnemy () - Daje pozycję i kierunek wroga.
• self.robot.position - umożliwia ustawienie własnej pozycji.
• self.robot.rotation - daje własny kierunek.
• self.robot.calculateCoordinates (kierunek, odległość, pozycja) - wyjaśnione później. Po pierwsze, musimy zrozumieć, jak działa układ współrzędnych w Python Battle.
Układ współrzędnych
W Python Battle układ współrzędnych przechodzi od (1,1) do (10,10). Zaczyna się od lewego górnego rogu, tak jak Pygame. Ściany otaczają boisko w każdym kierunku. Możemy użyć opcji self.robot.position, aby znaleźć pozycję robota w układzie współrzędnych.
Wskazówki
Wskazówki są zapisywane jako liczba od 0-3. 0 to góra (północ), 1 to prawo (wschód), 2 to dół (południe), a 3 to lewe (zachód). Kiedy robot skręca w prawo, dodaje 1 do swojego kierunku. Gdy skręca w lewo, odejmuje 1 od swojego kierunku. To takie proste. Możemy użyć self.robot.rotation, aby znaleźć kierunek robota.
calculCoordinates ()
Funkcja calculCoordinates () przyjmuje trzy parametry: odległość, kierunek i położenie. Zasadniczo znajduje współrzędne przestrzeni, która jest kwadratem odległości od pozycji w kierunku. Na przykład obliczenia współrzędnych (2,3, (5,5)) znajdują miejsce, które jest dwoma kwadratami po lewej (lewy jest kierunek 3) kwadratu (5,5). Teraz możemy wymyślić strategię. Idę z prostym:
1 Idź w kierunku wroga.
2 Atakuj, gdy to możliwe.
Zacznijmy od podstawowego kodu poprzedniego robota:
class AI:
def __init__(self):
pass
def turn(self):
if self.robot.lookInFront() == "bot":
self.robot.attack()
Ten kod zajmie się drugą częścią naszej strategii: "atakuj, gdy to możliwe". Teraz musimy zakodować pierwszą część. Dodajmy ten kod do funkcji turn ():
else:
self.goTowards(self.robot.locateEnemy()[0])
To wywoła metodę naszej klasy AI o nazwie self.goTowards () z argumentem wroga. Metoda self.robot.locateEnemy () zwraca listę zawierającą pozycję i obrót wroga. Jeśli uruchomisz ten kod, nie zadziała, ponieważ nie zdefiniowaliśmy jeszcze self.goTowards (). Zacznijmy to teraz definiować:
z
def goTowards(self,enemyLocation):
myLocation = self.robot.position
delta = (enemyLocation[0]-myLocation[0],
enemyLocation[1]-myLocation[1])
Zaczynasz od znalezienia delty lub różnicy między lokalizacją docelową a lokalizacją robota. Następnie musisz dowiedzieć się, w którym kierunku musisz być zwrócony twarzą do bota wroga:
if abs(delta[0]) > abs(delta[1]):
if delta[0] < 0:
targetOrientation = 3 //Twarz w lewo
else:
targetOrientation = 1 //Twarz w prawo
else:
if delta[1] < 0:
targetOrientation = 0 //Twarz w górę
else:
targetOrientation = 2 //Twarz w dół
Teraz musisz iść w tym kierunku. Jeśli jesteś już w tym kierunku, łatwo:
if self.robot.rotation == targetOrientation:
self.robot.goForth()
W przeciwnym razie musisz dowiedzieć się, w którą stronę skręcić. Najpierw ustal, ile skrętów w lewo musiałbyś wykonać, aby zmierzyć się z właściwym kierunkiem:
else:
leftTurnsNeeded = (self.robot.rotation - targetOrientation) % 4
Następnie musisz obrócić właściwą drogę. Jeśli zmierzenie się z potrzebą więcej niż dwóch skrętów w lewo, możesz po prostu skręcić w prawo raz:
if leftTurnsNeeded <= 2:
self.robot.turnLeft()
else:
self.robot.turnRight()
Oto pełny kod robota.
Listing 27.2 Bardziej skomplikowany robot
class AI:
def __init__(self):
pass
def turn(self):
if self.robot.lookInFront() == "bot":
self.robot.attack()
else:
self.goTowards(self.robot.locateEnemy()[0])
def goTowards(self,enemyLocation):
myLocation = self.robot.position
delta = (enemyLocation[0]-myLocation[0],enemyLocation[1]-myLocation[1])
if abs(delta[0]) > abs(delta[1]):
if delta[0] < 0:
targetOrientation = 3
else:
targetOrientation = 1
else:
if delta[1] < 0:
targetOrientation = 0
else:
targetOrientation = 2
if self.robot.rotation == targetOrientation:
self.robot.goForth()
else:
leftTurnsNeeded = (self.robot.rotation - targetOrientation) % 4
if leftTurnsNeeded <= 2:
self.robot.turnLeft()
else:
self.robot.turnRight()
Spróbujmy tego w CircleAI. Z pewnością cała nasza ciężka praca opłaciła się i pozwoliła nam w końcu ją pokonać! Zapisz AI jako bardziej skomplikowany.py i ponownie uruchom PythonBattle:
>>>
Enter red AI: circleai
Enter blue AI: morecomplicatedai
•
•
•
Red wins with 10 health!
CircleAI jest trudny do pokonania, ponieważ trudno go trafić. Jeśli spróbujesz zaatakować go z boku lub z tyłu, ucieknie, zanim robot będzie mógł go uderzyć więcej niż raz. Ponadto, ponieważ obejmuje ścianę, możesz atakować tylko jedną stronę. Jeśli spróbujesz zaatakować go z przodu, najprawdopodobniej dostaniesz pierwsze trafienie i tym samym wygrasz grę. Nawet jeśli nie jest to najbardziej zaawansowana strategia, CircleAI jest naprawdę trudna do pokonania. Prawdopodobnie możliwe jest opracowanie sztucznej inteligencji, która może konsekwentnie pokonać CircleAI, ale jeśli wiesz, że CircleAI to sztuczna inteligencja, z którą się mierzysz. Jeśli nie wiesz, co drugi gracz wykorzystuje jako strategię dla swojej sztucznej inteligencji, jest jeszcze trudniej!
Czego się nauczyłeś?
• W jaki sposób gry wykorzystują sztuczną inteligencję, aby sprytni wrogowie
• Jak stworzyć własną sztuczną inteligencję jako część PythonBattle
Wypróbuj to
• Zmień moją strategię i spróbuj wymyślić robota, który pokonuje CircleAI.
Oto zasady dotyczące nazw zmiennych (zwanych również identyfikatorami):
• Muszą się zaczynać od litery lub znaku podkreślenia. Następnie możesz użyć nieograniczonej sekwencji liter, cyfr lub znaków podkreślenia.
• Litery mogą być wielkie lub małe, a sprawa ma znaczenie. Innymi słowy, Ax nie jest tym samym co aX.
• Liczby mogą być dowolnymi cyframi od 0 do 9 włącznie.
Oprócz liter, cyfr i znaku podkreślenia nie można używać innych znaków. Spacje, znaki interpunkcyjne i inne znaki nie są dozwolone w nazwach zmiennych:
~ `! @ # $% ^ & * (); -: "'<>,.? / {} [] + = /
Jedyną dozwoloną postacią specjalną jest znak podkreślenia. Jeśli nie wiesz, co to jest, oto kilka przykładów:
• pierwszy_numer = 15
• student_name = "John"
Znak między pierwszym a numerem jest podkreśleniem. Jest też jeden między uczniem a imieniem. Programiści czasami używają podkreślenia, aby oddzielić dwa słowa w nazwie zmiennej. Ponieważ spacje nie są dozwolone w nazwach zmiennych, używają podkreślenia zamiast tego. Zalecam, aby nie używać znaku podkreślenia na początku lub na końcu nazwy zmiennej, chyba że wiesz dokładnie, dlaczego go używasz. W niektórych sytuacjach użycie znaku podkreślenia na początku lub końcu identyfikatora ma specjalne znaczenie. Więc unikaj tego:
• _first_number = 15
• student_name_ = "John"
Oto kilka przykładów poprawnych nazw zmiennych:
• my_answer
• odpowiedź23
• odpowiedz_23
• Twój odpowiedź
• Your2ndAnswer
Oto kilka przykładów nieprawidłowych nazw zmiennych:
• 23 odpowiedz (nazwy zmiennych nie mogą zaczynać się od liczby).
• twoja odpowiedź (znak łącznika nie jest dozwolony).
• moja odpowiedź (spacje nie są dozwolone).
Różnice między Pythonem 2 i 3
Wspomnieliśmy o kilku różnicach między Pythonem 2 i Pythonem 3. My używaliśmy Pythona 2, ale chcemy również, abyś wiedział, jak rozpoznać kod Pythona 3 i uczynić swój kod kompatybilnym z Pythonem 3, jeśli chcesz. Ten dodatek mówi tylko o różnicach w Pythonie 2 do 3 w częściach Pythona. (Na przykład Python 3 obsługuje łańcuchy Unicode inaczej, ale ponieważ nie rozmawialiśmy o Unicode, nie będziemy mówić o zmianach w Unicode Pythona 3). Mając to na uwadze, oto kilka sposobów, w jakie Python 3 różni się od Python 2.
print
W Pythonie 3 print jest funkcją. To znaczy zamiast pisać
print "Hello, World!"
musisz pisać
print ("Hello, World!")
Istnieją z tym inne różnice. Nie możesz po prostu wstawić przecinka na końcu, aby wyjście z następnego wydruku pojawiło się w tej samej linii, tak jak w Pythonie 2:
print "Hello",
print "Świat!"
Zamiast tego w Pythonie 3 musisz to zrobić:
print ("Hello", end = "")
print ("Świat!")
Istnieją inne rzeczy, które możesz zrobić z argumentem końcowym, ale są one rzadko używane. Możesz je przeglądać w dokumentacji Pythona 3, jeśli chcesz. Być może zauważyłeś, że kolorowanie kodu na wydruku jest inne w Pythonie 3 niż w Pythonie 2. To dlatego, że w Pythonie 2, print jest słowem kluczowym, ale w Pythonie 3 print () jest funkcją.
input()
W Pythonie 3 funkcja, która kiedyś była nazywana raw_input () w Pythonie 2, nazywa się teraz po prostu input (). Jest to funkcja, która zwraca ciąg znaków i nie próbuje wykonywać żadnej oceny ciągu wejściowego (na przykład konwertując go na int lub float). Funkcja, która została nazwana input () w Pythonie 2, która próbuje ocenić dane wejściowe (jeśli to możliwe przekonwertować na liczbę), nie istnieje w Pythonie 3. Oznacza to, że zamiast pisać to (w Pythonie 2)
your_name = raw_input ("Wpisz swoje imię:")
musisz napisać (w Pythonie 3)
your_name = input ("Wpisz swoje imię i nazwisko:")
I zamiast pisać (w Pythonie 2)
age = input ("Wprowadź swój wiek:")
musisz napisać (w Pythonie 3)
age = int (input ("Wpisz swój wiek:"))
Dzielenie liczb całkowitych
Trzecią ważną zmianą w Pythonie 3 jest sposób, w jaki obsługuje on podział całkowity. Pamiętaj "liczbę całkowitą
Otrzymujesz (w Pythonie 2):
>>> print 5/2
2
Python 2 domyślnie dokonuje podziału podłogi. Python 3 domyślnie dokonuje podziału zmiennoprzecinkowego. Tak więc w Pythonie 3 dostajesz
>>> print (5/2)
2.5
Jeśli chcesz podzielić bez reszty w Pythonie 3, możesz to uzyskać, używając podwójnego ukośnika, jak poniżej:
>>> print (5 // 2)
2
Operator modulus (%), aby uzyskać resztę w podziale na liczby całkowite, działa tak samo w Pythonie 3, jak w Pythonie 2:
Python 2:
>>> print 5% 2
1
Python 3:
>>> print (5% 2)
1
range()
W Pythonie2 funkcja range () zwraca listę. Ale w Pythonie 3, range () zwraca obiekt zakresu. W celu zapętlenia obiekt zakresu w Pythonie 3 działa zasadniczo tak samo jak lista w Pythonie 2. Ale jeśli spróbujesz go wydrukować, nie zobaczysz poszczególnych wartości w zakresie:
Python 2:
>>> print range (5)
[0, 1, 2, 3, 4]
Python 3:
>>> print (range (5))
range (0, 5)
Konwersja Pythona 2 do 3
Istnieje narzędzie o nazwie 2to3, które próbuje automatycznie konwertować kod Pythona 2 na kod Pythona 3. Jeśli używasz Pythona 3, możesz wypróbować go na niektórych aukcjach w tej książce. Wiele z nich prawdopodobnie będzie działać. Mimo że Python 3 jest najnowszą wersją Pythona, Python 2 jest nadal szeroko obsługiwany. Ponieważ wiele osób napisało kod Pythona 2, który nie działa w Pythonie 3, wiele firm i użytkowników nadal używa Pythona 2. Wiele modułów nie zostało zaktualizowanych, a niektóre moduły mogą nie zostać zaktualizowane. Istnieje dużo więcej zasobów dla kodu Pythona 2 niż dla Pythona 3 i jest to jeden z powodów, dla których zdecydowaliśmy się trzymać Pythona 2 w tej książce. Ale jeśli chcesz spróbować użyć Pythona 3 we własnych projektach programistycznych, życzymy powodzenia.
Oto odpowiedzi na pytania "Sprawdź swoją wiedzę" i "Wypróbuj" na końcu każdego rozdziału. Oczywiście czasami pojawia się więcej niż jedna odpowiednia odpowiedź, szczególnie w przypadku pytań "Wypróbuj", ale możesz użyć tych odpowiedzi, aby sprawdzić, czy jesteś na dobrej drodze.
Pierwsze kroki
Sprawdź swoją wiedzę
1 W systemie Windows uruchom IDLE, otwierając menu Start, a pod pozycją Python 2.7 wybierz wpis IDLE (Python GUI). W Mac OS X kliknij IDLE w Docku, jeśli dodałeś aplikację do Docka, lub kliknij dwukrotnie IDLE.app w folderze Python 2.7 w folderze Aplikacje. W Linuksie zależy to od tego, jakiego menedżera okien używasz, ale zazwyczaj istnieje jakieś menu aplikacji lub programów. Zauważ, że w Linuksie wiele osób nie używa IDLE - po prostu uruchamia Pythona z terminala i używa edytora takiego jak vi lub emacs do edycji kodu.
2 print wyświetla jakiś tekst w oknie wyjściowym (okno powłoki IDLE, w naszych pierwszych przykładach).
3 Symbolem mnożenia w Pythonie jest * (symbol gwiazdki).
4 Po uruchomieniu programu IDLE wyświetla ten wiersz:
>>> ======================= RESTART =======================
5 "Wykonywanie" programu to inny sposób powiedzenia "uruchomienia" programu.
Wypróbuj to
1 >>> printj 7 * 24 * 60 (7 dni w tygodniu, 24 godziny na dobę, 60 minut na godzinę). Powinieneś otrzymać 10 080 jako odpowiedź.
2 Twój program powinien wyglądać mniej więcej tak:
print "My name is Warren Sande."
print "My birth date is January 1, 1970."
print "My favorite color is blue."
Pamiętaj o tym - pamięć i zmienne
Sprawdź swoją wiedzę
1 Mówisz Pythonowi, że zmienna jest łańcuchem znaków, umieszczając w niej cudzysłowy.
2 Pytanie brzmiało: "Czy możesz zmienić wartość przypisaną zmiennej?" To zależy od tego, co rozumiesz przez "zmianę". Jeśli to zrobisz,
myAge = 10
wtedy możesz to zrobić
myAge = 11
Zmieniłeś to, co jest przypisane do myAge. Przenieśliście tag myAge na inną rzecz: przenieśliście go z 10 na 11. Ale tak naprawdę nie zmieniliście 10 na 11. Więc lepiej jest powiedzieć, że możecie "przypisać nazwę do innej wartości, "Lub" przypisz nową wartość do zmiennej ", a nie" zmień wartość zmiennej ".
3 Nie, NAUCZYCIEL nie jest tym samym co NAUCZYCIEL. Ponieważ w nazwach zmiennych rozróżniana jest wielkość liter, ostatnia litera dwóch nazw zmiennych czyni je różnymi.
4 Tak, "Blah" i "Blah" są takie same. Oba są łańcuchami, w tym przypadku Python nie dba o to, jakiego rodzaju cytatów używasz, o ile cytaty otwierające i zamykające wokół ciągu pasują.
5 Nie, "4" nie jest tym samym, co 4. Pierwszy jest ciągiem znaków (nawet jeśli ma tylko jeden znak), ponieważ ma wokół siebie cytaty. Drugi to numer.
6 Odpowiedź b. 2Nauczyciel nie jest poprawną nazwą zmiennej. Nazwy zmiennych w Pythonie nie mogą zaczynać się od liczby.
7 "10" jest ciągiem znaków, ponieważ ma wokół siebie cytaty.
Wypróbuj to
1 W trybie interaktywnym zrobiłbyś coś takiego:
>>> temperature = 25
>>> print temperaturę
25
2 Możesz wykonać jedną z następujących czynności:
>>> temperature = 40
>>> print temperature
40
lub
>>> temperature = temperature + 15
>>> print temperaturę
40
3 Zrobiłbyś coś takiego:
>>> firstName = "Fred"
>>> print firstName
Fred
4 Używając zmiennych, program "minuty na dzień" wyglądałby mniej więcej tak:
>>> DaysPerWeek = 7
>>> HoursPerDay = 24
>>> MinutesPerHour = 60
>>> print DaysPerWeek * HoursPerDay * MinutesPerHour
10080
5 Aby zobaczyć, co by się stało, gdyby w ciągu dnia było 26 godzin, zrobiłbyś to:
>>> HoursPerDay = 26
>>> print DaysPerWeek * HoursPerDay * MinutesPerHour
10920
Podstawowa matematyka
Sprawdź swoją wiedzę
1 Python używa symbolu * (gwiazdka) do mnożenia.
2 Python powiedziałby, że 8/3 = 2. Ponieważ 8 i 3 są liczbami całkowitymi, Python 2 daje odpowiedź zaokrąglona w dół do najbliższej liczby całkowitej. (Zauważ, że w Pythonie 3 otrzymasz 2.66666666667, ponieważ Python 3 nie robi "podziału podłogi" na liczby całkowite domyślnie jak Python 2).
3 Aby uzyskać resztę, użyj operatora Modulus: 8% 3.
4 Aby uzyskać dziesiętną odpowiedź dla 8/3, zmień jedną z nich na liczbę dziesiętną: 8.0 / 3 lub 8 / 3.0. (Zauważ, że w Pythonie 3 otrzymujesz automatyczną odpowiedź dziesiętną).
5 Jaki jest inny sposób obliczania 6 * 6 * 6 * 6 w Pythonie? 6 ** 4.
6 17 000 000 w zapisie E będzie zapisanych jako 1.7e7.
7 4,56e-5 jest taki sam jak 0,0000456.
Wypróbuj to
1 Oto kilka sposobów rozwiązania tych problemów. Mogłeś wymyślić inny sposób na zrobienie tego samego.
a) Oblicz, ile każda osoba powinna zapłacić w restauracji:
>>> print 35.27 * 1.15 / 3
>>> 13.5201666667
v
Zaokrąglając to, każda osoba powinna zapłacić 13,52 USD.
b) Oblicz powierzchnię i obwód prostokąta:
length = 16.7
width = 12.5
Perimeter = 2 * length + 2 * width
Area = length * width
print 'Length = ', length, ' Width = ', width
print "Area = ", Area
print "Perimeter = ", Perimeter
Here's a sample run of the program:
Length = 16.7 Width = 12.5
Area = 208.75
Perimeter = 58.4
2 Oto program do konwersji temperatur z Fahrenheita na Celsjusza:
fahrenheit = 75
celsius = 5.0/9 * (fahrenheit - 32)
print "Fahrenheit = ", fahrenheit, "Celsius =", Celsius
3 Oblicz czas potrzebny do przejechania pewnej odległości przy danej prędkości:
distance = 200
speed = 80.0
time = distance / speed
print "time =", time
(Pamiętaj, aby w podziale utworzyć co najmniej jedną liczbę dziesiętną, chyba że chcesz, aby odpowiedź została zaokrąglona w dół do liczby całkowitej).
Rodzaje danych
Sprawdź swoją wiedzę
1 Funkcja int () zawsze zaokrągla w dół (do następnej liczby całkowitej najbliższej zeru w linii liczbowej).
2 Czy w programie konwersji temperatury zadziałałyby
cel = float(5 / 9 * (fahr - 32))
cel = 5 / 9 * float(fahr - 32)
Wypróbuj je i zobacz, co się stanie:
>>> fahr = 75
>>> cel = float (5/9 * (fahr - 32))
>>> cel print
0.0
Dlaczego to nie zadziałało?
Pamiętaj, że wszystko w nawiasach jest wykonywane jako pierwsze. Tak to wygląda:
75 - 32 = 43
Następnie
5/9 = 0
Ponieważ idzie od lewej do prawej, najpierw wykonuje się 5/9. Ponieważ 5 i 9 są liczbami całkowitymi, Python dokonuje podziału na liczby całkowite i zaokrągla odpowiedź w dół. Ponieważ odpowiedź jest mniejsza niż 1, zostaje zaokrąglona w dół do 0. Następnie
0 * 43 = 0
Następnie
float (0) = 0.0
Zanim zdążyło się unieść (), było już za późno - odpowiedź brzmiała już 0! To samo dotyczy drugiego równania.
3 Możesz "oszukać" int (), aby zaokrąglić, zamiast zaokrąglać w dół, dodając 0,5 do liczby, którą przekazujesz do int (). Oto przykład (w trybie interaktywnym):
>>> a = 13.2
>>> roundoff = int(a + 0.5)
>>> roundoff
13
>>> b = 13.7
>>> roundoff = int(b + 0.5)
>>> b
14
Jeśli oryginalny numer jest mniejszy niż 13,5, int () otrzymuje liczbę mniejszą niż 14, która zaokrągla w dół do 13. Jeśli oryginalny numer wynosi 13,5 lub więcej, int () otrzymuje liczbę równą lub większą niż 14, która zaokrągla w dół do 14.
Wypróbuj to
1 Możesz użyć float (), aby przekonwertować ciąg znaków na liczbę dziesiętną:
>>> a = float ('12 .34 ')
>>> print a
12,34
Ale skąd wiesz, że jest to liczba, a nie ciąg? Sprawdźmy typ:
>>> type(a)
2 Możesz użyć int(), aby przekonwertować liczbę dziesiętną na liczbę całkowitą:
>>> print int (56,78)
56
Odpowiedź została zaokrąglona w dół.
3 Możesz użyć int (), aby przekonwertować ciąg znaków na liczbę całkowitą:
>>> a = int ('75 ')
>>>print a
75
>>> typ (a)
< type "int" >
Wejście
Sprawdź swoją wiedzę
1 Z tym kodem
answer = raw_input()
jeśli użytkownik wpisze 12, odpowiedź zawiera ciąg. To dlatego, że raw_input () zawsze daje ci ciąg znaków. Spróbuj tego w krótkim programie i zobacz:
print "enter a number: ",
answer = raw_input()
print type(answer)
>>> ============== RESTART ==============
>>>
enter a number: 12
< type 'str' >
>>>
Więc raw_input () daje ci łańcuch. Pamiętaj, że w Pythonie 3 raw_input () jest po prostu nazywany input ().
2 Aby uzyskać raw_input (), aby wydrukować komunikat zachęty, umieść tekst w cudzysłowie w nawiasach, tak jak poniżej:
answer = raw_input("Type in a number: ")
3 Aby uzyskać liczbę całkowitą za pomocą raw_input (), użyj int (), aby przekonwertować otrzymany ciąg z raw_input (). Możesz to zrobić w dwóch krokach:
something = raw_input()
answer = int(something)
Lub możesz to zrobić w jednym kroku, tak:
answer = int (raw_input ())
Jest to bardzo podobne do poprzedniego pytania, z wyjątkiem tego, że używasz float () zamiast int ().
Wypróbuj to
1 Twoje instrukcje w trybie interaktywnym powinny wyglądać mniej więcej tak:
>>> first = 'Warren'
>>> last = 'Sande'
>>> print first + last
WarrenSande
Ups! Nie ma miejsca. Możesz dodać spację na końcu swojego imienia
>>> first = 'Warren
lub spróbuj tego:
>>> print first + ' ' + last
Warren Sande
Możesz też użyć przecinka, takiego jak ten:
>>> first = 'Warren'
>>> last = 'Sande'
>>> print first, last
Warren Sande
2 Program powinien wyglądać mniej więcej tak:
first = raw_input('enter your first name: ')
last = raw_input('enter your last name: ')
print 'Hello,', first, last, 'how are you today?
3 Program powinien wyglądać mniej więcej tak:
length = float(raw_input ('length of the room in feet: '))
width = float(raw_input ('width of the room in feet: '))
area = length * width
print 'The area is', area, 'square feet.'
4 Możesz dodać kilka wierszy do programu z #C:
length = float(raw_input ('length of the room in feet: '))
width = float(raw_input ('width of the room in feet: '))
cost_per_yard = float(raw_input ('cost per square yard: '))
area_feet = length * width
area_yards = area_feet / 9.0
total_cost = area_yards * cost_per_yard
print 'The area is', area_feet, 'square feet.'
print 'That is', area_yards, 'square yards.'
print 'Which will cost', total_cost
5 Program powinien wyglądać następująco:
quarters = int(raw_input("How many quarters? "))
dimes = int(raw_input("How many dimes? "))
nickels = int(raw_input("How many nickels? "))
pennies = int(raw_input("How many pennies? "))
total = 0.25 * quarters + 0.10 * dimes + 0.05 * nickels + 0.01 * pennies
print "You have a total of: ", total
GUI - graficzne interfejsy użytkownika
Sprawdź swoją wiedzę
1 Aby wyświetlić okno wiadomości z EasyGui, użyj msgbox (), w ten sposób:
easygui.msgbox ("To jest odpowiedź!")
2 Aby uzyskać ciąg znaków jako dane wejściowe za pomocą EasyGui, użyj pola Enter.
3 Aby uzyskać liczbę całkowitą jako dane wejściowe, możesz użyć skrzynki wejściowej (która pobiera ciąg od użytkownika), a następnie przekształcić ją w int. Lub możesz użyć skrzynki integerbox.
4 Aby uzyskać pływak od użytkownika, możesz użyć skrzynki (która daje ci łańcuch), a następnie użyć funkcji float (), aby przekonwertować łańcuch na zmiennoprzecinkowy.
5 Domyślna wartość jest jak "automatyczna odpowiedź". Oto jeden ze sposobów, w jaki możesz użyć domyślnego: jeśli pisałeś program, w którym wszyscy uczniowie w twojej klasie musieli wprowadzić swoje imię i nazwisko oraz adres, możesz mieć nazwę miasta gdzie mieszkasz jako domyślne miasto w adresie. W ten sposób uczniowie nie musieliby wpisywać go, chyba że mieszkali w innym mieście.
Wypróbuj to
1 Oto program do konwersji temperatury za pomocą EasyGui:
# tempgui1.py
# EasyGui version of temperature-conversion program
# converts Fahrenheit to Celsius
import easygui
easygui.msgbox('This program converts Fahrenheit to Celsius')
temperature = easygui.enterbox('Type in a temperature in Fahrenheit:')
Fahr = float(temperature)
Cel = (Fahr - 32) * 5.0 / 9
easygui.msgbox('That is ' + str(Cel) + ' degrees Celsius.')
2 Oto program, który prosi o podanie twojego imienia i części adresu, a następnie wyświetla cały adres. W tym przypadku pomaga wiedzieć, jak wymusić nową linię. Nowa linia powoduje rozpoczęcie następującego tekstu w nowej linii. Aby to zrobić, używasz n. Zostało to wyjaśnione w rozdziale 21, ale tutaj jest podgląd:
# address.py
# Enter parts of your address and display the whole thing
import easygui
name = easygui.enterbox("What is your name?")
addr = easygui.enterbox("What is your street address?")
city = easygui.enterbox("What is your city?")
state = easygui.enterbox("What is your state or province?")
code = easygui.enterbox("What is your postal code or zip code?")
whole_addr = name + "\n" + addr + "\n" + city + ", " + state + "\n" + code
easygui.msgbox(whole_addr, "Here is your address:")
Decyzje, decyzje
Sprawdź swoją wiedzę
1 Wyjście byłoby:
Poniżej 20
Ponieważ mój_numer jest mniejszy niż 20, test w instrukcji if jest prawdziwy, więc wykonywany jest blok następujący po wierszu if (w tym przypadku tylko jednej linii).
2 Wyjście byłoby:
20 lub więcej
Ponieważ mój_numer jest większy niż 20, test w instrukcji if jest fałszywy, więc kod w bloku następującym po if nie jest wykonywany. Zamiast tego wykonywany jest kod z bloku else.
3 Aby sprawdzić, czy liczba jest większa niż 30, ale mniejsza lub równa 40, użyłbyś czegoś takiego:
if number > 30 and number <= 40:
print 'The number is between 30 and 40'
Możesz również to zrobić:
if 30 < number <= 40:
print "The number is between 30 and 40"
4 Aby sprawdzić literę Q wielkimi lub małymi literami, możesz zrobić coś takiego:
if answer == 'Q' or answer == 'q':
print "you typed a 'Q' "
Zwróć uwagę, że ciąg, który wydrukowaliśmy, używa podwójnych cudzysłowów, ale wewnątrz Q znajdują się pojedyncze cudzysłowy. Jeśli zastanawiałeś się, jak drukować cudzysłowy, jest to jeden ze sposobów: użyj innego rodzaju cudzysłowu, aby załączyć swój string
Wypróbuj to
1 Oto jedna odpowiedź:
# program to calculate store discount
# 10% off for $10 or less, 20% off for more than $10
item_price = float(raw_input ('enter the price of the item: '))
if item_price <= 10.0:
discount = item_price * 0.10
else:
discount = item_price * 0.20
final_price = item_price - discount
print 'You got ', discount, 'off, so your final price was', final_price
Nie martwiłem się o zaokrąglenie odpowiedzi do dwóch miejsc po przecinku (centów) lub wyświetlenie znaku dolara2 Oto jeden ze sposobów:
2 Oto jeden ze sposobów:
# program to check age and gender of soccer players
# accept girls who are 10 to 12 years old
gender = raw_input("Are you male or female? ('m' or 'f') ")
if gender == 'f':
age = int(raw_input('What is your age? '))
if age >= 10 and age <= 12:
print 'You can play on the team'
else:
print 'You are not the right age.'
else:
print 'Only girls are allowed on this team
3 Oto jedna odpowiedź:
# program to check if you need gas.
# Next station is 200 km away
tank_size = int(raw_input('How big is your tank (liters)? '))
full = int(raw_input ('How full is your tank (eg. 50 for half full)?'))
mileage = int(raw_input ('What is your gas mileage (km per liter)? '))
range = tank_size * (full / 100.0) * mileage
print 'You can go another', range, 'km.'
print 'The next gas station is 200km away.'
if range <= 200:
print 'GET GAS NOW!'
else:
print 'You can wait for the next station
Aby dodać 5-litrowy bufor, zmień linię
range = tank_size * (full / 100.0) * mileage
do
range = (tank_size - 5) * (full / 100.0) * mileage
Oto prosty program haseł:
password = "bigsecret"
guess = raw_input("Enter your password: ")
if guess == password:
print "Password correct. Welcome"
# put the rest of the code for your program here
else:
print "Password incorrect. Goodbye"
Zapętlanie pętli
Sprawdź swoją wiedzę
1 Pętla uruchomiłaby się pięć razy.
2 Pętla uruchomiłaby się trzy razy, a wartości byłyby następujące: i = 1, i = 3, i = 5.
3 zakresy (1, 8) dałyby ci [1, 2, 3, 4, 5, 6, 7].
4 zakresy (8) dadzą ci [0, 1, 2, 3, 4, 5, 6, 7].
5 zakresów (2, 9, 2) da ci [2, 4, 6, 8].
6 zakresów (10, 0, -2) da ci [10, 8, 6, 4, 2].
7 Używasz, aby zatrzymać bieżącą iterację pętli i przejść do następnej iteracji.
8 A pętla while kończy się, gdy testowany warunek jest fałszywy.
Wypróbuj to
1 Oto program do drukowania tablicy mnożenia wyboru użytkownika za pomocą pętli for:
# program to print multiplication table up to 10
number = int(raw_input('Which table would you like? '))
print 'Here is your table:'
for i in range(1, 11):
print number, 'x', i, '=', number * i
2 Oto ta sama tabliczka mnożenia przy użyciu pętli while:
# program to print mult table (while loop)
number = int(raw_input('Which table would you like? '))
print 'Here is your table:'
i = 1
while i <= 10:
print number, 'times', i, '=', number * i
i = i + 1
3 Oto tabliczka mnożenia z zakresem zdefiniowanym przez użytkownika:
# program to print multiplication table
# user inputs how high they want it to go
number = int(raw_input('Which table would you like? '))
limit = int(raw_input('How high would you like it to go? '))
print 'Here is your table:'
for i in range(1, limit + 1):
print number, 'times', i, '=', number * i
Zwróć uwagę w wierszu for, że druga rzecz w zakresie () zawiera zmienną, a nie tylko liczbę. Dowiesz się więcej o tym w części 11
Tylko dla Ciebie - komentarze
Wypróbuj to
1 Oto przykład niektórych komentarzy, które dodam do programu konwersji temperatury:
# tempconv1.py
# program to convert a Fahrenheit temperature to Celsius
Fahr = 75
Cel = (Fahr - 32) * 5.0 / 9 #decimal division, not integer
print "Fahrenheit = ", Fahr, "Celsius = ", Cel
Czas gry
Wypróbuj to
1 Czy próbowałeś wpisać program i uruchomić go? Nie zapomnij umieścić grafiki w tym samym folderze co program.
Zagnieżdżone i zmienne pętle
Sprawdź swoją wiedzę
1 Możesz utworzyć zmienną pętlę w Pythonie, umieszczając zmienną w funkcji range () w ten sposób
for i in range(numberOfLoops)
lub
for i in range(1, someNumber)
2 Aby utworzyć zagnieżdżoną pętlę, umieść pętlę w ciele innej pętli, tak jak poniżej:
for i in range(5):
for j in range(8):
print "hi",
print
Kod ten wydrukuje "hi" osiem razy na linii (pętla wewnętrzna) i wykona pięć linii (pętla zewnętrzna).
3 Zostanie wydrukowanych 15 gwiazdek.
4 Wyjście z kodu będzie wyglądało następująco:
* * *
* * *
* * *
* * *
* * *
5 W przypadku czteropoziomowego drzewa decyzyjnego dostępne są 2 ** 4 lub 2 * 2 * 2 * 2 możliwe opcje. To 16 możliwych wyborów lub 16 ścieżek przez drzewo.
Wypróbuj to
1 Oto program odliczający czas, który pyta użytkownika, gdzie zacząć:
# Countdown timer asks the user where to start
import time
start = int(raw_input("Countdown timer: How many seconds? ", ))
for i in range (start, 0, -1):
print i
time.sleep(1)
print "BLAST OFF!"
2 Oto wersja, która drukuje rząd gwiazd obok każdego numeru:
# Countdown timer asks the user where to start
# and prints stars beside each number
import time
start = int(raw_input("Countdown timer: How many seconds? ", ))
for i in range (start, 0, -1):
print i,
for star in range(i):
print '*',
print
time.sleep(1)
print "BLAST OFF!"
Zbieranie rzeczy razem - listy
Sprawdź swoją wiedzę
1 Możesz dodać coś do listy za pomocą append (), insert () lub extend ().
2 Możesz usunąć coś z listy za pomocą remove (), pop () lub del.
3 Aby uzyskać posortowaną kopię listy, możesz wykonać jedną z następujących czynności:
• Utwórz kopię listy, używając plasterków: new_list = my_list [:]. Następnie posortuj nową listę:
new_list.sort ().
• Użyj funkcji sorted (): new_list = sorted (my_list).
4 Dowiesz się, czy dana wartość znajduje się na liście, używając słowa kluczowego in.
5 Określasz lokalizację wartości na liście za pomocą metody index ().
6 Krotka to kolekcja przypominająca listę, z tym że nie możesz jej zmienić. Krotki są niezmienne (niezmienne), podczas gdy listy są zmienne (zmienne).
7 Możesz utworzyć listę list na kilka sposobów:
• Używając zagnieżdżonych nawiasów kwadratowych:
>>> my_list = [[1, 2, 3], ['a', 'b', 'c'], ['red', 'green', 'blue']
• Używając append () i dołączając listę:
>>> my_list = []
>>> my_list.append ([1, 2, 3])
>>> my_list.append (['a', 'b', 'c'])
>>> my_list.append (['czerwony', 'zielony', 'niebieski'])
>>> print my_list
[[1, 2, 3], ["a", "b", "c"], ["czerwony", "zielony", "niebieski"]]
&ull; Tworząc indywidualne listy, a następnie łącząc je:
>>> list1 = [1, 2, 3]
>>> list2 = ['a', 'b', 'c']
>>> list3 = ['red', 'green', 'blue']
>>> my_list = [list1, list2, list3]
>>> print my_list
[[1, 2, 3], ['a', 'b', 'c'], ['red', 'green', 'blue']]
8 Otrzymujesz pojedynczą wartość z listy list, używając dwóch indeksów (lub indeksów)
my_list = [[1, 2, 3], ['a', 'b', 'c'], ['red', 'green', 'blue']]
my_color = my_list [2] [1]
Odpowiedź byłaby "zielona".
9 Słownik to zbiór par klucz-wartość.
10 Możesz dodać element do słownika, określając klucz i wartość:
phone_numbers ['John'] = '555-1234'
11 Aby wyszukać element w słowniku za pomocą klawisza, możesz użyć indeksu:
print phone_numbers ['John']
Wypróbuj to
1 Oto program, który otrzyma pięć nazw, umieści je na liście, a następnie wydrukuje:
nameList = []
print "Enter 5 names (press the Enter key after each name):"
for i in range(5):
name = raw_input()
nameList.append(name)
print "The names are:", nameList
2 Oto program, który wydrukuje oryginalną listę i posortowaną wersję:
nameList = []
print "Enter 5 names (press the Enter key after each name):"
for i in range(5):
name = raw_input()
nameList.append(name)
print "The names are:", nameList
print "The sorted names are:", sorted(nameList)
3 Oto program do drukowania tylko trzeciej nazwy z listy:
nameList = []
print "Enter 5 names (press the Enter key after each name):"
for i in range(5):
name = raw_input()
nameList.append(name)
print "The third name is:", nameList[2]
4 Oto program umożliwiający użytkownikowi zastąpienie nazwy na liście:
nameList = []
print "Enter 5 names (press the Enter key after each name):"
for i in range(5):
name = raw_input()
nameList.append(name)
print "The names are:", nameList
print "Replace one name. Which one? (1-5):",
replace = int(raw_input())
new = raw_input("New name: ")
nameList[replace - 1] = new
print "The names are:", nameList
5 Oto program, który pozwala użytkownikowi utworzyć słownik ze słowami i definicjami:
user_dictionary = {}
while 1:
command = raw_input("'a' to add word, 'l' to lookup a word, 'q' to quit ")
if command == "a":
word = raw_input("Type the word: ")
definition = raw_input("Type the definition: ")
user_dictionary[word] = definition
print "Word added!"
elif command == "l":
word = raw_input("Type the word: ")
if word in user_dictionary.keys():
print user_dictionary[word]
else:
print "That word isn't in the dictionary yet."
elif command == 'q':
break
Funkcje
Sprawdź swoją wiedzę
1 Używasz słowa kluczowego def, aby utworzyć funkcję.
2 Wywołujesz funkcję, używając jej nazwy z nawiasami.
3 Przekazujesz argumenty do funkcji, umieszczając argumenty w nawiasach podczas wywoływania funkcji.
4 Nie ma limitu liczby argumentów, które może mieć funkcja.
5 Funkcja wysyła informacje z powrotem do dzwoniącego za pomocą słowa kluczowego return.
6 Po zakończeniu działania dowolne zmienne lokalne są niszczone.
Wypróbuj to
1 Funkcja to tylko kilka instrukcji drukowania:
Program, który wywołuje, może wyglądać następująco:
for i in range(5):
printMyNameBig()
2 Oto mój przykład drukowania adresów z siedmioma argumentami:
# define a function with seven arguments
def printAddr(name, num, street, city, prov, pcode, country):
print name
print num,
print street
print city,
if prov !="":
print ", "+prov
else:
print ""
print pcode
print country
print
#call the function and pass seven arguments to it
printAddr("Sam", "45", "Main St.", "Ottawa", "ON", "K2M 2E9", "Canada")
printAddr("Jian", "64", "2nd Ave.", "Hong Kong", "", "235643", "China")
3 Brak odpowiedzi, po prostu spróbuj.
4 Funkcja dodawania zmiany powinna wyglądać następująco:
def addUpChange(quarters, dimes, nickels, pennies):
total = 0.25 * quarters + 0.10 * dimes + 0.05 * nickels + 0.01 * pennies
return total
Program, który go wywołuje, wyglądałby tak:
quarters = int(raw_input("quarters: "))
dimes = int(raw_input("dimes: "))
nickels = int(raw_input("nickels: "))
pennies = int(raw_input("pennies: "))
total = addUpChange(quarters, dimes, nickels, pennies)
print "You have a total of: ", total
Obiekty
Sprawdź swoją wiedzę
1 Aby zdefiniować nowy typ obiektu, należy użyć słowa kluczowego class.
2 Atrybuty to "rzeczy, które znasz" na temat obiektu. Są to zmienne zawarte w obiekcie.
3 Metody to czynności, które możesz wykonać dla obiektu. Są to funkcje zawarte w obiekcie.
4 Klasa to tylko definicja lub plan obiektu. Instancja jest tym, co dostajesz, kiedy tworzysz obiekt z planu.
5 Nazwa self jest zwykle używana jako odwołanie do instancji w metodzie obiektu.
6 Polimorfizm to możliwość posiadania dwóch lub więcej metod o tej samej nazwie na różnych obiektach. Metody mogą zachowywać się inaczej w zależności od tego, do którego obiektu należą.
7 Dziedziczenie to zdolność obiektów do uzyskiwania atrybutów i metod od swoich "rodziców". Klasa "dziecko" (nazywana klasą podrzędną lub klasą pochodną) pobiera wszystkie atrybuty i metody rodzica, a także może mieć atrybuty i metody, które nie są udostępniane rodzicowi.
Wypróbuj to
1 Klasa konta bankowego może wyglądać następująco:
class BankAccount:
def __init__(self, acct_number, acct_name):
self.acct_number = acct_number
self.acct_name = acct_name
self.balance = 0.0
def displayBalance(self):
print "The account balance is:", self.balance
def deposit(self, amount):
self.balance = self.balance + amount
print "You deposited", amount
print "The new balance is:", self.balance
def withdraw(self, amount):
if self.balance >= amount:
self.balance = self.balance - amount
print "You withdrew", amount
print "The new balance is:", self.balance
else:
print "You tried to withdraw", amount
print "The account balance is:", self.balance
print "Withdrawal denied. Not enough funds."
A oto kod do przetestowania i upewnienia się, że działa:
myAccount = BankAccount(234567, "Warren Sande")
print "Account name:", myAccount.acct_name
print "Account number:", myAccount.acct_number
myAccount.displayBalance()
myAccount.deposit(34.52)
myAccount.withdraw(12.25)
myAccount.withdraw(30.18)
2 Aby utworzyć konto odsetek, utwórz podklasę konta bankowego i utwórz metodę dodawania odsetek:
class InterestAccount(BankAccount):
def __init__(self, acct_number, acct_name, rate):
BankAccount.__init__(self, acct_number, acct_name)
self.rate = rate
def addInterest (self):
interest = self.balance * self.rate
print "adding interest to the account,", self.rate * 100, "percent"
self.deposit (interest)
Oto kod do przetestowania:
myAccount = InterestAccount(234567, "Warren Sande", 0.11)
print "Account name:", myAccount.acct_name
print "Account number:", myAccount.acct_number
myAccount.displayBalance()
myAccount.deposit(34.52)
myAccount.addInterest()
Moduły
Sprawdź swoją wiedzę
1 Niektóre zalety korzystania z modułów to
• Możesz napisać kod raz i użyć go w wielu programach.
• Możesz używać modułów napisanych przez innych ludzi.
• Twoje pliki kodu są mniejsze, więc łatwiej jest znaleźć rzeczy w kodzie.
• Możesz korzystać tylko z części (modułów), których potrzebujesz do wykonania pracy.
2 Tworzysz moduł pisząc kod Pythona i zapisując go w pliku.
3 Jeśli chcesz użyć modułu, użyj słowa kluczowego import.
4 Importowanie modułu jest tym samym, co importowanie przestrzeni nazw.
5 Dwa sposoby importowania modułu czasowego, aby mieć dostęp do wszystkich nazw w module
import time
i
from time import
Wypróbuj to
1 Aby napisać moduł, po prostu umieść kod swojej funkcji "big name" w pliku - coś takiego jak bigname.py. Następnie, aby zaimportować moduł i wywołać funkcję, zrób coś takiego
import bigname
bigname.printMyNameBig()
Albo możesz to zrobić:
from bigname import *
printMyNameBig()
2 Aby wprowadzić c_to_f () do przestrzeni nazw programu głównego, możesz to zrobić:
from my_module import c_to_f
lub to:
from my_module import *
3 Krótki program do wydrukowania pięciu losowych liczb całkowitych od 1 do 20 wyglądałby tak:
look like this
import random
for i in range(5):
print random.randint(1, 20)
4 Krótki program, który drukuje losową liczbę dziesiętną co 3 sekundy przez 30 sekund wyglądałby następująco:
import random, time
for i in range(10):
print random.random()
time.sleep(3)
Grafika
Sprawdź swoją wiedzę
1 Wartość RGB [255, 255, 255] powoduje, że kolor jest biały.
2 Wartość RGB [0, 255, 0] powoduje, że kolor jest zielony.
3 Aby narysować prostokąty, użyj metody Pygame pygame.draw.rect ().
4 Aby narysować linie łączące kilka punktów razem (np. Łącz kropki), użyj metody pygame.draw.lines ().
5 Termin "piksel" oznacza "element obrazu" i oznacza jedną kropkę na ekranie (lub papierze).
6 W oknie Pygame lokalizacja [0, 0] jest lewym górnym rogiem.
7 Na schemacie lokalizacja [50, 200] znajduje się na literze B.
8 Na schemacie lokalizacja [300, 50] znajduje się na liście D.
9 Metoda blit () służy do kopiowania obrazów w Pygame.
10 Aby przenieść lub animować obraz, wykonaj następujące dwa kroki:
• Usuń obraz ze starej lokalizacji.
• Narysuj obraz w nowej lokalizacji.
Wypróbuj to
1 Oto program, który rysuje kilka różnych kształtów na ekranie.
import pygame, sys
pygame.init()
screen=pygame.display.set_mode((640, 480))
screen.fill((250, 120, 0))
pygame.draw.arc(screen, (255, 255, 0), pygame.rect.Rect(43, 368, 277, 235),
-6.25, 0, 15)
pygame.draw.rect(screen, (255, 0, 0), pygame.rect.Rect(334, 191, 190, 290))
pygame.draw.rect(screen, (128, 64, 0), pygame.rect.Rect(391, 349, 76, 132))
pygame.draw.line(screen, (0, 255, 0), (268, 259), (438, 84), 25)
pygame.draw.line(screen, (0, 255, 0), (578, 259), (438, 84), 25)
pygame.draw.circle(screen, (0, 0, 0), (452, 409), 11, 2)
pygame.draw.polygon(screen, (0, 0, 255), [(39, 39), (44, 136), (59, 136),
(60, 102), (92, 102), (94, 131), (107, 141), (111, 50), (97, 50), (93,
86), (60, 82), (58, 38)], 5)
pygame.draw.rect(screen, (0, 0, 255), pygame.rect.Rect(143, 90, 23, 63), 5)
pygame.draw.circle(screen, (0, 0, 255), (153, 60), 15, 5)
clock = pygame.time.Clock()
pygame.display.flip()
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
running = False
pygame.quit()
2 Aby zastąpić obraz piłki plażowej innym obrazem, po prostu zastąp nazwę pliku w tym wierszu
my_ball = pygame.image.load('beach_ball.png')
with a different filename for a different graphic.
3 W listingu 16.16, zmień
x_speed = 10
y_speed = 10
to something else, like
x_speed = 20
y_speed = 8
4 Aby piłka odbijała się od "niewidzialnej" ściany, zmień linię na liście 16.16 od
if x > screen.get_width() - 90 or x < 0:
do tego:
if x > screen.get_width() - 250 or x < 0:
To sprawia, że piłka odwraca kierunek, zanim dotrze do krawędzi okna. Możesz zrobić to samo dla "podłogi" ze współrzędnymi y.
5 Oto, jak wygląda lista 16.6 z display.flip przesuniętym wewnątrz pętli while iz dodanym o import pygame, sys, random
pygame.init()
screen = pygame.display.set_mode([640,480])
screen.fill([255, 255, 255])
for i in range (100):
width = random.randint(0, 250)
height = random.randint(0, 100)
top = random.randint(0, 400)
left = random.randint(0, 500)
pygame.draw.rect(screen, [0,0,0], [left, top, width, height], 1)
pygame.display.flip()
pygame.time.delay(30)
Powinieneś być w stanie zobaczyć każdy prostokąt wyświetlany osobno, ponieważ spowolniliśmy program i odświeżamy wyświetlacz po narysowaniu każdego prostokąta. Jeśli robisz to do programów sinusoidalnych, możesz zobaczyć każdy punkt fali sinusoidalnej.
Sprite′y i wykrywanie kolizji
Sprawdź swoją wiedzę
1 Wykrywanie kolizji prostokątów oznacza wykrywanie, gdy dwa obiekty graficzne dotykają się lub nakładają, używając prostokąta wokół obiektów.
2 Wykrywanie kolizji w trybie pikselowym wykorzystuje prawdziwy obrys obiektu graficznego do wykrywania kolizji. Wykrywanie kolizji prostokątów wykorzystuje prostokąt wokół obiektu w celu określenia kolizji. Perfekcyjne wykrywanie kolizji w pikselach jest bardziej dokładne i realistyczne, ale wymaga również więcej kodu, co nieco spowalnia pracę.
3 Możesz śledzić wiele obiektów sprite razem, używając zwykłej listy Pythona lub grupy Sprite Pygame.
4 Możesz kontrolować szybkość animacji (szybkość klatek) w kodzie, dodając opóźnienia między każdą ramką lub używając pygame.time.Clock, aby uzyskać określoną szybkość klatek. Możesz także zmienić, jak daleko (ile pikseli) obiekt porusza się w każdej klatce.
5 Korzystanie z metody opóźnienia jest mniej dokładne, ponieważ nie bierze pod uwagę czasu, jaki zajmuje sam kod dla każdej klatki, więc nie wiesz dokładnie, jaką liczbę klatek uzyskasz.
6 Za pomocą pygame możesz dowiedzieć się, na jakiej szybkości odtwarzania działa program. time.Clock.get_fps ().
Nowy rodzaj danych wejściowych - zdarzenia
Sprawdź swoją wiedzę
1 Dwa rodzaje zdarzeń, na które program może reagować, to zdarzenia klawiatury i zdarzenia myszy.
2 Fragment kodu, który zajmuje się zdarzeniem, nazywany jest programem obsługi zdarzeń.
3 Pygame używa zdarzenia KEYDOWN do wykrywania naciskanych klawiszy.
4 Atrybut pos informuje, gdzie znajduje się mysz, gdy zdarzenie ma miejsce.
5 Aby uzyskać następny dostępny numer zdarzenia dla zdarzeń użytkownika, użyj pygame.USEREVENT.
6 Aby utworzyć timer, użyj pygame.time.set_timer ().
7 Aby wyświetlić tekst w oknie Pygame, użyj obiektu czcionki.
8 Oto trzy kroki, aby użyć obiektu czcionki:
• Utwórz obiekt czcionki.
• Renderuj tekst, tworząc powierzchnię.
• Blit tę powierzchnię do powierzchni wyświetlacza.
Wypróbuj to
1 Dlaczego piłka zachowuje się dziwnie, gdy uderza w bok wiosła zamiast w górę? Ponieważ masz kolizję, więc kod próbuje odwrócić kierunek y piłki (spraw, by poszła w górę zamiast w dół). Ale ponieważ piłka wchodzi z boku, nadal "zderza się" z rakietką, nawet po odwróceniu. Następnym razem pętla (jedna klatka później), odwraca kierunek ponownie, więc znowu spada, i tak dalej. Prostym sposobem naprawienia tego jest zawsze ustawienie piłki tak, aby przechodziła w górę (ujemna prędkość y), gdy zderzy się z wiosłem. To nie jest idealne, ponieważ oznacza to, że nawet jeśli piłka uderzy w bok rakietki, będzie się odbijać - niezbyt realistycznie! Ale rozwiązuje problem piłki odbijającej się wokół rakietki. Jeśli chcesz bardziej realistycznego rozwiązania, będzie wymagało nieco więcej kodu. Prawdopodobnie będziesz musiał dodać coś, co sprawdzi, która krawędź rakietki zderzyła się z piłką, zanim "podskoczy".
Dźwięk
Sprawdź swoją wiedzę
1 Rodzaje plików używanych do przechowywania dźwięku obejmują Wave (.wav), MP3 (.mp3), Ogg Vorbis (.ogg) i Windows Media Audio (.wma).
2 Moduł pygame.mixer służy do odtwarzania muzyki.
3 Ustawiasz głośność dla obiektów dźwiękowych Pygame za pomocą metody set_volume () każdego obiektu dźwiękowego.
4 Ustawiasz głośność podkładu muzycznego za pomocą pygame.mixer.music.set_volume ().
5 Aby wygasić muzykę, użyj metody pygame.mixer.music.fadeout (). Użyj liczby milisekund (tysięcznych części sekundy) czasu przenikania jako argumentu. Na przykład pygame.mixer.music.fadeout (2000) rozjaśni dźwięk w 2 sekundy.
Więcej GUI
Sprawdź swoją wiedzę
1 Trzy nazwy elementów graficznych GUI to kontrola, widget i komponent.
2 Litera, którą naciskasz (razem z Alt), aby dostać się do menu, nazywa się skrótem klawiszowym.
3 pliki Qt Designer muszą kończyć się na .ui.
4 Rodzaje komponentów, które można dołączyć do GUI za pomocą przycisku PyQt, pole wyboru, pasek postępu, lista, przycisk opcji, pole wirowania, suwak, pole tekstowe, obraz, etykieta i kilka innych. Zobacz pole Widget w Qt Designer, aby wyświetlić całą listę.
5 Aby widget działał, musi mieć program obsługi zdarzeń.
6 Znak & (ampersand) służy do definiowania skrótu klawiszowego w Qt Designer.
7 Zawartość pola spinowego w Qt Designer jest zawsze liczbą całkowitą.
Wypróbuj to
1. Aby rozwiązać problem spinnera, wybierz widget pudełka spinowego w Qt Designer. W Edytorze właściwości zmień minimalne i maksymalne właściwości. Minimalna właściwość powinna wynosić około -1000, a maksymalna może być bardzo duża, np. 1000000.
Formatowanie wydruku i łańcuchy
Sprawdź swoją wiedzę
1 Jeśli masz dwie oddzielne instrukcje drukowania i chcesz, aby wszystko było drukowane w tej samej linii, umieść przecinek na końcu pierwszej instrukcji drukowania, jak poniżej:
print "What is",
print "your name?"
2 Aby dodać dodatkowe puste linie po wydrukowaniu, możesz dodać dodatkowe instrukcje drukowania bez niczego w nich, takie jak:
print "Hello"
print
print
print
print "World"
Lub możesz whyświetlić znaki nowej linii,\ n, w ten sposób
print "Hello\n\n\nWorld"
3 Aby uporządkować rzeczy w kolumnach, użyj znaku tabulacji, \t
4 Aby wydrukować numer w notacji E, użyj łańcucha formatu %e lub %E, jak poniżej:
>>> number = 12.3456
>>> print '%e' % number
1.234560e+001
Wypróbuj to
1 Program wyglądałby tak:
name = raw_input("What is your name? ")
age = int(raw_input("How old are you? "))
color = raw_input("What is your favorite color? ")
print "Your name is", name,
print "you are", age, "years old,",
print "and you like the color", color
2 Kod do wyrównania tabeli czasów za pomocą kart wyglądałby następująco:
for looper in range(1, 11):
print looper, "\ttimes 8 =\t", looper * 8
Notice the \t in front of the word times and after the = sign.
3 Here is a program to print the fractions of 8:
for i in range(1, 9):
fraction = i / 8.0
print str(i) + '/8 = %.3f' % fraction
Pierwsza część, drukuj str (i) + '/ 8 =, drukuje ułamek. Ostatnia część,% .3f '% fraction, drukuje liczbę dziesiętną z trzema miejscami po przecinku.
Wejście i wyjście pliku
Sprawdź swoją wiedzę
1 Rodzaj obiektu w Pythonie, który jest używany do pracy z plikami, nazywany jest obiektem pliku.
2 Tworzysz obiekt pliku za pomocą funkcji open (), która jest jedną z wbudowanych funkcji Pythona.
3 Nazwa pliku to nazwa używana do przechowywania pliku na dysku (lub w innym magazynie, takim jak dysk flash). Obiekt pliku jest rzeczą używaną do pracy z plikami w Pythonie. Nazwa obiektu pliku nie musi być taka sama jak nazwa pliku na dysku.
4 Po zakończeniu odczytu lub zapisu pliku program powinien zamknąć plik.
5 Jeśli otworzysz plik w trybie dołączania i napiszesz coś do niego, informacje, które napiszesz, zostaną dodane (dodane) na końcu pliku.
6 Jeśli otworzysz plik w trybie zapisu, a następnie napiszesz coś do pliku, wszystko, co było w pliku, zostanie utracone i zostanie zastąpione nowymi danymi.
7 Aby zresetować punkt odczytu pliku na początek, użyj metody seek () z argumentem 0, takim jak ten:
myFile.seek (0)
8. Aby zapisać obiekt Pythona do pliku za pomocą pikli, należy użyć metody pickle.dump (), z obiektem, który chcesz zapisać i nazwą pliku jako argumentami, takimi jak ten:
pickle.dump (myObject, "my_pickle_file.pkl")
9 Aby usunąć lub pobrać obiekt z pliku pikli, użyj metody pickle.load (), z plikiem pickle jako argumentem, takim jak ten:
myObject = pickle.load ("my_pickle_file.pkl")
Wypróbuj to
1 Oto prosty program do tworzenia głupich zdań:
import random
noun_file = open("nouns.txt", 'r')
nouns = noun_file.readline()
noun_list = nouns.split(',')
noun_file.close()
adj_file = open("adjectives.txt", 'r')
adjectives = adj_file.readline()
adj_list = adjectives.split(',')
adj_file.close()
verb_file = open("verbs.txt", 'r')
verbs = verb_file.readline()
verb_list = verbs.split(',')
verb_file.close()
adverb_file = open("adverbs.txt", 'r')
adverbs = adverb_file.readline()
adverb_list = adverbs.split(',')
adverb_file.close()
noun = random.choice(noun_list)
adj = random.choice(adj_list)
verb = random.choice(verb_list)
adverb = random.choice(adverb_list)
print"The", adj, noun, verb, adverb + '.'
2 Oto program, który zapisuje niektóre dane w pliku tekstowym:
name = raw_input("Enter your name: ")
age = raw_input("Enter your age: ")
color = raw_input("Enter your favorite color: ")
food = raw_input("Enter your favorite food: ")
my_data = open("my_data_file.txt", 'w')
my_data.write(name + "\n")
my_data.write(age + "\n")
my_data.write(color + "\n")
my_data.write(food)
my_data.close()
3 Oto program, który zapisuje niektóre dane za pomocą modułu pickle:
import pickle
name = raw_input("Enter your name: ")
age = raw_input("Enter your age: ")
color = raw_input("Enter your favorite color: ")
food = raw_input("Enter your favorite food: ")
my_list = [name, age, color, food]
pickle_file = open("my_pickle_file.pkl", 'w')
pickle.dump(my_list, pickle_file)
pickle_file.close()
Wykorzystaj szansę - losowość
Sprawdź swoją wiedzę
1 Zdarzenie losowe to coś, co się zdarza ("wydarzenie"), kiedy nie wiesz z wyprzedzeniem, jaki będzie wynik. Dwa przykłady to rzucanie monetą (nie wiesz, czy wyjdzie ona z głów lub ogonów) i rzucanie parą kostek (nie wiesz, jakie liczby pojawią się na kościach).
2 Rzucanie 11-stronną kością różni się od toczenia dwóch 6-stronnych kości, ponieważ przy kości 11-stronnej wszystkie liczby od 2 do 12 mają równe prawdopodobieństwo zbliżenia się. W przypadku dwóch 6-stronnych kości niektóre liczby (sumy dwóch kości) pojawią się częściej niż inne.
3 Oto dwa sposoby symulacji rzutu kostką w Pythonie:
import random
sides = [1, 2, 3, 4, 5, 6]
die_1 = random.choice(sides)
and
import random
die_1 = random.randint(1, 6)
4 Aby reprezentować pojedynczą kartę, użyliśmy obiektu.
5 Aby reprezentować talię kart, użyliśmy listy. Każda pozycja na liście była jedną kartą (obiektem).
6 Aby usunąć kartę z talii lub ręki, użyliśmy metody remove () dla list, takich jak: deck.remove () lub hand.remove ().
Wypróbuj to
1 Po prostu spróbuj i zobacz, co się stanie.
Symulacje komputerowe
Sprawdź swoją wiedzę>
1 Symulacje komputerowe są wykorzystywane z wielu powodów:
•Aby zaoszczędzić pieniądze (robić eksperymenty, które byłyby zbyt drogie, aby robić to w świecie rzeczywistym).
• Aby chronić ludzi i sprzęt (robić eksperymenty, które byłyby zbyt niebezpieczne w rzeczywistym świecie).
• Aby wypróbować rzeczy, które po prostu nie są możliwe w rzeczywistym świecie (np. Dokonanie wielkiej katastrofy asteroid na Księżycu).
•Aby przyspieszyć czas (aby eksperyment przebiegał szybciej niż w prawdziwym świecie). Jest to dobre do studiowania rzeczy, które trwają długo, jak topnienie lodowców.
• Aby spowolnić czas (aby eksperyment przebiegał wolniej niż w prawdziwym świecie). Jest to dobre do badania rzeczy, które zdarzają się bardzo szybko, takich jak elektrony zapadające się w drucie.
2 Możesz wymienić wszelkiego rodzaju symulacje komputerowe, które możesz wymyślić. Mogą to być gry, programy matematyczne lub naukowe, a nawet prognozy pogody (tworzone za pomocą symulacji komputerowych).
3 Obiekt timedelta służy do przechowywania różnicy między dwiema datami lub czasami.
aBitwa Pythona
Wypróbuj to
1 To jest podstawowy robot, który pokonuje CircleAI:
class AI:
def __init__(self):
self.isFirstTurn = True
def turn(self):
if self.isFirstTurn:
self.robot.turnLeft()
self.isFirstTurn = False
elif self.robot.lookInFront() == "bot":
self.robot.attack()
else:
self.robot.doNothing()
Strategia tego robota polega na tym, aby poczekać, aż CircleAI obejdzie planszę i zaatakuje, gdy dotrze do niej CircleAI. Stworzyłem go, wykorzystując swoją wiedzę na temat działania CircleAI i nie wygrałbym z innymi robotami. Jak już wspomniałem w rozdziale, znacznie trudniej byłoby zrobić robota, który wygrywa za każdym razem, nawet jeśli nie wie, z którym robotem walczy.