6         LEKCJA 6 – PĘTLE

6.1        Szybkie tworzenie sekwencji

Po uruchomieniu IDLE’a zgłasza się tryb interaktywny Pythona.

Wykorzystamy go do nauki szybkiego tworzenia sekwencji.

Do tworzenia sekwencji, których elementy należą do ciągu arytmetycznego, używamy funkcji range:

 

>>> range(10)

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 

Pojedynczy parametr oznacza koniec (tj. pierwszy element nie należący do) sekwencji (pierwszym elementem zawsze jest zero).

Aby wyświetlić kwadraty liczb od 0 do 9, napiszemy:

 

>>> for x in range(10):

      print x,'** 2 =',x*x

 

     

0 ** 2 = 0

1 ** 2 = 1

2 ** 2 = 4

3 ** 2 = 9

4 ** 2 = 16

5 ** 2 = 25

6 ** 2 = 36

7 ** 2 = 49

8 ** 2 = 64

9 ** 2 = 81

 

Aby zmienić pierwszy element tworzonej sekwencji używamy funkcji range z dwoma parametrami (początek i koniec):

 

>>> range(1,10)

[1, 2, 3, 4, 5, 6, 7, 8, 9]

 

Aby wyświetlić kwadraty liczb od 3 do 9, napiszemy:

 

>>> for x in range(3,10):

      print x,'** 2 =',x*x

 

     

3 ** 2 = 9

4 ** 2 = 16

5 ** 2 = 25

6 ** 2 = 36

7 ** 2 = 49

8 ** 2 = 64

9 ** 2 = 81

 

Aby zmienić krok pomiędzy elementami tworzonej sekwencji używamy funkcji range z trzema parametrami (początek, koniec i krok):

 

>>> range(1,10,2)

[1, 3, 5, 7, 9]

 

Możemy w ten sposób również odwrócić kolejność elementów, poprzez użycie ujemnego kroku:

 

>>> range(9,0,-1)

[9, 8, 7, 6, 5, 4, 3, 2, 1]

 

Aby wyświetlić kwadraty liczb nieparzystych malejąco od 9 do 1, napiszemy:

 

>>> for x in range(9,0,-2):

      print x,'** 2 =',x*x

 

     

9 ** 2 = 81

7 ** 2 = 49

5 ** 2 = 25

3 ** 2 = 9

1 ** 2 = 1

6.2        Formatowanie liczb

Celem pętli często jest wyświetlenie kolumny liczb. Aby liczby wyświetlane były w należyty sposób i w pożądanym miejscu używamy operatora formatowania % w połączeniu z ciągiem formatującym. Ciąg formatujący składa się ze znaku %, po którym następują opcje formatowania, ilość znaków przeznaczonych do wyświetlenia oraz typ danej do wyświetlenia (przy czym tylko trzeci element – tj. typ danych jest wymagany).

Typ danej sygnalizujemy pojedynczą literą. I tak:

 

 

>>> print "%s" % 1

1

>>> print "%s" % range(6)

[0, 1, 2, 3, 4, 5]

>>> print "%s" % "txt"

txt

 

 

>>> print "%c" % "A"

A

>>> print "%c" % 077

?

>>> print "%c" % 33

!

>>> print "%c" % "Abc" # błąd!

 

Traceback (most recent call last):

  File "<pyshell#44>", line 1, in -toplevel-

    print "%c" % "Abc"

TypeError: %c requires int or char

 

 

>>> print "%i" % 0xff

255

>>> print "%i" % 2.2

2

>>> print "%i" % "11" # błąd!

 

Traceback (most recent call last):

  File "<pyshell#32>", line 1, in -toplevel-

    print "%i" % "11" # błąd!

TypeError: int argument required

 

 

>>> print "%x" % 0xff

ff

>>> print "%x" % 2.2

2

>>> print "%x" % 22

16

 

 

>>> print "%o" % 0xff

377

>>> print "%o" % 2.2

2

>>> print "%o" % 077

77

 

>>> print "%e" % 1

1.000000e+000

>>> print "%e" % 1.23

1.230000e+000

>>> print "%e" % 123

1.230000e+002

 

 

>>> print "%f" % 123

123.000000

>>> print "%f" % 1.23

1.230000

6.3        Ustalenie długości pola do wyświetlenia tekstu

Aby przekonać się na czym polega zaleta formatowania, wyświetlmy tabelę kwadratów i sześcianów wybranych liczb:

 

>>> for x in range(5,100,10):

      print x,x**2,x**3

 

     

5 25 125

15 225 3375

25 625 15625

35 1225 42875

45 2025 91125

55 3025 166375

65 4225 274625

