در آموزشهای گذشته با حلقۀ while
آشنا شدیم و نحوۀ بهکارگیری این ساختار را در قالب یکسری مثال کاربردی بررسی کردیم و دیدیم که در صورت برقرار بودن شرایطی خاص، اجرای دستورات داخل بدنۀ حلقه تکرار میشوند اما در این آموزش قصد داریم با ساختار حلقۀ for
آشنا شویم. در واقع، دستور for
همچون دستور while
برای تکرار اجرای یک قطعه کد مورد استفاده قرار میگیرد با این تفاوت که در بهکارگیری حلقۀ for
دقیقاً میدانیم که تَسک مد نظر را چند مرتبه باید تکرار کنیم. فرم کلی حلقۀ for
بدین صورت میباشد:
for target in object: # Assign object items to target
#block(s) of statements, Repeated loop body: uses target
✨ برای آموزش ویدیویی پایتون اینجا کلیک کنید. ✨
در حالت عادی و بر اساس الگوی فوق هر حلقۀ for
دقیقاً به تعداد عضوهای دنبالۀ object
تکرار میشود بدین صورت که هر یک از اعضای دنباله به ترتیب و با شروع از عضو اول به متغیر target
منتسب شده و دستورات داخل بدنۀ حلقه به ازای هر یک از انتسابها اجرا میشوند و این پروسه تا زمان اِتمام اعضای دنبالۀ object
ادامه پیدا میکند.
حال به منظور آشنایی بیشتر با ساختار دستور for
و نحوۀ کارکرد آن در زبان برنامهنویسی پایتون مثالی را در ادامه بررسی میکنیم که در آن قصد داریم تا با کمک حلقۀ for
هر یک از حروف استرینگ «SokanAcademy» را به صورت جداگانه در خروجی چاپ کنیم:
letterNum = 0
for letter in "SokanAcademy":
letterNum += 1
print("Letter ", letterNum, " is ", letter,".")
print("SokanAcademy has", letterNum, "letters.")
در کد فوق متغیری با شناسۀ letterNum
تعریف کرده و عدد صحیح 0 را به آن اختصاص دادهایم که قرار است تا به منظور شمارش تعداد حروف کلمۀ مد نظر یا به عبارتی شمارش تعداد دفعات تکرار اجرای دستوراتِ داخل حلقۀ for
مورد استفاده قرار گیرد بدین صورت که مقدار منتسب به متغیر letterNum
در هر بار اجرای حلقه یک واحد افزایش پیدا کرده و مقدار نهایی آن در خروجی چاپ میشود.
در سطر بعد یک دستور مرکب تعریف کردهایم که با کیورد for
آغاز شده سپس شناسۀ یک متغیر دلخواه همچون letter
و به دنبال آن کیورد in
را آوردهایم و بدین ترتیب به مفسر پایتون گفتهایم که در ادامه دادهای از نوع دنباله و از جنس استرینگ با مقدار «SokanAcademy» را مد نظر قرار دهد (توجه داشته باشیم که دنبالهها انواع مختلفی دارند که در آموزشهای آینده با آنها آشنا خواهیم شد.)
نکته یک آبجکت از نوع دنباله متشکل از چند عضو است که هر یک از اعضای آن به ترتیب و یکی پس از دیگری در جای ثابتی قرار گرفته و دنبالهای را ایجاد میکنند.
همانطور که در آموزشهای گذشته اشاره کردیم، آبجکتهای استرینگ از نوع دادۀ دنباله هستند چرا که هر آبجکت استرینگ از تعدادی حروف تشکیل شده است که به ترتیب و پشت سر هم در یک ردیف آمدهاند و جایگاه هر یک از حروف در این دنباله ثابت است به طوری که عوض کردن جایگاه هر یک از اعضای دنباله منجر به ایجاد دنبالۀ جدیدی میشود. برای مثال، دنبالههایی همچون «eat» و «ate» از حروف یکسانی تشکیل شدهاند اما ترتیب اعضای آنها متفاوت بوده و از همین روی دو دنبالۀ متفاوت محسوب میشوند.
حال به مثال فوق برمیگردیم و در ادامۀ تعریف دنبالهای از جنس استرینگ، سربند دستور مرکب for
را با علامت :
به پایان میرسانیم و بدین ترتیب به مفسر پایتون میگوییم به ازای هر یک از حروف دنبالۀ «SokanAcademy» دستورات بدنۀ داخلی را اجرا کند که برای دسترسی به هر یک از حروف دنباله نیز از متغیر letter
استفاده میکنیم بدین صورت که در هر بار تکرار حلقۀ for
حروف دنبالۀ «SokanAcademy» به ترتیب به متغیر letter
منتسب میشوند.
در ادامه دستورات بدنۀ داخلی حلقۀ for
را با رعایت تورفتگی نسبت به بلوک سربند و در یک بلوک مجزا مینویسیم به طوری که در هر نوبت از اجرای حلقهٔ for
توسط مفسر اجرا میشوند و در هر بار یک واحد به متغیر letterNum
افزوده شده و دستور ()print
اجرا میشود.
در واقع، فانکشن ()print
را داخل حلقۀ for
با پنج آرگومان ورودی فراخوانی کردهایم که در آن گفتهایم در هر بار اجرای حلقه آخرین مقدار منتسب به متغیر letterNum
یا به عبارتی اندیس هر حرف از دنبالۀ فوقالذکر و همچنین مقدار متناظر آن از متغیر letter
یا هر یک از حروف مربوطه از دنباله را به همراه استرینگهای تعریفشده در خروجی چاپ کند و در نهایت پس از خروج از بدنۀ حلقۀ for
فانکشن ()print
را با آرگومان ورودی letterNum
فراخوانی کردهایم تا پس از پایان تکرارها در حلقۀ for
تعداد حروف دنبالۀ مذکور را در خروجی چاپ کند.
اسکریپت این برنامه را در فایلی به نام forLoop.py
ذخیره کرده و آن را اجرا میکنیم که در خروجی خواهیم داشت:
Letter 1 is S .
Letter 2 is o .
Letter 3 is k .
Letter 4 is a .
Letter 5 is n .
Letter 6 is A .
Letter 7 is c .
Letter 8 is a .
Letter 9 is d .
Letter 10 is e .
Letter 11 is m .
Letter 12 is y .
SokanAcademy has 12 letters.
همانطور که اشاره کردیم، در حالت عادی حلقۀ for
به ازای تمامی اعضای دنباله اجرا میشود اما نکتۀ قابلتوجه اینکه در حلقۀ for
نیز همچون حلقۀ while
با بهکارگیری کیوردهای break
و continue
یا دستور else
میتوانیم جریان عادی اجرای حلقه را کنترل کنیم که در ادامه کاربرد هر یک از دستورها را در حلقۀ for
و در قالب چند مثال بررسی میکنیم.
کاربرد دستور break در حلقۀ for
برای درک نحوۀ کارکرد دستور break
در حلقۀ for
مثالی را در نظر میگیریم که در آن یک مقدار ورودی را از کاربر دریافت کرده سپس با استفاده از حلقۀ for
حروف بهکاررفته در کلمۀ ورودی را در خروجی چاپ میکنیم به طوری که محدودیتی در تعداد کاراکترهای کلمۀ ورودی توسط کاربر در نظر میگیریم تا تعداد کاراکترهای کلمۀ ورودی شش حرف یا کمتر باشد که برای پیادهسازی چنین مثالی کدی مانند زیر خواهیم داشت:
username = input("Enter a username less than 6 characters: ")
letterNum = 1
for letter in username:
print("Letter ", letterNum, " is ", letter)
letterNum += 1
if letterNum > 6:
print("Your username is too long!")
break
در کد فوق متغیری تحت عنوان username
تعریف کرده و کلمۀ ورودی توسط کاربر را به آن منتسب میکنیم و در ادامه متغیری به نام letterNum
تعریف میکنیم که این متغیر را به منظور شمارش تعداد حروف کلمۀ ورودی به کار میگیریم. در ادامه دستور for
را تعریف کردهایم که در آن گفتهایم هر یک از حروف کلمۀ ذخیرهشده در متغیر username
به ترتیب به متغیر letter
منتسب شده و توسط فانکشن ()print
در خروجی چاپ شوند و به ازای هر بار اجرای حلقۀ for
نیز یک واحد به متغیر letterNum
اضافه شده و به همراه هر یک از حروف کلمۀ ورودی در خروجی چاپ شوند.
حال اگر مقدار منتسب به متغیر letterNum
بیشتر از شش شود یا به عبارتی کلمۀ ورودی کاربر بیش از شش کاراکتر داشته باشد به طوری که حلقۀ for
برای بار ششم اجرا شده و مقدار متغیر letterNum
برابر با عدد هفت گردد، شرط سطر ششم True
ارزیابی شده و دستورات بدنۀ داخلی آن اجرا میشوند که در آن گفتهایم استرینگ «!Your username is too long» در خروجی چاپ شده و در ادامه دستور break
اجرا شود که در نهایت برنامه به طور کامل از حلقۀ for
خارج شده و ادامۀ حروف کلمۀ ورودی را چاپ نمیکند.
اسکریپت این برنامه را در فایلی به نام forBreak.py
ذخیره کرده و آن را اجرا میکنیم که در خروجی خواهیم داشت:
Enter a username less than 6 characters: NargesAsadi
Letter 1 is N
Letter 2 is a
Letter 3 is r
Letter 4 is g
Letter 5 is e
Letter 6 is s
Your username is too long!
همانطور که میبینید، حلقۀ for
شش مرتبه اجرا شده سپس برنامه به طور کامل از آن خارج شده و سایر کاراکترهای کلمۀ ورودی را چاپ نکرده است.
کاربرد دستور continue در حلقۀ for
در این مرحله مثالی مد نظر قرار میدهیم که در آن قصد داریم تا تعداد حروف استرینگ «SokanAcademy» را در خروجی چاپ کنیم به طوری که حروف a یا A از آن نادیده گرفته شده و چاپ نشوند که برای این منظور کدی مانند زیر خواهیم داشت:
letterNum = 0
for letter in "SokanAcademy":
letterNum += 1
if (letter == "a" or letter == "A"):
print("Letter ", letterNum, " is ", letter, "and not processed.")
continue
print("Letter ", letterNum, " is ", letter)
در کد فوق یک دستور if
در بدنۀ داخلی حلقۀ for
تعریف کرده و در آن گفتهایم چنانچه مقدار منتسب به متغیر letter
برابر با هر یک از حروف a یا A باشد، شرط برقرار بوده و دستورات بدنۀ داخلی آن اجرا شوند و بدین ترتیب فانکشن ()print
فراخوانی شده و منجر به چاپ هر یک از حروف a یا A و همچنین اندیس متناظرشان به همراه استرینگ فوقالذکر در خروجی میشود و در ادامه دستور continue
اجرا شده و بدین ترتیب سایر دستورهای برنامه نادیده گرفته میشوند به طوری که مفسر مجدداً به ابتدای حلقه بازمیگردد و دور بعدی تکرار حلقه را با حرف بعدی شروع میکند.
اسکریپت این برنامه را در فایلی به نام forContinue.py
ذخیره کرده و آن را اجرا میکنیم که در خروجی خواهیم داشت:
Letter 1 is S
Letter 2 is o
Letter 3 is k
Letter 4 is a and not processed.
Letter 5 is n
Letter 6 is A and not processed.
Letter 7 is c
Letter 8 is a and not processed.
Letter 9 is d
Letter 10 is e
Letter 11 is m
Letter 12 is y
همانطور که میبینید، حروف چهارم، ششم و هشتم در خروجی چاپ نشدهاند. حال فرض کنید به جای دستور continue
در کد فوق از دستور break
استفاده کنیم که در چنین شرایطی با اجرای حلقۀ for
و رسیدن به هر یک از حروف A یا a دستور break
اجرا شده و برنامه از حلقۀ تکرار خارج میشود و بدین ترتیب سایر اعضای دنباله نادیده گرفته شده و چاپ نمیشوند اما این در حالی است که دستور continue
تنها یک دور از تکرار حلقۀ for
را نادیده گرفته و اجرای آن را از ابتدا آغاز میکند.
به خاطر داشته باشید برای استفادۀ منطقی از دستورهای break و continue در حلقهها آنها را در بدنۀ یک دستور شرطی قرار میدهیم.
کاربرد فانکشن ()range در حلقۀ for
فرض کنید بخواهیم دنبالهای از اعداد صحیح 0 تا 9 را در یک حلقۀ for
مورد استفاده قرار دهیم که یکی از روشهای ایجاد این دنباله استفاده از فانکشن از پیش تعریفشدۀ ()range
است که برای آشنایی با کاربردهای فانکشن ()range
در حلقۀ for
برنامۀ زیر را مد نظر قرار میدهیم:
# range(stop)
for i in range(10):
print(i)
در کد فوق فانکشن ()range
را با یک آرگومان ورودی فراخوانی کردهایم که به عنوان نقطۀ پایانی دنباله در نظر گرفته شده و دنبالهای از اعداد صحیح کمتر از آن (بازۀ 0 تا 9) را ریترن میکند. همانطور که میبینید، در حلقۀ for
گفتهایم به ازای هر یک از مقادیر دنبالۀ مذکور فانکشن ()print
فراخوانی شده و اعداد بازۀ 0 تا 9 را در خروجی چاپ کند.
اسکریپت این برنامه را در فایلی به نام range.py
ذخیره کرده و آن را اجرا میکنیم که در خروجی خواهیم داشت:
0
1
2
3
4
5
6
7
8
9
حال اگر بخواهیم دنبالهای از اعداد صحیح را در بازهای مشخص در خروجی چاپ کنیم، از الگوی (range(start, stop
استفاده میکنیم و بدین ترتیب دو آرگومان ورودی به فانکشن ()range
میدهیم که به عنوان نقطۀ شروع و پایان بازۀ مذکور در نظر گرفته میشوند. برای مثال، برنامۀ زیر را مد نظر قرار میدهیم:
# range(start, stop)
for i in range(5, 10):
print(i)
در برنامۀ فوق گفتهایم اعداد صحیح متعلق به بازۀ 5 تا 10 در هر بار اجرای حلقۀ for
به ترتیب به متغیر i
منتسب شده در خروجی چاپ شوند که خروجی حاصل از اجرای برنامه بدین ترتیب خواهد بود:
5
6
7
8
9
همانطور که میبینید، آرگومان ورودی اول به فانکشن ()range
به عنوان اولین عدد از دنبالۀ فوق در نظر گرفته شده و اعداد بعدی نیز به ترتیب چاپ شدهاند و با رسیدن به نقطۀ انتهایی (عدد صحیح 10) دنباله پایان یافته و خود عدد مربوط به آرگومان دوم (نقطۀ پایانی) به عنوان عضو دنباله محسوب نشده است.
نکته در الگوی فانکشن (range(start, stop هر یک از آرگومانهای ورودی اول و دوم میتوانند اعداد صحیحی با مقادیر منفی باشند اما در چنین شرایطی عدد مربوط به آرگومان ورودی اول میباید از عدد آرگومان دوم کوچکتر باشد و در غیر این صورت دنبالهای بدون عضو تولید میشود.
همچنین اگر بخواهیم دنبالهای از اعداد صحیح با فاصلهای یکسان از یکدیگر تولید کنیم به طوری که اعداد دنباله بیش از یک واحد با هم اختلاف داشته باشند از فانکشن ()range
بر اساس الگوی (range(start, stop, step
استفاده میکنیم. برای مثال، برنامۀ زیر را در نظر میگیریم:
# range(start, stop, step)
for i in range(0, 20, 3):
print(i)
در کد فوق فانکشن ()range
را با سه آرگومان ورودی فراخوانی کردهایم که در آن گفتهایم دنبالهای از اعداد صحیح با شروع از عدد 0 تا 20 (غیر از خود عدد 20) در خروجی چاپ شود به طوری که هر عضو با عضو قبل و بعد خود سه واحد اختلاف داشته باشد که با اجرای این کد در خروجی خواهیم داشت:
0
3
6
9
12
15
18
اگر بخواهیم دنبالۀ اعداد به صورت نزولی و با شروع از عدد بزرگتر چاپ شوند نیاز است تا فاصلۀ اعداد دنباله را یک عدد صحیح منفی تعریف کنیم. برای مثال، کد زیر را مد نظر قرار میدهیم:
# range(start, stop, negativeStep)
for i in range(20, 2, -2):
print(i)
در کد فوق گفتهایم دنبالۀ اعداد صحیح به صورت نزولی و با شروع از عدد 20 چاپ شود به طوری که اعداد دنباله به اندازۀ دو واحد با هم اختلاف داشته و آرگومان پایاندهندۀ فانکشن ()range
یا به عبارتی عدد 0 در این مثال در خروجی چاپ نشود که با اجرای این کد در خروجی خواهیم داشت:
20
18
16
14
12
10
8
6
4
2
همانطور که میبینید، دنبالهای با گامهای متوالی منفی به سمت عدد کوچکتر داریم که در آخر عدد 0 چاپ نشده است و توجه داشته باشیم که در این الگو هر سه آرگومان ورودی باید از نوع عدد صحیح باشند و برای تعریف آرگومان ورودی stop
یا نقطۀ پایانی دنباله به صورت عدد منفی باید آرگومان سوم نیز عددی منفی تعریف شود.
بهکارگیری حلقههای for تودرتو
پیش از این گفتیم که دستورهای مرکب در زبان برنامهنویسی پایتون را میتوان به صورت تودرتو و در بدنۀ داخلی یکدیگر استفاده کرد و از همین روی، همچون تعریف دستور if
در بدنۀ یک حلقۀ تکرار، میتوانیم یک حلقۀ for
را در بدنۀ داخلی حلقۀ for
دیگر تعریف کنیم که برای درک بهتر این موضوع مثال زیر را بررسی میکنیم:
for i in range(1, 4):
for j in range(1, 4):
print(i, "*", j, " = ", i * j)
در برنامۀ فوق دو حلقۀ for
تودرتو تعریف کردهایم که در آن گفتهایم به ازای هر یک از اعداد صحیح منتسب به متغیر i
در بازه اعداد 1 تا 4 (غیر از عدد 4) حلقۀ داخلی تکرار شده و در هر مرحله هر یک از اعداد بازۀ مذکور را به متغیر j
منتسب کرده و در ادامه به مقدار منتسب به متغیر i
ضرب کند و حاصل را در خروجی چاپ کند. به عبارتی، حلقۀ داخلی به ازای هر یک از مقادیر منتسب به متغیر i
سه مرتبه تکرار شده و حاصلضرب آن در مقدار متغیر j
را در خروجی چاپ میکند.
اسکریپت برنامه را در فایلی به نام nestedLoop.py
ذخیره کرده و آن را اجرا میکنیم که در خروجی خواهیم داشت:
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
همانطور که میبیند، به ازای هر یک از اعداد منتسب به متغیر i
حلقۀ داخلی سه مرتبه تکرار شده و اعداد بازۀ 1 تا 4 یکبهیک به متغیر j
منتسب شده و در ادامه مقادیر هر یک از متغیرهای i
و j
در هم ضرب شدهاند و در گام بعد عدد دوم از دنبالۀ اعداد صحیح به متغیر i
منتسب شده و به ازای آن نیز حلقۀ داخلی سه مرتبه تکرار شده و هر یک از مقادیر بازۀ 1 تا 4 به متغیر j
منتسب شده است و در نهایت مقادیر متغیرهای i
و j
در هم ضرب شدهاند که این پروسه تا زمان اِتمام انتساب هر یک از مقادیر بازۀ اعداد صحیح به متغیر i
ادامه مییابد.
بهکارگیری دستور else در حلقۀ for
در آموزشهای گذشته به بررسی این موضوع پرداختیم که با بهکارگیری دستور else
در حلقۀ while
بدنۀ داخلی این دستور در صورتی اجرا میشود که برنامه با اجرای دستور break
از بدنۀ حلقۀ while
خارج نشود و در حلقۀ for
نیز میتوانیم از دستور else
استفاده کنیم که فرم کلی آن بدین صورت میباشد:
for target in object: # Assign object items to target
#statements Repeated loop body: use target
else: # Optional else part
#statements If we didn't hit a 'break'
در ادامه به منظور آشنایی با نحوۀ بهکارگیری دستور else
در حلقۀ for
مثالی را مد نظر قرار میدهیم که در آن قصد داریم تا ببینیم عدد ورودی توسط کاربر عددی اول است یا خیر که برای این منظور ابتدا لازم است تا نکتهای را بیان کنیم.
نکته عدد اول عددی است که به غیر از خودش و 1 مقسومعلیه دیگری ندارد بدین معنی که باقیماندۀ تقسیم یک عدد اول بر تمام اعداد کوچکتر از خودش به جز عدد 1 برابر با 0 نمیباشد.
حال به مثال فوق برمیگردیم و برای پیادهسازی آن کدی مانند زیر را مد نظر قرار میدهیم:
n = int(input("Enter a number -->"))
for i in range(2, n):
if n % i == 0:
print(n, "is not a prime number")
break
else:
print(n, "is a prime number")
در کد فوق متغیری به نام n
تعریف کرده و عدد ورودی از سمت کاربر را در آن نگهداری میکنیم. در سطر بعد با بهکارگیری حلقۀ for
و فراخوانی فانکشن ()range
در آن بازهای از اعداد صحیح دو عدد ورودی تولید کرده و گفتهایم عدد ورودی به تکتک اعداد این بازه تقسیم شود و چنانچه باقیماندۀ تقسیم برابر با صفر شود شرط برقرار بوده و استرینگ مربوط به اول نبودن عدد مذکور در خروجی چاپ شود و در ادامه دستور break
اجرا شده و برنامه به طور کامل از حلقه خارج میگردد که در چنین شرایطی بدنۀ داخلی دستور else
پس از حلقۀ for
اجرا نمیشود.
اسکریپت این برنامه را در فایلی به نام forElse.py
ذخیره کرده و آن را اجرا میکنیم که به عنوان یک مثال در خروجی داریم:
Enter a number -->25
25 is not a prime number.
با اجرای برنامه عدد 25 به متغیر n
منتسب شده و در ادامه حلقۀ for
اجرا میشود که بازهای از اعداد صحیح از 2 تا 25 (به جز عدد 25) تولید شده و عدد ورودی بر تمامی اعداد کوچکتر از خودش تقسیم میشود و در هر بار تقسیم اعداد شرط if
چک میشود و در صورتی که باقیمانده برابر با 0 باشد استرینگ مربوط به اول نبودن عدد چاپ میشود که باقیماندۀ تقسیم عدد 25 بر عددی همچون 5 برابر با 0 شده و در ادامه با اجرای دستور break
برنامه از حلقه خارج شده و دستور else
نیز اجرا نمیگردد. یک بار دیگر برنامۀ forElse.py
را اجرا کرده و عدد 23 را به عنوان ورودی به آن میدهیم که در خروجی خواهیم داشت:
Enter a number -->23
23 is a prime number
در واقع، عدد 23 بر هیچ یک از اعداد کوچکتر از خودش بخشپذیر نبوده و در هیچ یک از تکرارهای حلقۀ for
شرط if
برقرار نمیگردد و بدنۀ آن اجرا نمیشود و از همین روی برنامه با اجرای دستور break
از حلقه خارج نمیشود که بدین ترتیب دستور بدنۀ داخلی else
اجرا شده و فانکشن ()print
استرینگ مربوط به اول بودن عدد را در خروجی چاپ میکند.