Επανάληψη με while

Θέλεις ένα παιχνίδι που κοστίζει 70 ευρώ και βάζεις στην άκρη 15 ευρώ από το χαρτζιλίκι κάθε εβδομάδα. Πόσες εβδομάδες θα περιμένεις; Με όσα ξέρεις ως τώρα, το πρόγραμμα θα ήταν κάπως έτσι:
python
savings = 0
savings = savings + 15
savings = savings + 15
savings = savings + 15
savings = savings + 15
savings = savings + 15
print(savings)
Για να ξέρεις πόσες γραμμές savings = savings + 15 να γράψεις, πρέπει να έχεις ήδη κάνει τον λογαριασμό στο χαρτί, δηλαδή να έχεις βρει μόνος σου την απάντηση που ζητάς από το πρόγραμμα. Αν το παιχνίδι κάνει 90 ευρώ, προσθέτεις γραμμές. Αν βάζεις 10 την εβδομάδα, προσθέτεις κι άλλες. Κι αν χρειάζονταν 300 επαναλήψεις, θα έγραφες 300 γραμμές. Αυτό που θέλεις να πεις στην Python είναι πιο σύντομο: «πρόσθετε 15, όσο δεν έχεις φτάσει τα 70».

Όσο ισχύει η συνθήκη

Στην Python αυτό το «όσο» το γράφεις με while:
python
Η γραμμή με το while μοιάζει με το if: μια συνθήκη, άνω και κάτω τελεία στο τέλος και από κάτω οι γραμμές με εσοχή. Η διαφορά είναι τι γίνεται μετά. Το if τρέχει τις γραμμές του μία φορά. Το while τις τρέχει, πηγαίνει ξανά στη συνθήκη και ρωτάει πάλι. Όσο η συνθήκη δίνει True, οι γραμμές ξανατρέχουν. Μόλις δώσει False, η Python προχωράει στην πρώτη γραμμή χωρίς εσοχή, εδώ το πρώτο print.
Ένα κομμάτι κώδικα που τρέχει ξανά και ξανά λέγεται loop και οι γραμμές με εσοχή κάτω από το while είναι το σώμα του. Στο σχολικό βιβλίο θα το βρεις ως δομή επανάληψης.
Το loop του while Διάγραμμα ροής: πρώτα savings = 0 και weeks = 0. Μετά ο έλεγχος savings < game_price. Αν δίνει True, τρέχει το σώμα του loop, savings = savings + weekly και weeks = weeks + 1, και το βέλος γυρίζει πίσω στον έλεγχο. Αν δίνει False, το πρόγραμμα βγαίνει από το loop και πάει στο print. True ξανά False savings = 0 weeks = 0 savings < game_price savings = savings + weekly weeks = weeks + 1 σώμα του loop print(...)
Το weeks είναι ένας μετρητής: ξεκινάει από το 0 και ανεβαίνει κατά 1 σε κάθε πέρασμα, οπότε στο τέλος λέει πόσες φορές έτρεξε το σώμα. Τρέξε το πρόγραμμα. Μετά άλλαξε το weekly σε 20 και, πριν πατήσεις Τρέξε, υπολόγισε με το μυαλό πόσες εβδομάδες θα βγάλει. Το πρόγραμμα δεν αλλάζει σε τίποτα άλλο: ό,τι τιμή κι αν βάλεις στην κορυφή, το loop τρέχει όσες φορές χρειάζεται.

Πότε η Python ελέγχει τη συνθήκη

Με τις αρχικές τιμές το πρόγραμμα τυπώνει Μάζεψες: 75. Το 70 δε διαιρείται με το 15, οπότε το τελευταίο πέρασμα το ξεπερνάει. Τι κάνει όμως η Python στη μέση ενός περάσματος; Δοκίμασε ένα μικρότερο loop, όπου ο μετρητής ανεβαίνει πρώτα και μετά το print τον τυπώνει:
Πρόβλεψε
count = 0
while count < 3:
    count = count + 1
    print(count)

Τι θα εμφανιστεί στην οθόνη;

Διάλεξε μία