75 5625 421875

85 7225 614125

95 9025 857375

 

Jak widać kolumny liczb wyświetlane są nierówno. Spróbujmy ustalić w formacie długość pola do wyświetlenia każdej liczby na 4, jej kwadratu na 6, a sześcianu na 8:

 

>>> for x in range(5,100,10):

      print "%4i%6i%8i" % (x,x**2,x**3)

 

     

   5    25     125

  15   225    3375

  25   625   15625

  35  1225   42875

  45  2025   91125

  55  3025  166375

  65  4225  274625

  75  5625  421875

  85  7225  614125

  95  9025  857375

 

Jak widać, efekt teraz jest znacznie bardziej przejrzysty.

Formatując liczby zmiennopozycyjne możemy także ustalić nie tylko całkowitą długość, ale także liczbę wyświetlanych miejsc po przecinku (np. na 3):

 

>>> for x in range(5,100,10):

      print "Pierwiastkiem liczby %2i jest %5.3f" % (x,x**0.5)

 

     

Pierwiastkiem liczby  5 jest 2.236

Pierwiastkiem liczby 15 jest 3.873

Pierwiastkiem liczby 25 jest 5.000

Pierwiastkiem liczby 35 jest 5.916

Pierwiastkiem liczby 45 jest 6.708

Pierwiastkiem liczby 55 jest 7.416

Pierwiastkiem liczby 65 jest 8.062

Pierwiastkiem liczby 75 jest 8.660

Pierwiastkiem liczby 85 jest 9.220

Pierwiastkiem liczby 95 jest 9.747

6.4        Opcje formatowania

Opcje formatowania modyfikują sposób wyświetlania liczb. Np. opcja + wymusza wyświetlanie znaku liczby, także dla liczb nieujemnych:

 

>>> for x in range (-10,11):

      print "%+i" % x,

 

     

-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10

 

Załóżmy, że chcemy otrzymać tabelę przeliczającą liczby dziesiętne na ósemkowe i szesnastkowe:

 

>>> for x in range(5,100,10):

      print "%3i%6o%5x" % (x,x,x)

 

     

  5     5    5

 15    17    f

 25    31   19

 35    43   23

 45    55   2d

 55    67   37

 65   101   41

 75   113   4b

 85   125   55

 95   137   5f

 

Nie jest to jednoznaczne. Użycie opcji # spowoduje, że liczby ósemkowe i szesnastkowe będą poprzedzane właściwym prefiksem:

 

>>> for x in range(5,100,10):

      print "%3i%#6o%#5x" % (x,x,x)

 

     

  5    05  0x5

 15   017  0xf

 25   031 0x19

 35   043 0x23

 45   055 0x2d

 55   067 0x37

 65  0101 0x41

 75  0113 0x4b

 85  0125 0x55

 95  0137 0x5f

 

Z kolei użycie opcji - spowoduje, że liczby będą wyrównywane do lewej, a nie prawej krawędzi swojego pola:

 

>>> for x in range(5,100,10):

      print "%-3i%#-6o%#-5x" % (x,x,x)

 

     

5  05    0x5 

15 017   0xf 

25 031   0x19

35 043   0x23

45 055   0x2d

55 067   0x37

65 0101  0x41

75 0113  0x4b

85 0125  0x55

95 0137  0x5f

 

Natomiast użycie opcji 0 spowoduje, że pole przeznaczone na liczby będzie wypełniane nie spacjami, lecz zerami:

 

>>> for x in range(5,100,10):

      print "%3i %#04o %#04x" % (x,x,x)

 

     

  5 0005 0x05

 15 0017 0x0f

 25 0031 0x19

 35 0043 0x23

 45 0055 0x2d

 55 0067 0x37

 65 0101 0x41

 75 0113 0x4b

 85 0125 0x55

 95 0137 0x5f

 

6.5        Pętle zagnieżdżone

Pętle mogą zawierać inne pętle – mówimy wtedy o nich, że są zagnieżdżone.

Spróbujmy wygenerować tabliczkę mnożenia:

 

>>> for x in range(1,11):

      print # przejście do nowego wiersza

      for y in range(1,11):

            print "%3i" % (x*y),

 

           

 

  1   2   3   4   5   6   7   8   9  10

  2   4   6   8  10  12  14  16  18  20

  3   6   9  12  15  18  21  24  27  30

  4   8  12  16  20  24  28  32  36  40

  5  10  15  20  25  30  35  40  45  50

  6  12  18  24  30  36  42  48  54  60

  7  14  21  28  35  42  49  56  63  70

  8  16  24  32  40  48  56  64  72  80

  9  18  27  36  45  54  63  72  81  90

 10  20  30  40  50  60  70  80  90 100

