برنامه‌نویسی پایتون فهرست مطالب
فصل ۶

حلقه for

کامپیوتر در یک چیز از انسان خیلی بهتر است: تکرار کردن بدون خستگی و بدون اشتباه. حلقه ابزاری است که این توانایی را در اختیار شما می‌گذارد.

در این فصل می‌خوانید
  1. چرا حلقه لازم است
  2. تابع range و شکل‌هایش
  3. پیمایش رشته
  4. الگوی انباره
  5. شرط داخل حلقه
  6. ورودی گرفتن داخل حلقه
  7. فاکتوریل
  8. شمارش معکوس
  9. انباره و شمارنده با هم
  10. ساختن جدول
  11. دام نام‌گذاری: sum و max و min

۱. چرا حلقه لازم است

فرض کنید بخواهید پنج بار یک پیام چاپ کنید. می‌شود پنج بار 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!

شرح مثال

۲. تابع 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

شرح مثال

۴. الگوی انباره

این مهم‌ترین الگوی این فصل است و در تمام دوره به کارتان می‌آید. سه قدم دارد: متغیری بسازید و صفر بگذارید، داخل حلقه چیزی به آن اضافه کنید، بعد از حلقه از آن استفاده کنید.

# 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 خیلی مهم است

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

شرح مثال

۶. ورودی گرفتن داخل حلقه

# 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 و مانند این موارد

تمرین‌های فصل شش

  1. اعداد ۱ تا ۱۰۰ را چاپ کنید.
  2. مضرب‌های ۳ بین ۱ تا ۱۰۰ را چاپ کنید. یک بار با if و یک بار با گام range.
  3. عدد n را بگیرید و مجموع اعداد ۱ تا n را چاپ کنید.
  4. عدد n را بگیرید و جدول ضربش را از n × 1 تا n × 10 چاپ کنید.
  5. یک کلمه بگیرید و هر کاراکترش را در یک خط جدا چاپ کنید.
  6. ده عدد بگیرید و بگویید چند تایشان منفی بودند.
  7. یک عدد بگیرید و فاکتوریلش را چاپ کنید.
  8. پانزده عدد اول دنباله فیبوناچی را چاپ کنید. هر عدد مجموع دو عدد قبلی است.
  9. یک جمله بگیرید و بشمارید چند فاصله دارد.
فصل قبل: elif و شرط‌های تودرتو فصل بعد: حلقه‌های تودرتو و الگوها