Jak się zapętlić z Pythonem?

Posted on 2019-02-04

Obok wyrażeń warunkowych pętle / loops to podstawowy element struktury kodu. Jak to jest w Pythonie?

Python jest inny. Nie ma się co dziwić, że pętle też są inne. No, ale zanim się zagłębimy w kod. Należy odpowiedzieć na pytanie czym jest pętla? Sprawa jest dość prosta - konstrukcja, która zewnia możliwość  powtarzania bloku kodu. Jak długo? - zależy, jakieś paramtery? - zależy. Od czego zależy? Nie od czego, a od kogo. Od programisty zależy - a jeszcze konkretniej od tego co chce zrobić.

Pętla while

Wygląda np. tak:

print('Podaj imię, albo wpisz "q", żeby opuścić program.')
name = input()
while name != 'q':
    print('Cześć, ' + name)
    name = input()

Pętlę deklarujemy przy pomocy słowa kluczowego while następnie podajemy warunek, który musi być spełniony, żeby kolejny przebieg pętli się wykonał, dalej jest blok kodu, do wykonywania w pętli. Jak w powyższym przykładzie, na początku wpiszecie q warunek okaże się fałszem, powitania nie będzie. A co jak by wpisać 1==1, albo True? Pętla będzie nieskończona. Przynajmniej teoretycznie. Z pętli można wyjść przy pomocy słowa kluczowego break, albo inaczej mówiąc - pętlę można przerwać:

print('Podaj imię, albo wpisz "q", żeby opuścić program.')
while True:
    name = input()
    if name == 'q':
        break
    print('Cześć, ' + name)

Oba przykłady są równoważne, przynajmniej jeżeli chodzi o zachowanie. Czytelność pierwszego jest wyższa i to jest preferowane rozwiązanie. Chociaż czasem ktoś pisząc kod, chce podkreślić, że ta, konkretna pętla jest nieskończona. Kiedy? Programy okienkowe mają tak, że po zainicjowaniu większość ich kodu to obsługa zdarzeń, bywa, że robi się to w pętli - zdarzeń. Koniec takiej pętli to koniec programu. Może sobie być nieskończona.

Można też przerwać wykonywanie bloku i przejść do kolejnej iteracji. Takie zachowanie uzyskuje się za pomocą słówka kluczowego continue. Jest to przydatne, jeżeli o pewnych elementach wiadomo, że chcemy je zignorować:

a = 0
while a < 100:
    a += 1
    if a % 5 != 0:
        continue
    print(a)

Zaczynamy z a równym zero. Warunek a < 100 oznacza, że pętla będzie się wykonywać aż a osiągnie pełną setkę. Wyrażenie a += 1 podbija a o jeden. Jest pierwsze w bloku, czyli to się stanie przy każdym przebiegu. Potem jest instrukcja warunkowa. % - to jest modulo, czyli reszta z dzielenia - tutaj dzielimy a przez 5 i sprawdzamy, czy reszta jest zero. Jak nie jest to wykonujemy blok instrukcji warunkowej, czyli przerywamy wykonywanie pętli i przechodzimy do początku. Czyli a + 1 i kolejna wartość jest testowana. Jak się okaże, że jednak reszta z dzielenia jest zero to wypisujemy liczbę na ekranie.

Pętla for

Tu sprawa jest inna, należy podać listę, albo inne coś, po czym pętla ma przejść oraz nazwę zmiennej, do której ma być przypisana kolejna wartość. W bloku kodu, wewnątrz pętli będzie dostęp do tej zmiennej. Kawałek kodu wart 1000 słów, oto przykład:

for a in range(100):
    if a % 5 != 0:
        continue
    print(a)

Jak widać for załatwia nam dbanie o zmienną, kolejne wartości zakończenie pętli. Całkiem to wygodne. A czym jest range. Na ten moment można przyjąć, że to coś co daje wsad dla funkcji for - zaczyna od zera, kończy na 100, bo tak chcemy, z krokiem 1. Czy da się coś tutaj usprawnić? Tak, można iterować od 5, do 100 z krokiem 5. Wtedy wszystko jest na miejscu, nie trzeba tego if-a:

for a in range(5, 100, 5):
    print(a)

Przykład iterowania się po liście:

l = ['Ala', 'Ola', 'Tosia']
for n in l:
    print(n)

Mamy listę imion `for przypisuje kolejne wartości, print wypisuje na ekran.

Pętla w pętli

Pętla jest blokiem kodu - jak każdy inny. Może się więc znaleźć w innej pętli:

for x in range(1, 11):
    for y in range(1, 11):
        print("" + str(x) +" * " + str(y) + " = " + str(x*y))

To jest tabliczka mnożenia. Trochę mozonlie wyląda parametr dla print. Wynika to z tego, że Python w miarę pilnuje typów. Jak chcemy operować na ciągach znaków trzeba to jasno i wyraźnie zakomunikować. Na szczęście można prościej:

for x in range(1, 11):
    for y in range(1, 11):
        print(f"{x} * {y} = {x*y}")

Znaczy to samo. Literka f mówi - zamień wszystko w wąsatych nawiasach na zmienne, wywołania funkcji, trzeba coś policzyć - to policz. Zrób tak, żeby było dobrze.

Coś do wykonania na koniec

Na koniec pętli oczywiście. Pętla for może mieć else. Podobnie jak if. Znaczenie jest trochę inne. W pętli else wykona się zawsze, niezależnie od tego, czy jest po czym iterować, czy nie:

l = ['Ala', 'Ola', 'Tosia']
for n in l:
    print(n)
else:
    print("i frytki")

for n in []:
    print(n)
else:
    print("i frytki")

Przyład, ciut bardziej realny

Załóżmy, że mamy naszą listę imion i trzeba je wrzucić do jednej zmiennej, ale oddzielone przecinkami

l = ['Ala', 'Ola', 'Tosia']
res = ''
for n in l:
    res = res + ', ' + n
print(res)

Czy to zadziała? Tak, czy to jest to o co chdzi? Prawie. Na początku jest przecinek, którego tam być nie powinno. Pewnie jakaś instrukcja warunkowa rozwiąże problem. Skąd wiadomo, że jesteśmy na początku? Jeżeli wynik jest jeszcze pusty, to pewnie przecinek można sobie darować, a w każdym innym przypadku - należy go dopisać:

l = ['Ala', 'Ola', 'Tosia']
res = ''
for n in l:
    if not res:
        res = n
    else:
        res = res + ', ' + n
print(res)