6.6        Zmiana przebiegu pętli

Nie wszystkie instrukcje w pętli muszą być wykonane za każdym razem. Do pomijania wszystkich instrukcji znajdujących się po niej w pętli służy instrukcja continue.

Załóżmy, że chcemy napisać program, który wyliczy i wyświetli pierwiastek kwadratowy dla każdej nieujemnej liczby z listy (lub krotki) podanej przez użytkownika.

Aby przejść do edycji nowego programu należy z menu File wybrać polecenie New Window.

Otworzy się nowe okno, przeznaczone do edycji programu. Wybierzmy z menu File polecenie Save As. Wybieramy folder Moje dokumenty, następnie wpisujemy nazwę pierwiastki.py.

 

Przepiszmy następujący program:

 

# Program, który wyliczy i wyświetli pierwiastek kwadratowy

# dla każdej nieujemnej liczby z listy podanej przez użytkownika

liczby = input("Podaj kilka liczb:")

for x in liczby:

    if x<0: continue

    print "Pierwiastkiem liczby %2i jest %5.3f" % (x,x**0.5)

 

W celu uruchomienia programu wybieramy z menu Run polecenie Run Module (lub wciskamy klawisz F5). Po chwili nasz program zostanie uruchomiony. Wypróbujmy:

 

>>>

Podaj kilka liczb:1,-1,2

Pierwiastkiem liczby  1 jest 1.000

Pierwiastkiem liczby  2 jest 1.414

 

Nie wszystkie zaplanowane obiegi pętli muszą być wykonane za każdym razem. Do przerywania pętli w dowolnym miejscu służy instrukcja break.

Załóżmy, że chcemy napisać program, który znajdzie i wyświetli pozycję na liście (lub w krotce) podanej przez użytkownika pierwszego wystąpienia liczby również podanej przez użytkownika.

Aby przejść do edycji nowego programu należy z menu File wybrać polecenie New Window.

Otworzy się nowe okno, przeznaczone do edycji programu. Wybierzmy z menu File polecenie Save As. Wybieramy folder Moje dokumenty, następnie wpisujemy nazwę szukaj.py.

 

# Program, który znajdzie i wyświetli pozycję na liście

# pierwszego wystąpienia określonej liczby

liczby = input("Podaj kilka liczb:")

szukana = input("Podaj liczbę do znalezienia:")

for p,x in enumerate(liczby):

    if x != szukana: continue

    print "Znaleziono liczbę %i na pozycji %i" % (x,p+1)

   

W celu uruchomienia programu wybieramy z menu Run polecenie Run Module (lub wciskamy klawisz F5). Po chwili nasz program zostanie uruchomiony. Wypróbujmy:

 

Podaj kilka liczb:1,2,3,2

Podaj liczbę do znalezienia:2

Znaleziono liczbę 2 na pozycji 2

Znaleziono liczbę 2 na pozycji 4

>>>

 

Jak widać, w tej chwili program wypisuje wszystkie, a nie tylko pierwszą pozycję szukanej liczby. Dopiszmy zatem na końcu programu jedną linię (pamiętajmy o wcięciu!):

 

    break

 

W celu uruchomienia programu wybieramy z menu Run polecenie Run Module (lub wciskamy klawisz F5). Po chwili nasz program zostanie uruchomiony. Wypróbujmy:

 

Podaj kilka liczb:1,2,3,2

Podaj liczbę do znalezienia:2

Znaleziono liczbę 2 na pozycji 2

>>>

 

Jak widać, w tej chwili program wypisuje już tylko pierwszą pozycję szukanej liczby.

Jeżeli jednak podamy liczbę, której nie ma na liście, nic nie zobaczymy:

 

Podaj kilka liczb:1,2

Podaj liczbę do znalezienia:3

>>>

 

Aby to naprawić, posłużymy się instrukcją else. Instrukcja ta określa co ma się wykonać na zakończenie pętli, ale tylko wtedy, gdy nie przerwano pętli instrukcją break.

Dopiszmy jeszcze dwie linie na końcu programu szukaj.py:

 

else:

    print "Liczby %i nie ma na liście" % szukana

 

Wypróbujmy:

 

Podaj kilka liczb:1,2

Podaj liczbę do znalezienia:5

Liczby 5 nie ma na liście

>>> 

 

Podaj kilka liczb:1,3

Podaj liczbę do znalezienia:3

Znaleziono liczbę 3 na pozycji 2

>>> 

6.7        Pętle o nieznanej liczbie powtórzeń

