1.3. Duży Lotek¶
Zakładamy, że znasz już podstawy podstaw :-) Pythona, czyli scenariusz Mały Lotek.
Jedna liczba to za mało, wylosujmy ich więcej! Zasady dużego lotka to typowanie 6 liczb z 49. Ponieważ trafienie jest tu bardzo trudne, napiszemy program w taki sposób, aby można było łatwo dostosować poziom jego trudności.
- Utwórz nowy plik
toto2.py
i uzupełnij go wymaganymi liniami wskazującymi interpreter pythona i użyte kodowanie. - Wykorzystując funkcje
raw_input()
orazint()
pobierz od użytkownika ilość liczb, które chce odgadnąć i zapisz wartość w zmiennejileliczb
. - Podobnie jak wyżej pobierz od użytkownika i zapisz maksymalną losowaną liczbę w zmiennej
maksliczba
. - Na koniec wyświetl w konsoli komunikat “Wytypuj ileliczb z maksliczba liczb: ”.
Tip
Do wyświetlenia komunikatu można użyć konstrukcji: print "Wytypuj", ileliczb, "z", maksliczba, " liczb:"
.
Jednak wygodniej korzystać z operatora %
. Wtedy instrukcja przyjmie postać:
print "Wytypuj %s z %s liczb: " % (ileliczb, maksliczba)
. Symbole zastępcze %s
zostaną zastąpione kolejnymi wartościami z listy podanej po operatorze %
.
Najczęściej używamy symboli: %s
– wartość zostaje zamieniona na napis przez funkcję
str()
; %d
– wartość ma być dziesiętną liczbą całkowitą; %f
– oczekujemy liczby
zmiennoprzecinkowej.
1.3.1. Listy¶
1.3.1.1. Ćwiczenie¶
Jedną wylosowaną liczbę zapamiętywaliśmy w jednej zmiennej, ale przechowywanie wielu wartości w osobnych zmiennych nie jest dobrym pomysłem. Najwygodniej byłoby mieć jedną zmienną, w której można zapisać wiele wartości. W Pythonie takim złożonym typem danych jest lista.
Przetestuj w interpreterze następujące polecenia:
~$ python
>>> liczby = []
>>> liczby
>>> liczby.append(1)
>>> liczby.append(2)
>>> liczby.append(4)
>>> liczby.append(4)
>>> liczby
>>> liczby.count(1)
>>> liczby.count(4)
>>> liczby.count(0)
Tip
Klawisze kursora (góra, dół) służą w terminalu do przywoływania poprzednich poleceń. Każde przywołane polecenie możesz przed zatwierdzeniem zmienić używając klawiszy lewo, prawo, del i backspace.
Jak widać po zadeklarowaniu pustej listy (liczby = []
), metoda .append()
pozwala dodawać do niej wartości, a metoda .count()
podaje, ile razy
dana wartość wystąpiła w liście. To się nam przyda ;-)
Wróćmy do programu i pliku toto2.py
, który powinien w tym momencie wyglądać tak:
1 2 3 4 5 6 7 8 9 | #!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
ileliczb = int(raw_input("Podaj ilość typowanych liczb: "))
maksliczba = int(raw_input("Podaj maksymalną losowaną liczbę: "))
# print "Wytypuj", ileliczb, "z", maksliczba, " liczb:"
print "Wytypuj %s z %s liczb: " % (ileliczb, maksliczba)
|
Kodujemy dalej. Użyj pętli:
- dodaj instrukcję
for
, aby wylosowaćileliczb
z zakresu ograniczonego przezmaksliczba
; - kolejne losowane wartości drukuj w terminalu;
- sprawdź działanie kodu.
Trzeba zapamiętać losowane wartości:
- przed pętlą zadeklaruj pustą listę;
- wewnątrz pętli umieść polecenie dodające wylosowane liczby do listy;
- na końcu programu (uwaga na wcięcia) wydrukuj zawartość listy;
- kilkukrotnie przetestuj program.
1.3.2. Pętla while¶
Czy lista zawsze zawiera akceptowalne wartości?
Pętla for
nie nadaje się do unikalnych losowania liczb, ponieważ wykonuje się określoną ilość razy,
a nie możemy zagwarantować, że losowane liczby będą za każdym razem inne.
Do wylosowania podanej ilości liczb wykorzystamy więc pętlę while wyrażenie_logiczne:
,
która powtarza kod dopóki podane wyrażenie jest prawdziwe.
Uzupełniamy kod w pliku toto2.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
ileliczb = int(raw_input("Podaj ilość typowanych liczb: "))
maksliczba = int(raw_input("Podaj maksymalną losowaną liczbę: "))
# print "Wytypuj %s z %s liczb: " % (ileliczb, maksliczba)
liczby = []
# for i in range(ileliczb):
i = 0
while i < ileliczb:
liczba = random.randint(1, maksliczba)
if liczby.count(liczba) == 0:
liczby.append(liczba)
i = i + 1
print "Wylosowane liczby:", liczby
|
Losowane liczby zapamiętujemy w liście liczby
. Zmienna i
to
licznik unikalnych wylosowanych liczb, korzystamy z niej w wyrażeniu
warunkowym i < ileliczb
, które kontroluje powtórzenia pętli. W instrukcji
warunkowej wykorzystujemy funkcję zliczającą wystąpienia wylosowanej wartości
w liście (liczby.count(liczba)
), aby dodawać (liczby.append(liczba)
)
do listy tylko liczby wcześniej niedodane.
1.3.3. Zbiory¶
Przy pobieraniu typów użytkownika użyjemy podobnie jak przed chwilą pętli
while
, ale typy zapisywać będziemy w zbiorze, który z założenia nie
może zawierać duplikatów (zob. zbiór).
1.3.3.1. Ćwiczenie¶
W interpreterze Pythona przetestuj następujące polecenia:
~$ python
>>> typy = set()
>>> typy.add(1)
>>> typy.add(2)
>>> typy
>>> typy.add(2)
>>> typy
>>> typy.add(0)
>>> typy.add(9)
>>> typy
Pierwsza instrukcja deklaruje pusty zbiór (typy = set()
). Metoda .add()
dodaje do zbioru elementy, ale nie da się dodać dwóch takich samych elementów.
Drugą cechą zbiorów jest to, że ich elementy nie są w żaden sposób uporządkowane.
Wykorzystajmy zbiór, aby pobrać od użytkownika typy liczb. W pliku
toto2.py
dopisujemy:
20 21 22 23 24 25 26 27 | print "Wytypuj", ileliczb, "z", maksliczba, "liczb:"
typy = set()
i = 0
while i < ileliczb:
typ = raw_input("Podaj liczbę %s: " % (i + 1))
if typ not in typy:
typy.add(typ)
i = i + 1
|
Zauważ, że operator in
pozwala sprawdzić, czy podana liczba
jest (if typ in typy
) lub nie (if typ not in typy:
) w zbiorze.
Przetestuj program.
1.3.4. Operacje na zbiorach¶
Określenie ilości trafień w większości języków programowania wymagałoby przeszukiwania listy wylosowanych liczb dla każdego podanego typu. W Pythonie możemy użyć arytmetyki zbiorów: wyznaczymy część wspólną.
1.3.4.1. Ćwiczenie¶
W interpreterze przetestuj poniższe instrukcje:
~$ python
>>> liczby = [1,3,5,7,9]
>>> typy = set([2,3,4,5,6])
>>> set(liczby) | typy
>>> set(liczby) - typy
>>> trafione = set(liczby) & typy
>>> len(trafione)
Polecenie set(liczby)
przekształca listę na zbiór. Kolejne operatory
zwracają sumę (|
), różnicę (-
) i iloczyn (&
), czyli część
wspólną zbiorów. Ta ostania operacja bardzo dobrze nadaje się do sprawdzenia,
ile liczb trafił użytkownik. Funkcja len()
zwraca ilość elementów
każdej sekwencji, czyli np. napisu, listy i zbioru.
Do pliku toto2.py
dopisujemy:
31 32 33 34 35 36 | trafione = set(liczby) & typy
if trafione:
print "\nIlość trafień: %s" % len(trafione)
print "Trafione liczby: ", trafione
else:
print "Brak trafień. Spróbuj jeszcze raz!"
|
Instrukcja if trafione:
sprawdza, czy część wspólna zawiera jakiekolwiek elementy.
Jeśli tak, drukujemy liczbę trafień i trafione liczby.
Przetestuj program dla 5 typów z 10 liczb. Działa? Jeśli masz wątpliwości, wpisz wylosowane i wytypowane liczby w interpreterze, np.:
>>> liczby = [1,4,2,6,7]
>>> typy = set([1,2,3,4,5])
>>> trafione = set(liczby) & typy
>>> if trafione:
... print len(trafione)
...
>>> print trafione
Wnioski? Logika kodu jest poprawna, czego dowodzi test w terminalu, ale program nie działa. Dlaczego?
Tip
Przypomnij sobie, jakiego typu wartości zwraca funkcja raw_input()
i użyj we właściwym miejscu funkcji int()
.
Wynik działania programu powinien wyglądać następująco:
1.3.4.2. Do 3 razy sztuka¶
Zastosuj pętlę for
tak, aby użytkownik mógł 3 razy typować liczby z tej
samej serii liczb wylosowanych. Wynik działania programu powinien przypominać
poniższy zrzut:
1.3.5. Błędy¶
Kod naszego programu do tej pory przedstawia się mniej więcej tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
ileliczb = int(raw_input("Podaj ilość typowanych liczb: "))
maksliczba = int(raw_input("Podaj maksymalną losowaną liczbę: "))
liczby = []
i = 0
while i < ileliczb:
liczba = random.randint(1, maksliczba)
print "Wylosowane liczba: %s " % liczba
if liczby.count(liczba) == 0:
liczby.append(liczba)
i = i + 1
for i in range(3):
print "Wytypuj %s z %s liczb: " % (ileliczb, maksliczba)
typy = set()
i = 0
while i < ileliczb:
typ = int(raw_input("Podaj liczbę %s: " % (i + 1)))
if typ not in typy:
typy.add(typ)
i = i + 1
trafione = set(liczby) & typy
if trafione:
print "\nIlość trafień: %s" % len(trafione)
print "Trafione liczby: ", trafione
else:
print "Brak trafień. Spróbuj jeszcze raz!"
print "\n" + "x" * 40 + "\n" # wydrukuj 40 znaków x
print "Wylosowane liczby:", liczby
|
Uruchom powyższy program i podaj ilość losowanych liczb większą od maksymalnej losowanej liczby. Program wpada w nieskończoną pętlę! Po chwili zastanowienia dojdziemy do wniosku, że nie da się wylosować np. 6 unikalnych liczb z zakresu 1-5.
1.3.5.1. Ćwiczenie¶
- Użyj w kodzie instrukcji warunkowej, w przypadku gdy użytkownik chciałby wylosować więcej liczb
niż podany zakres maksymalny, wyświetli komunikat “Błędne dane!” i przerwie wykonywanie programu
za pomocą funkcji
exit()
.
1.3.6. Wyjątki¶
Testujemy dalej. Uruchom program i zamiast liczby podaj tekst. Co się dzieje? Uruchom jeszcze raz, ale tym razem jako typy podaj wartości spoza zakresu <0;maksliczba>. Da się to zrobić?
Jak pewnie zauważyłeś, w pierwszym wypadku zgłoszony zostaje wyjątek ValuError
(zob.: wyjątki) i komunikat invalid literal for int() with base 10
,
który informuje, że funkcja int()
nie jest w stanie przekształcić podanego
ciągu znaków na liczbę całkowitą. W drugim wypadku podanie nielogicznych
typów jest możliwe.
Uzupełnijmy program tak, aby był nieco odporniejszy na niepoprawne dane:
6 7 8 9 10 11 12 13 14 | try:
ileliczb = int(raw_input("Podaj ilość typowanych liczb: "))
maksliczba = int(raw_input("Podaj maksymalną losowaną liczbę: "))
if ileliczb > maksliczba:
print "Błędne dane!"
exit()
except ValueError:
print "Błędne dane!"
exit()
|
Do przechwytywania wyjątków używamy konstrukcji try: ... except: ...
, czyli:
spróbuj wykonać kod w bloku try
, a w razie błędów przechwyć wyjątek i wykonaj
podporządkowane instrukcje. W powyższym przypadku wyświetlamy odpowiedni
komunikat i kończymy działanie programu (exit()
).
Pobierając typy od użytkownika również musimy spróbować przekształcić podane znaki na liczbę i w razie błędu przechwycić wyjątek. Poza tym trzeba sprawdzić, czy użytkownik podaje sensowne typy. Uzupełniamy kod:
28 29 30 31 32 33 34 35 36 37 | while i < ileliczb:
try:
typ = int(raw_input("Podaj liczbę %s: " % (i + 1)))
except ValueError:
print "Błędne dane!"
continue
if 0 < typ <= maksliczba and typ not in typy:
typy.add(typ)
i = i + 1
|
Nowością w powyższym kodzie jest instrukcja continue
. Inaczej niż break
nie przerywa ona działania pętli, ale rozpoczyna jej wykonywanie od początku
ignorując następujące po niej komendy.
Drugą nowością jest warunek if 0 < typ <= maksliczba:
.
Jest to skrócony zapis wyrażenia logicznego z użyciem operatora koniunkcji:
typ > 0 and typ <= maksliczba
. Sprawdzamy w ten sposób czy wartość zmiennej
typ
jest większa od zera i mniejsza lub równa wartości zmiennej maksliczba
.
1.3.7. Materiały¶
Źródła:
Materiały Python 101
udostępniane przez
Centrum Edukacji Obywatelskiej na licencji
Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.
Utworzony: | 2017-09-08 o 19:38 w Sphinx 1.4.5 |
---|---|
Autorzy: | Patrz plik “Autorzy” |