حلقه for
کامپیوتر در یک چیز از انسان خیلی بهتر است: تکرار کردن بدون خستگی و بدون اشتباه. حلقه ابزاری است که این توانایی را در اختیار شما میگذارد.
۱. چرا حلقه لازم است
فرض کنید بخواهید پنج بار یک پیام چاپ کنید. میشود پنج بار
print نوشت. حالا فرض کنید هزار بار. اینجاست که حلقه لازم
میشود.
# Without a loop we would have to write print() five times.
# 'for' repeats the indented block once for every value produced by range().
for i in range(5):
print(i, 'Hello Kadoos!')
print('---')
# range(1, 5) starts at 1 and STOPS BEFORE 5 -> 1, 2, 3, 4
for i in range(1, 5):
print(i, 'Hello Kadoos!')
اولین حلقه: نمونه 01_first_loop.py
0 Hello Kadoos! 1 Hello Kadoos! 2 Hello Kadoos! 3 Hello Kadoos! 4 Hello Kadoos! --- 1 Hello Kadoos! 2 Hello Kadoos! 3 Hello Kadoos! 4 Hello Kadoos!
شرح مثال
- ساختار: کلمه
for، یک نام متغیر، کلمهin، چیزی که باید رویش پیمایش شود، و دونقطه. - متغیر
iدر هر دور، مقدار بعدی را میگیرد. نامش دلخواه است؛iمخفف index است و قراردادی جهانی است، ولی اگر نام معنادارتری دارید بهتر است از آن استفاده کنید. - بلوک تو رفته، بدنه حلقه است و به تعداد مقدارها تکرار میشود.
- مهم:
range(5)از صفر شروع میکند و به پنج نمیرسد. یعنی ۰ و ۱ و ۲ و ۳ و ۴، که دقیقاً پنج عدد است.
۲. تابع range و شکلهایش
# range(stop) -> 0, 1, ..., stop-1
for i in range(5):
print(i, end=' ')
print()
# range(start, stop) -> start, ..., stop-1
for i in range(2, 6):
print(i, end=' ')
print()
# range(start, stop, step) -> jumps of 'step'
for i in range(0, 21, 5):
print(i, end=' ')
print()
# A negative step counts backwards.
for i in range(10, 0, -2):
print(i, end=' ')
print()
# The 'stop' value is NEVER included - this is the most common beginner mistake.
# To print 1..10 we need range(1, 11):
for i in range(1, 11):
print(i, end=' ')
print()
شکلهای range: نمونه 02_range_variants.py
0 1 2 3 4 2 3 4 5 0 5 10 15 20 10 8 6 4 2 1 2 3 4 5 6 7 8 9 10
| شکل | تولید میکند |
|---|---|
range(5) | ۰ تا ۴ |
range(2, 6) | ۲ تا ۵ |
range(0, 21, 5) | ۰ و ۵ و ۱۰ و ۱۵ و ۲۰ |
range(10, 0, -2) | ۱۰ و ۸ و ۶ و ۴ و ۲ |
range(1, 11) | ۱ تا ۱۰ |
عدد پایانی range هرگز تولید نمیشود.
برای چاپ ۱ تا ۱۰ باید بنویسید range(1, 11). این خطا آنقدر
رایج است که در دنیا اسم مخصوص دارد: خطای «یکی کم، یکی زیاد». هر بار
که حلقهای نوشتید، اولین چیزی که باید چک کنید همین است.
در مثال بالا از end=' ' استفاده شده تا اعداد کنار هم چاپ
شوند، و print() خالی بعد از حلقه، خط را میبندد. این همان
نکته فصل اول است که اینجا به کار آمد.
۳. پیمایش رشته
for فقط با range کار نمیکند. هر چیزی که
«مجموعهای از اجزا» باشد را میشود پیمایش کرد، از جمله رشته.
# A 'for' loop can walk directly through the characters of a string.
name = 'Kadoos'
for char in name:
print(char, end=' ')
print()
# Counting the vowels of a sentence.
sentence = input('Enter a sentence: ')
vowels = 0
for char in sentence.lower():
if char in 'aeiou':
vowels += 1
print('Number of vowels:', vowels)
پیمایش رشته: نمونه 03_loop_over_string.py
K a d o o s Enter a sentence: Hello Kadoos Number of vowels: 5
شرح مثال
- در هر دور،
charیک کاراکتر از رشته میگیرد. ضرورتی ندارد با اندیس سر و کله بزنید. char in 'aeiou'میپرسد آیا این کاراکتر یکی از حروف صدادار است. عملگرinرا در فصل سوم دیدیم.lower()باعث میشود حروف بزرگ هم شمرده شوند.- متغیر
vowelsیک شمارنده است: از صفر شروع میشود و هر بار که شرط برقرار شد یکی زیاد میشود.
۴. الگوی انباره
این مهمترین الگوی این فصل است و در تمام دوره به کارتان میآید. سه قدم دارد: متغیری بسازید و صفر بگذارید، داخل حلقه چیزی به آن اضافه کنید، بعد از حلقه از آن استفاده کنید.
# The accumulator pattern:
# 1) start with a variable set to 0
# 2) add something to it on every turn of the loop
# 3) use it after the loop
total = 0
for i in range(10001): # 0, 1, 2, ..., 10000
total = total + i
# the short form is: total += i
print(total)
جمع اعداد تا ده هزار: نمونه 04_sum_to_n.py
50005000
print بیرون حلقه است، پس یک بار و در پایان اجرا میشود.
اگر آن را چهار فاصله تو ببرید، داخل حلقه میرود و ده هزار خط چاپ
میکند. تفاوت یک برنامه درست و یک برنامه بهدردنخور، گاهی فقط چهار
فاصله است.
۵. شرط داخل حلقه
ترکیب if و for به شما اجازه میدهد فقط بعضی از
مقدارها را حساب کنید.
# An 'if' inside a loop lets us accumulate only some of the values.
total = 0
for i in range(10001):
if i % 2 == 0:
total += i
print('Sum of the even numbers from 0 to 10000:', total)
# The same result without an 'if', by making range() jump two by two:
total = 0
for i in range(0, 10001, 2):
total += i
print('Same result with a step of 2:', total)
جمع اعداد زوج: نمونه 05_sum_of_evens.py
شرح مثال
- در روش اول، حلقه ده هزار بار میچرخد و نیمی از دورها بیفایدهاند.
- در روش دوم، خود
rangeدو تا دو تا میپرد و حلقه نصف دورها را میزند. نتیجه یکی است ولی روش دوم هم سریعتر است و هم گویاتر. - درس کلی: پیش از اینکه شرط بگذارید، ببینید میشود اصلاً مقدارهای نامربوط را تولید نکرد.
۶. ورودی گرفتن داخل حلقه
# The loop can also contain an input(): here we read exactly five numbers.
total = 0
for i in range(5):
user_input = input(f'Enter number {i + 1} of 5: ')
number = float(user_input)
total += number
print('Sum:', total)
خواندن پنج عدد: نمونه 06_sum_user_numbers.py
نکته ظریف: در پیام از i + 1 استفاده شده است. چون
i از صفر شروع میشود ولی آدمها از یک میشمارند. اگر
i خالی را چاپ کنید، کاربر پیام «عدد صفر از پنج» میبیند که
عجیب است.
۷. فاکتوریل
# The factorial of n is 1 * 2 * 3 * ... * n
# For a product the accumulator must start at 1, not at 0.
user_input = input('Enter a number: ')
number = int(user_input)
factorial = 1
for i in range(1, number + 1):
factorial = factorial * i
print(f'{number}! = {factorial}')
فاکتوریل: نمونه 07_factorial.py
Enter a number: 5 5! = 120
اگر factorial را صفر بگذارید، هر ضربی در صفر، صفر
میشود و جواب همیشه صفر در میآید. برای جمع باید از
صفر شروع کنید و برای ضرب از یک. عدد شروع باید عنصر
بیاثر آن عمل باشد.
به number + 1 در range دقت کنید: چون عدد
پایانی شامل نمیشود، برای اینکه خود number هم در ضرب شرکت
کند باید یکی بیشتر بنویسیم.
۸. شمارش معکوس
# Counting backwards with a negative step.
user_input = input('Start the countdown from: ')
start = int(user_input)
for i in range(start, 0, -1):
print(i)
print('Lift off!')
شمارش معکوس: نمونه 08_countdown.py
Start the countdown from: 3 3 2 1 Lift off!
گام منفی یعنی از عدد بزرگ به کوچک. عدد پایانی صفر است و شامل نمیشود، پس حلقه روی یک تمام میشود که همان چیزی است که میخواهیم.
۹. انباره و شمارنده با هم
# Two accumulators at the same time: a total and a counter.
user_input = input('How many numbers do you want to enter? ')
count = int(user_input)
total = 0
for i in range(count):
number = float(input(f'Number {i + 1}: '))
total += number
# Dividing by zero must be avoided when the user answers 0.
if count > 0:
print('Average:', total / count)
else:
print('No number was entered.')
میانگین n عدد: نمونه 09_average_of_n.py
اگر کاربر در جواب «چند عدد وارد میکنید» صفر بزند، حلقه اصلاً اجرا
نمیشود و بعد total / count یعنی تقسیم بر صفر، و برنامه
خراب میشود. شرط if count > 0 جلوی آن را میگیرد. هر
جا میانگین میگیرید، به این حالت فکر کنید.
۱۰. ساختن جدول
# Building a small table with a loop. The \t escape keeps the columns aligned.
print('n\tn^2\tn^3')
for n in range(1, 11):
print(f'{n}\t{n ** 2}\t{n ** 3}')
جدول توان: نمونه 10_power_table.py
n n^2 n^3 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125
دنباله \t از فصل سوم اینجا ستونها را مرتب نگه میدارد. اگر
عددها خیلی بزرگ شوند تب کافی نیست و باید از قالببندی عرض ثابت
f-string استفاده کنید، مثل {n:5}.
۱۱. دام نامگذاری: sum و max و min
در نسخه اصلی فایلهای این جلسه، انبارهها نام sum داشتند.
برنامه کار میکرد، ولی یک دام پنهان داشت که ارزش دارد یک بار برای همیشه
ببینیدش.
# Python already has a built-in function called sum().
print(sum([1, 2, 3])) # 6
# If we use 'sum' as a variable name, the function is gone:
sum = 0
for i in range(5):
sum += i
print(sum) # 10 -> this still works
# But now the function no longer exists:
# print(sum([1, 2, 3])) -> TypeError: 'int' object is not callable
چرا متغیر را sum صدا نمیزنیم
همین ماجرا برای max و min و list
و str و input هم صادق است. نامهای جایگزین
سادهاند: total به جای sum،
biggest به جای max، smallest به
جای min. در فصل دهم دوباره به این موضوع برمیگردیم، چون
آنجا واقعاً به آن توابع نیاز داریم.
پوشه S06-for-loops شامل نمونههای
01_first_loop.py تا 10_power_table.py.
خلاصه فصل
| ابزار | وظیفه آن |
|---|---|
for i in range(n): | تکرار n بار، از ۰ تا n منهای یک |
range(a, b) | از a تا b منهای یک |
range(a, b, s) | با گام s. گام منفی یعنی معکوس |
for c in text: | پیمایش کاراکترهای یک رشته |
| انباره | متغیری که پیش از حلقه صفر (یا یک) میشود و داخل حلقه رشد میکند |
| شمارنده | انبارهای که هر بار فقط یکی زیاد میشود |
جای print | داخل حلقه یعنی هر دور، بیرون حلقه یعنی یک بار |
| نامهای ممنوع | sum max min list و مانند این موارد |
تمرینهای فصل شش
- اعداد ۱ تا ۱۰۰ را چاپ کنید.
- مضربهای ۳ بین ۱ تا ۱۰۰ را چاپ کنید. یک بار با
ifو یک بار با گامrange. - عدد
nرا بگیرید و مجموع اعداد ۱ تاnرا چاپ کنید. - عدد
nرا بگیرید و جدول ضربش را ازn × 1تاn × 10چاپ کنید. - یک کلمه بگیرید و هر کاراکترش را در یک خط جدا چاپ کنید.
- ده عدد بگیرید و بگویید چند تایشان منفی بودند.
- یک عدد بگیرید و فاکتوریلش را چاپ کنید.
- پانزده عدد اول دنباله فیبوناچی را چاپ کنید. هر عدد مجموع دو عدد قبلی است.
- یک جمله بگیرید و بشمارید چند فاصله دارد.