Wiemy już, jak przerwać we właściwym miejscu zbyt długą pętlę. Czasami jednak musimy użyć w programie pętli, której liczby powtórzeń nie jesteśmy w stanie w żaden sposób przewidzieć. Przypomnijmy sobie algorytm Euklidesa na wyliczanie Największego Wspólnego Dzielnika. Powtarzamy w nim operacje dzielenia, nie jesteśmy jednak w stanie z góry powiedzieć, ile tych operacji będzie.

Do tworzenia pętli o nieznanej liczbie powtórzeń w Pythonie służy instrukcja while.

Przejdźmy do okna trybu interaktywnego i wpiszmy:

 

>>> a=[1,2,3,4,5,6]

>>> while a:

                               a=a[:len(a)-1]

                                  print a

 

                                     

[1, 2, 3, 4, 5]

[1, 2, 3, 4]

[1, 2, 3]

[1, 2]

[1]

[]

>>> 

 

Pętla typu while może również zawierać blok po else, wykonywany po ostatnim obiegu pętli:

 

>>> a=7

>>> while a:

      a-=1

print a

else: # wciśnij klawisz backspace by cofnąć wcięcie

print "koniec"

 

                                     

6

5

4

3

2

1

0

koniec

6.8        Przykład: wyliczanie Największego Wspólnego Dzielnika

Spróbujemy teraz napisać program na wyliczanie metodą Euklidesa NWD dwóch liczb podanych przez użytkownika. Aby przejść do edycji nowego programu należy z menu File wybrać polecenie New Window. Otworzy się nowe okno, przeznaczone do edycji programu. Wybierzmy z menu File polecenie Save As. Wybieramy folder Moje dokumenty, następnie wpisujemy nazwę nwd.py.

 

# Wyliczanie NWD i NWW

# 1. wprowadzanie liczb

print "Podaj dwie liczby naturalne:”

a = input("Pierwsza:")

b = input("Druga:")

# 2. ustalenie która jest mniejsza

if a > b:

      w = a

      m = b

else:

      w = b

      m = a

# 3. pętla główna

r = w % m

while r:

      w = m

      m = r

      r = w % m

# 4. wyświetlenie rezultatów

print "NWD liczb %i i %i wynosi %i, a ich NWW wynosi %i" % (a,b,m,a*b/m)

 

Wypróbujmy:

 

>>> ================================ RESTART =============================

>>>

Podaj dwie liczby naturalne:

Pierwsza:6

Druga:8

NWD liczb 6 i 8 wynosi 2, a ich NWW wynosi 24

>>> ================================ RESTART =============================

>>>

Podaj dwie liczby naturalne:

Pierwsza:21

Druga:14

NWD liczb 21 i 14 wynosi 7, a ich NWW wynosi 42

>>> 

6.9        Przykład: wyszukiwanie liczb pierwszych

Do wyszukania liczb pierwszych z podanego zakresu posłużymy się sitem Eratostenesa.

Algorytm ten polega na usuwaniu z badanego zakresu wszystkich wielokrotności kolejnych liczb pierwszych.

Aby przejść do edycji nowego programu należy z menu File wybrać polecenie New Window. Otworzy się nowe okno, przeznaczone do edycji programu. Wybierzmy z menu File polecenie Save As. Wybieramy folder Moje dokumenty, następnie wpisujemy nazwę pierwsze.py.

 

 

# Wyszukiwanie liczb pierwszych

koniec = input("Podaj górną granicę zakresu do wyszukania liczb pierwszych:")

pierwsze = range(koniec+1)

n = 1

while ( n < koniec ):

      n += 1

      if pierwsze[n]==0: # zerem oznaczamy liczby nie-pierwsze

                                  continue

            m = n * 2

      while m <= koniec:

           pierwsze[m]=0 # zerem oznaczamy liczby nie-pierwsze

           m += n

print "Znaleziono następujące liczby pierwsze:"

for n in pierwsze[2:]:

    if n: print n,

 

Wypróbujmy:

 

Podaj górną granicę zakresu do wyszukania liczb pierwszych:99

Znaleziono następujące liczby pierwsze:

1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

>>> 

6.10    Ćwiczenia kontrolne

I.                    Woda zamarza przy 32 stopniach Fahrenheita, a wrze przy 212 stopniach Fahrenheita. Napisz program „stopnie.py”, który wyświetli tabelę przeliczeń stopni Celsjusza na stopnie Fahrenheita w zakresie od –20 do +40 stopni Celsjusza (co 5 stopni). Pamiętaj o wyświetlaniu znaku plus/minus przy temperaturze.

II.                 Napisz program „oceny.py”, który wczytuje od użytkownika kolejne oceny i: