Цикли
Проблем
Колко ще спестиш?
Решаваш да спестяваш: първия месец отделяш 10 €, втория 20 €, третия 30 € и все така с по 10 € повече. Колко ще имаш след 4 месеца?
total = 0total += 1 * 10total += 2 * 10total += 3 * 10total += 4 * 10print(total)100Работи. Но след 3 години ще са 36 реда, почти еднакви. А ако броят на месеците се въвежда от клавиатурата, изобщо не знаеш колко реда да напишеш. Трябва ти начин да кажеш „повтори това толкова пъти“.
Идеята
for: повтори за всяко число
Повтарящото се парче код се казва цикъл. Най-често ползваният е for. Ето числата от 1 до 10:
for i in range(1, 11): print(i)12345678910for i in range(1, 11): значи „за всяко i от числата, които дава range“. i е броячът: при всеки кръг в него се записва следващото число. range има три части, разделени със запетая:
- Начало:
1. Първото число. Ако го няма,range(10), началото е 0. - Край:
11. Краят не влиза: последното число е 10. Затоваrange(1, 11)е от 1 до 10. - Стъпка: колко се добавя всеки път. Ако я няма, е 1.
range(3, 0, -1)брои назад: 3, 2, 1.
Тялото е отместеното с 4 интервала след двоеточието, както при if.
Всяко изпълнение на тялото се казва итерация или просто кръг.
По-точно, за любопитните
- Стъпката може да е каквато ти трябва: през едно, назад. А
range(10)брои от 0 до 9: пак 10 кръга. Защо се брои от 0, ще стане ясно в урока за списъците.
for i in range(1, 11, 2): print(i, end=" ")print()for i in range(10, 0, -1): print(i, end=" ")print()for i in range(10): print(i, end=" ")print()1 3 5 7 910 9 8 7 6 5 4 3 2 10 1 2 3 4 5 6 7 8 9- В Python броячът остава и след цикъла, с последната си стойност. В Java, C# и JavaScript го няма след цикъла.
for i in range(1, 4): print(i)print("След цикъла i е", i)123След цикъла i е 3- Python няма
forс условие и стъпка катоfor (int i = 1; i <= 10; i++)в Java. Когато трябва „докато нещо е вярно“, имаwhile(след малко).
Виж го
Кръг по кръг
Това са спестяванията от първата карта, с цикъл. Следи как се сменят month и total.
total = 0for month in range(1, 5): total += month * 10print(total) # 100Стъпка по стъпка, с думи
- total започва от 0.
- month = 1, първото число от range(1, 5). Влизаме в тялото.
- Кръг 1: total += 1 * 10, total става 10.
- month става 2, следващото число от range. Още един кръг, total става 30.
- month 3: total става 60.
- month 4: total става 100.
- range(1, 5) няма повече числа: краят 5 не влиза. Цикълът свършва, month остава 4.
- След цикъла total е 100.
Тялото е един ред и е написано веднъж. За 36 месеца сменяш само 5 на 37. А можеш да сложиш там и променлива, прочетена от клавиатурата.
Пробвай
Обратно броене
Какво ще отпечата програмата?
for sec in range(3, 0, -1): print(sec)print("Старт!")range(3, 0, -1) брои назад: 3, 2, 1. Краят 0 не влиза, затова 0 не се печата. Редът след цикъла не е отместен, затова се изпълнява накрая, веднъж.Идеята
while: докато не дойде краят
Понякога не знаеш предварително колко кръга ще има. Касата чете цени, докато касиерът не въведе 0, и тогава казва сметката. Тук for не пасва. Пасва while: повтаря, докато условието е вярно.
total = 0price = int(input())while price != 0: total += price price = int(input())print(f"Общо: {total} €")12470Общо: 23 €Първата цена се чете преди цикъла, за да има какво да провери условието. Следващата се чете в края на тялото. Ако първото число е 0, тялото не се изпълнява нито веднъж.
Понякога тялото трябва да се изпълни поне веднъж, а условието да се провери след кръга. Например въпрос, който се повтаря, докато отговорът не стане приемлив. В Java, C# и JavaScript за това има do-while. В Python го няма. Пише се while True:, цикъл, чието условие е винаги вярно, и вътре break, който го спира, щом отговорът е добър (за break още след малко):
while True: print("Колко билета (от 1 до 10)?") count = int(input()) if 1 <= count <= 10: breakprint(f"Запазени билети: {count}")0153Колко билета (от 1 до 10)?Колко билета (от 1 до 10)?Колко билета (от 1 до 10)?Запазени билети: 3По-точно, за любопитните
- Ако условието никога не стане невярно, цикълът не свършва. Това е безкраен цикъл: програмата „увисва“ и трябва да я спреш ръчно. Най-честата причина е забравена промяна на променливата в условието, например липсващо
price = …в края на тялото. -
while True:безbreakвътре е безкраен цикъл. Провери, че има път доbreak. - Всеки for може да се напише като while. Избираш този, който се чете по-ясно:
forза известен брой кръгове,whileза „докато нещо стане“.
Пробвай
Намери грешката
Програмата трябва да събере числата от 1 до 5: 1 + 2 + 3 + 4 + 5 = 15. Отпечатва 10. На кой ред е грешката?
Избери реда с грешката.
Краят на range не влиза: range(1, n) е 1, 2, 3, 4, и 5 не се добавя: 1 + 2 + 3 + 4 = 10. Трябва range(1, n + 1).
Такава грешка с един кръг повече или по-малко е най-честата при циклите. Проверката „на сухо“ я хваща: разпиши i и total за всеки кръг на лист.
Сумата е в total, не в sum: в Python sum е име на вградена функция и е добре да не го заемаш.
Идеята
break и continue
Две думи сменят обичайния ход на цикъла.
continue прескача останалото от текущия кръг и минава на следващия. Записваш часове за прегледи от 9 до 17, но в 13 е обедната почивка:
for hour in range(9, 18): if hour == 13: continue print(f"{hour}:00")9:0010:0011:0012:0014:0015:0016:0017:00break спира целия цикъл веднага. Търсиш първото число, на което 91 се дели. Щом го намериш, няма смисъл да продължаваш:
n = 91for d in range(2, n): if n % d == 0: print(f"{n} се дели на {d}") break91 се дели на 7По-точно, за любопитните
breakспира само цикъла, в който се намира. Ако е във вложен цикъл (следващата карта), външният продължава.- while True: с break вътре вече го видя: цикъл, който свършва не от условието, а от break на подходящото място.
Идеята
Цикъл в цикъл
Залата на киното има 3 реда по 4 места. Искаш да отпечаташ всички места. За всеки ред минаваш през всички места в него:
for row in range(1, 4): for seat in range(1, 5): print(f"[{row}-{seat}]", end="") print()[1-1][1-2][1-3][1-4][2-1][2-2][2-3][2-4][3-1][3-2][3-3][3-4]Това се казва вложени цикли. Вътрешният цикъл минава целия си път при всеки кръг на външния: 3 реда · 4 места = 12 отпечатвания. end="" казва на print да не слиза на нов ред, затова местата остават на един ред. Празното print() след вътрешния цикъл слиза на нов ред.
Пробвай
Стълбичка
На първия ред трябва да има една звездичка, на втория две, на четвъртия четири. Какво трябва да пише на празното място?
for row in range(1, 5):
for star in range():
print("*", end="")
print()Вътрешният цикъл трябва да се върти толкова пъти, колкото е номерът на реда. Затова границата му е row, броячът на външния цикъл.
Идеята
Случайни числа за игрите
За игра на зарове трябва число, което програмата не знае предварително. Дава го random:
import random
dice = random.randint(1, 6)print(f"Хвърли {dice}")random е модул: готов код, който идва с Python. Включваш го с import random най-горе във файла, както math.
random.randint(1, 6) дава цяло число от 1 до 6. Внимавай: тук и двете граници влизат, за разлика от range.
Всяко пускане дава различно число, затова тук няма изход. Ето и цикъл, който хвърля, докато не се падне шестица:
import random
rolls = 0while True: dice = random.randint(1, 6) rolls += 1 if dice == 6: breakprint(f"Шестица след {rolls} хвърляния")По-точно, за любопитните
- Ако зададеш начално число с
random.seed(42), всяко пускане дава една и съща поредица. Това помага при тестване. random.random()дава дробно число от 0 до 1 (без 1), катоMath.random()в JavaScript.
- Числата не са истински случайни: смятат се по формула. За игри стигат, за пароли и сигурност не.
Упражнение
Задачи с цикли
Реши задачите в редактора си. За всяка има примерен вход и изход, с който да сравниш своя. Числото се чете както в урока „Вход и изход“.
1. Таблица за умножение. Прочети число и отпечатай произведенията му с числата от 1 до 10.
77 x 1 = 77 x 2 = 147 x 3 = 217 x 4 = 287 x 5 = 357 x 6 = 427 x 7 = 497 x 8 = 567 x 9 = 637 x 10 = 702. Просто число. Едно число е просто, ако се дели само на 1 и на себе си: 2, 3, 5, 7, 11… Прочети число и кажи дали е просто. Подсказка: опитай делителите от 2 нагоре и спри с break при първия.
9191 не е простоЗа 11 изходът е „11 е просто“.
3. Цифрите на число. Прочети цяло положително число. Отпечатай го наобратно и сумата на цифрите му. Подсказка: n % 10 е последната цифра, а n // 10 маха последната цифра. Повтаряй, докато числото не стане 0.
2024Обратно: 4202Сума на цифрите: 84. Познай числото. Компютърът „намисля“ число от 1 до 100, а ти го търсиш. След всеки опит програмата казва „По-малко е.“ или „По-голямо е.“, а накрая колко опита ти е отнело. Първо го напиши с тайно число 37, за да провериш с примера:
502537По-малко е.По-голямо е.Позна от 3 опита!Когато работи, смени 37 със случайно число от 1 до 100. Вече и ти не знаеш отговора.
Още задачи
- От 1 до N. Прочети N и отпечатай числата от 1 до N на един ред. За 5:
1 2 3 4 5. - Факториел. N! = 1 · 2 · 3 · … · N. За 5: 120. В Python цялото число няма горна граница: 20! е 2432902008176640000, а 30! се смята също толкова точно.
- Прости числа до N. Отпечатай всички прости числа до N. За 20:
2 3 5 7 11 13 17 19. Проверката от задача 2 отива вътре в цикъл по числата: вложени цикли. - Фибоначи. Всяко число е сумата на предишните две: 0, 1, 1, 2, 3, 5, 8… Прочети N и отпечатай първите N числа. За 10:
0 1 1 2 3 5 8 13 21 34. - Квадрат от звездички. Прочети N и отпечатай квадрат N × N. За 3:
* * ** * ** * *- Триъгълник от звездички. Същото, но на всеки ред толкова звездички, колкото е номерът му. За 3:
** ** * *- Хвърляне на монета. Прочети N, хвърли монета N пъти със случайно число (0 е ези, 1 е тура) и отпечатай колко пъти се е паднало всяко. Колкото по-голямо е N, толкова по-близо са двете числа до N / 2.
- Камък, ножица, хартия. Играч срещу компютър. Играчът въвежда избора си, компютърът избира случайно, програмата казва кой печели. С while True и break пита „Още една игра? (да/не)“ и накрая отпечатва резултата.
Тест