Το ίδιο φαίνεται και στον κουμπαρά. Στον πέμπτο έλεγχο το savings είναι 60, το 60 < 70 δίνει True και ξεκινάει ένα ακόμα πέρασμα, που τελειώνει ολόκληρο στα 75. Με 60 ευρώ δεν αγοράζεις το παιχνίδι, οπότε χρειάζεσαι όντως πέντε εβδομάδες και θα σου περισσέψουν 5 ευρώ.
Το savings σε κάθε έλεγχο του while Χρονολόγιο έξι ελέγχων. Με weeks = 0 το savings είναι 0 και το 0 < 70 δίνει True. Με weeks = 1 έως 4 το savings γίνεται 15, 30, 45, 60 και ο έλεγχος δίνει κάθε φορά True. Με weeks = 5 το savings είναι 75, το 75 < 70 δίνει False και το loop σταματάει. Με 60 ευρώ ο έλεγχος δίνει ακόμα True, οπότε γίνεται άλλο ένα πέρασμα. savings ΣΕ ΚΑΘΕ ΕΛΕΓΧΟ 0 weeks = 0 0 < 70 True 15 weeks = 1 15 < 70 True 30 weeks = 2 30 < 70 True 45 weeks = 3 45 < 70 True 60 weeks = 4 60 < 70 True 75 weeks = 5 75 < 70 False Με 60 ευρώ ο έλεγχος δίνει ακόμα True, οπότε γίνεται άλλο ένα πέρασμα.
Σε ένα παιχνίδι στο κινητό ξεκινάς με τρεις ζωές και θέλεις να δείχνεις πόσες έχουν μείνει πριν χάσεις την καθεμία. Εδώ το print είναι πρώτο και η αφαίρεση δεύτερη. Προχώρα βήμα βήμα και κοίτα πότε αλλάζει το lives:
Βήμα προς βήμα
Βήμα 1 από 12
lives = 3
while lives > 0:
print("Ζωές:", lives)
lives = lives - 1
print("Game over")
Μεταβλητές

lives = 3

Ξεκινάς με τρεις ζωές.

Ένα loop που δεν τελειώνει

Αν το σώμα δεν αλλάζει ποτέ την τιμή που ελέγχει η συνθήκη, η συνθήκη δίνει True για πάντα. Ένα δάνειο 300 ευρώ το ξεπληρώνεις με 100 ευρώ τον μήνα, αλλά σε αυτό το πρόγραμμα κάποιος ξέχασε να αφαιρεί τη δόση. Για να μη γεμίσει η οθόνη, τυπώνει μόνο μία γραμμή κάθε 12 μήνες. Τρέξε το και πάτα Σταμάτα όταν καταλάβεις τι γίνεται:
python
Τα χρόνια περνάνε και το χρέος μένει 300. Αυτό λέγεται ατέρμονο loop: η Python δε θα φτάσει ποτέ στο τελευταίο print, γιατί το debt > 0 δεν αλλάζει ποτέ. Πρόσθεσε στο σώμα, με εσοχή, τη γραμμή που λείπει, debt = debt - 100, και τρέξε ξανά. Τώρα πρέπει να δεις μόνο το Εξοφλήθηκε σε 3 μήνες, αφού το δάνειο κλείνει πριν συμπληρωθεί ένα έτος.
Υπάρχει και πιο ύπουλη εκδοχή, όπου η τιμή αλλάζει κανονικά αλλά η συνθήκη δεν παύει ποτέ να ισχύει. Αν ο κουμπαράς έλεγχε while savings != 70:, με 15 ευρώ την εβδομάδα το savings θα περνούσε από το 60 στο 75 χωρίς να γίνει ποτέ ακριβώς 70. Γι' αυτό σε ένα loop που μετράει προς ένα όριο βάζεις < ή > και όχι !=.
Για κάθε while που γράφεις, βρες ποια γραμμή του σώματος φέρνει τη συνθήκη πιο κοντά στο False. Αν δεν υπάρχει τέτοια γραμμή, το loop δε θα σταματήσει.

Η συντομογραφία +=

Οι γραμμές του τύπου weeks = weeks + 1 είναι τόσο συνηθισμένες στα loops, που η Python, όπως και οι περισσότερες γλώσσες, έχει συντομογραφία γι' αυτές:
python
weeks += 1         # το ίδιο με weeks = weeks + 1
savings += weekly  # το ίδιο με savings = savings + weekly
lives -= 1         # το ίδιο με lives = lives - 1
Κάνουν ακριβώς το ίδιο: υπολογίζουν το δεξί μέρος με την τρέχουσα τιμή και βάζουν το αποτέλεσμα πίσω στο ίδιο όνομα. Στον κώδικα άλλων θα βρεις κυρίως τη σύντομη μορφή.

Το ίδιο σε ψευδοκώδικα

Ο κουμπαράς σε ψευδοκώδικα:
ΓΛΩΣΣΑ
ΠΡΟΓΡΑΜΜΑ ΚΟΥΜΠΑΡΑΣ
ΜΕΤΑΒΛΗΤΕΣ
  ΑΚΕΡΑΙΕΣ: ΤΙΜΗ_ΠΑΙΧΝΙΔΙΟΥ, ΕΒΔΟΜΑΔΙΑΙΑ, ΑΠΟΤΑΜΙΕΥΣΗ, ΕΒΔΟΜΑΔΕΣ
ΑΡΧΗ
  ΤΙΜΗ_ΠΑΙΧΝΙΔΙΟΥ ← 70
  ΕΒΔΟΜΑΔΙΑΙΑ ← 15
  ΑΠΟΤΑΜΙΕΥΣΗ ← 0
  ΕΒΔΟΜΑΔΕΣ ← 0
  ΟΣΟ ΑΠΟΤΑΜΙΕΥΣΗ < ΤΙΜΗ_ΠΑΙΧΝΙΔΙΟΥ ΕΠΑΝΑΛΑΒΕ
    ΑΠΟΤΑΜΙΕΥΣΗ ← ΑΠΟΤΑΜΙΕΥΣΗ + ΕΒΔΟΜΑΔΙΑΙΑ
    ΕΒΔΟΜΑΔΕΣ ← ΕΒΔΟΜΑΔΕΣ + 1
  ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
  ΓΡΑΨΕ 'Εβδομάδες:', ΕΒΔΟΜΑΔΕΣ
  ΓΡΑΨΕ 'Μάζεψες:', ΑΠΟΤΑΜΙΕΥΣΗ
ΤΕΛΟΣ_ΠΡΟΓΡΑΜΜΑΤΟΣ
Το ΟΣΟ ... ΕΠΑΝΑΛΑΒΕ είναι το while, με τον ίδιο έλεγχο πριν από κάθε πέρασμα. Το σώμα κλείνει με ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ, ενώ η Python καταλαβαίνει πού τελειώνει από την πρώτη γραμμή χωρίς εσοχή. Η ΓΛΩΣΣΑ δεν έχει +=, οπότε γράφεις πάντα ολόκληρη την εκχώρηση. Στη ΓΛΩΣΣΑ υπάρχει και η ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ ... ΜΕΧΡΙΣ_ΟΤΟΥ συνθήκη: ελέγχει μετά το σώμα, οπότε το σώμα τρέχει τουλάχιστον μία φορά, και σταματάει όταν η συνθήκη γίνει αληθής, όχι ψευδής.

Σύνοψη

  • Το while τρέχει το σώμα του ξανά και ξανά, όσο η συνθήκη του δίνει True. Μόλις δώσει False, η Python συνεχίζει στην πρώτη γραμμή χωρίς εσοχή.
  • Δε χρειάζεται να ξέρεις από πριν πόσες φορές θα τρέξει. Αυτό το αποφασίζουν οι τιμές.
  • Η Python ελέγχει τη συνθήκη μόνο πριν από κάθε πέρασμα. Ένα πέρασμα που ξεκίνησε τελειώνει ολόκληρο, ακόμα κι αν η συνθήκη πάψει να ισχύει στη μέση του.
  • Ένας μετρητής ξεκινάει από 0 και ανεβαίνει κατά 1 σε κάθε πέρασμα. Στο τέλος σου λέει πόσες φορές έτρεξε το σώμα.
  • Αν καμία γραμμή του σώματος δε φέρνει τη συνθήκη πιο κοντά στο False, το loop δεν τελειώνει. Στη σελίδα το σταματάς με το κουμπί Σταμάτα.
  • Το x += 1 είναι συντομογραφία του x = x + 1 και το x -= 1 του x = x - 1.
  • Στον ψευδοκώδικα γράφεις το while ως ΟΣΟ ... ΕΠΑΝΑΛΑΒΕ και το κλείνεις με ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ. Η ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ ... ΜΕΧΡΙΣ_ΟΤΟΥ ελέγχει μετά το σώμα και σταματάει όταν η συνθήκη γίνει αληθής.

Θες να συνεχίσεις;

Το course είναι δωρεάν. Κάνε σύνδεση για να κρατάς την πρόοδο και τις σημειώσεις σου.