در آموزشهای گذشته با نحوۀ تعریف و استفاده از دستور if در زبان برنامهنویسی پایتون آشنا شدیم و دیدیم که با برقرار بودن یک شرط خاص کدهای داخل بدنۀ دستور if یک بار اجرا شده و در غیر این صورت دستورات مذکور به هیچ وجه اجرا نمیشوند. برای مثال، فرض کنید جهت ورود به وبسایت سکان آکادمی یک پسورد ثابت در قالب استرینگ «SokanAcademy» در نظر گرفته شده است به طوری که تمامی کاربران برای ورود به سایت میباید این پسورد را به درستی وارد کنند و در غیر این صورت اجازۀ ورود به ایشان داده نمیشود که برای پیادهسازی چنین مثالی، کدی مانند زیر خواهیم داشت:
correctPassword = "SokanAcademy" password = input("Please enter the password --> ") if password == correctPassword: print("Welcome to SokanAcademy.com!")
در کد فوق استرینگ «SokanAcademy» را به عنوان پسوردی ثابت در متغیری با شناسۀ correctPassword ذخیره کردهایم سپس از کاربر خواستهایم تا کلمۀ عبور مربوطه را وارد کند که آن را به متغیری تحت عنوان password منتسب کردهایم. در ادامه و در دستور شرطی چک میکنیم که آیا استرینگ ذخیرهشده در متغیر password یا به عبارتی پسورد ورودی از سمت کاربر با کلمۀ عبور مد نظر برای وبسایت مطابقت دارد یا خیر که در صورت درست بودن این شرط استرینگ «!Welcome to SokanAcademy.com» را در معرض دید کاربر قرار میدهیم و در غیر این صورت هیچ کاری انجام نمیدهیم. اسکریپت این برنامه را در فایلی به نام ifClause.py ذخیره کرده و آن را اجرا میکنیم. حال فرض کنید کاربری پسورد خود را در قالب استرینگی بدین ترتیب وارد میکند:
Please enter the password --> sokanacademy
در واقع، کاربر مذکور هیچ توجهی به بزرگ یا کوچک بودن حروف کلمۀ عبور ندارد و این در حالی است که از یکسو مفسر پایتون نسبت به حالت حروف حساس بوده و از سوی دیگر رمز عبور مد نظر با دو حرف بزرگ به صورت استرینگ «SokanAcademy» تعریف شده است که از همین روی شرط if برقرار نبوده و دستورات بدنۀ آن هرگز اجرا نمیشوند.
در چنین شرایطی کاربر نمیتواند وارد سایت شود چرا که دستور if تنها یک بار درست بودن رمز عبور را بررسی میکند و بدین ترتیب کاربر مذکور امکان تلاش مجدد به منظور وارد کردن پسورد جدید را ندارد که از همین روی نیاز به دستوری داریم تا پروسۀ دریافت کلمۀ عبور از کاربر و بررسی مطابقت آن با پسورد درست را چندین مرتبه تکرار کند تا بدین طریق هر کاربر چند مرتبه امکان ارسال رمز عبور خود را داشته باشد.
همانطور که در آموزشهای قبل اشاره کردیم، یکی از قابلیتهای تمامی زبانهای برنامهنویسی استفاده از یکسری سینتکس استاندارد به منظور اجرای مکرر بخشی از کدهای برنامه در جهت کنترل جریان آن است که تحت عنوان Loop (حلقه) شناخته میشود که از آن جمله میتوان حلقۀ while را نام برد که فرم کلی این دستور مرکب بدین صورت میباشد:
while testConditions: # block(s) of code
مفسر پایتون با رسیدن به حلقههای تکرار از جنس while شرط تعیینشده را بررسی میکند و تا زمانی که مقدار این شرط برابر با True ارزیابی شود، قطعه کدهای داخل بدنۀ آن را به صورت مکرر اجرا میکند که چنین دستوری اصطلاحاً لوپ (حلقه) نامیده میشود چرا که دستورات داخل آن پشتسرهم اجرا میشوند و با پایان یافتن آنها مجدداً به ابتدا برگشته و شرط پایان حلقه بررسی میشود که در صورت برقرار بودن شرط مذکور حلقه ادامه پیدا میکند و در غیر این صورت جریان برنامه از حلقه مذکور خارج شده و سایر دستورات پس از آن اجرا میشوند.
نکته
حلقۀ while تنها در صورت درست بودن شرط تعیینشده تکرار میشود و از همین روی چنانچه در همان ابتدا و پیش از ورود به حلقه شرط مد نظر برقرار نشود، مفسر وارد حلقه نشده و دستورات داخل آن را نادیده میگیرد و به سراغ اجرای سایر کدهای برنامه میرود.
بر اساس آنچه در نکتۀ فوق بیان شد، ممکن است در برخی موارد حلقۀ while تعریفشده در برنامه اجرا نشود که برای درک بهتر این موضوع مثال زیر را در ادامه آوردهایم:
>>> while False: print("This code never will run.")
در کد فوق مقدار شرط while از همان ابتدا برابر با مقدار بولین False تعریف شده است که از همین روی دستور داخل بدنۀ آن هرگز اجرا نمیشود. حال به منظور آشنایی بیشتر با ساختار حلقههایی از جنس while در زبان برنامهنویسی پایتون به مثال فوق که مرتبط بود با «ورود به سایت سکان آکادمی» باز میگردیم و سعی میکنیم تا برنامۀ آن را با استفاده از دستور while بازنویسی و تکمیل کنیم:
correctPassword = "SokanAcademy" password = input("Please enter the password --> ") while password != correctPassword: password = input("Please try again and enter the correct password --> ") print("Welcome to SokanAcadmy.com")
در ابتدا، همچون مثال قبل، استرینگ «SokanAcademy» را به عنوان پسوردی ثابت در متغیری با شناسۀ correctPassword ذخیره کردهایم و از کاربر خواستهایم تا کلمۀ عبور مربوطه را وارد کند که آن را به متغیری تحت عنوان password منتسب کردهایم و در سطر بعد دستور حلقۀ while را به کار گرفتهایم و بدین ترتیب در شرط حلقه گفتهایم تا زمانی که استرینگ منتسب به متغیر password یا به عبارتی کلمۀ عبور ورودی توسط کاربر مخالف کلمۀ عبور مد نظر برای وبسایت باشد، دستورات داخل حلقه مکرراً اجرا شوند که پس از شرط حلقه و برای پایان دادن به سربند این دستور مرکب از علامت : استفاده کردهایم سپس دستورات داخل بدنۀ while را با رعایت تورفتگی نسبت به بلوک سربند آن در یک بلوک جدید مینویسیم.
در دستورات داخل بدنۀ حلقه نیز در صورتی که کاربر به هر دلیلی پسورد ورود به وبسایت را اشتباه وارد کند، استرینگی به صورت «<-- Please try again and enter the correct password» در خروجی چاپ شده و مفسر منتظر ورود کلمۀ عبور جدید از سمت کاربر میماند و این پروسه تا زمانی ادامه مییابد که کلمۀ عبور واردشده توسط کاربر با کلمۀ عبور درست مطابقت نداشته باشد و به محض اینکه کاربر رمز ورود درست را وارد کند، شرط حلقۀ while برابر با مقدار بولین False ارزیابی شده و مفسر از حلقه خارج میشود و ادامۀ دستورات برنامه را اجرا میکند که در نهایت استرینگ خوشامدگویی در معرض دید کاربر قرار میگیرد. حال اسکریپت این برنامه را در فایلی به نام whileLoop.py ذخیره کرده و آن را اجرا میکنیم که در خروجی خواهیم داشت:
Please enter the password --> sokanacademy Please try again and enter the correct password --> sokanAcademy Please try again and enter the correct password --> Sokanacademy Please try again and enter the correct password --> SokanAcademy Welcome to SokanAcadmy.com
همانطور که در نتایج خروجی میبینید، با اجرای برنامه از کاربر درخواست میشود تا کلمۀ عبور را وارد کند و تا زمانی که کلمۀ عبور درست توسط کاربر وارد نشده، دائماً برنامه اجرا میشود و منتظر دریافت ورودی از سمت کاربر میماند و به محض وارد کردن پسورد درست توسط کاربر پیغام خوشامدگویی در خروجی چاپ میشود.
نکته
در زمان کدنویسی دستور while باید دقت داشته باشیم که شرط ورود را با استفاده از دستورات داخل بدنۀ آن به گونهای کنترل کنیم که در نهایت شرط مد نظر برابر با مقدار بولین False شده و حلقۀ مذکور در جایی پایان یابد که در غیر این صورت اجرای آن تا بینهایت ادامه پیدا میکند!
آشنایی با مفهوم حلقههای بینهایت
در اصطلاح برنامهنویسی به چنین حلقههایی Infinite Loop یا حلقۀ بیپایان گفته میشود و برای توقف آن ناچار باید پنجرۀ خروجی را ببندیم که در این صورت سایر دستورات برنامه هم اجرا نمیشوند. به منظور آشنایی با نحوۀ کنترل این حلقهها، بلوک کد زیر را در نظر میگیریم:
i = 5 while i: print(i) i -= 1 #i = i-1 print("At the end i equals", i, ".")
در کد فوق مفسر پایتون اجرای برنامه را از سطر اول شروع میکند که در ابتدا متغیری با شناسۀ i تعریف شده و عدد صحیح پنج به آن منتسب شده است و در ادامه با رسیدن به کلمۀ کلیدی while شرط آن را بررسی میکند، و همانطور که در آموزشهای قبل اشاره کردیم، تمامی اعداد به جز عدد صفر با مقدار بولین True ارزیابی میشود که از همین روی شرط مذکور برقرار بوده و مفسر وارد بدنۀ آن شده و دستورات داخلی را اجرا میکند.
در اولین دستور از بدنۀ حلقۀ while فانکشن ()print با آرگومان ورودی i فراخوانی شده است بدین معنی که مقدار منتسب به متغیر i در خروجی چاپ شده و در سطر بعد یک واحد از این مقدار کم میشود و مجدداً مفسر به ابتدای حلقه بازگشته و شرط را بررسی میکند و این مراحل تا زمانی ادامه مییابد که شرط حلقۀ while برابر با مقدار بولین False ارزیابی شود که در این صورت مفسر از حلقه خارج شده و دستور سطر آخر را اجرا میکند که بدین ترتیب استرینگ «At the end i equals» به همراه آخرین مقدار منتسب به متغیر i در خروجی چاپ میشود. اسکریپت برنامۀ فوق را در فایلی به نام whileLoopInfinite.py ذخیره کرده و آن را اجرا میکنیم که در خروجی خواهیم داشت:
5 4 3 2 1 At the end i equals 0 .
همانطور که میبینید، اولین مقدار منتسب به متغیر i عدد پنج بوده و در خروجی چاپ شده است و در ادامه یک واحد از آن کم شده و مفسر پایتون به ابتدای حلقه بازگشته و مقدار جدیدِ منتسب به این متغیر را چاپ کرده است که این مراحل تا زمانی ادامه یافته است که مقدار متغیر i صفر شده و مقدار بولین شرط حلقۀ while برابر با False شده است؛ به عبارت دیگر، حلقۀ while در این مثال به گونهای کنترل شده است تا در نهایت مقدار بولین شرط آن برابر با False شده و متوقف گردیده است. حال برای آشنایی با سازوکار یک حلقۀ بینهایت، برنامۀ مثال قبل را بدین صورت تغییر میدهیم:
i = 5 while i: print(i) #i -= 1 #i = i-1 print("At the end i equals", i, ".")
در واقع، تنها تغییری که در مثال قبل اِعمال کردهایم این است که بخشی از کد که مسئول کاهش مقدار متغیر i است را کامنت کردهایم و بدین ترتیب در هر بار اجرای حلقه چیزی از مقدار اولیۀ متغیر i کم نمیشود و همواره برابر با عدد پنج باقی مانده و بالتبع شرط حلقۀ while همواره True در نظر گرفته میشود! اکنون برنامه را اجرا میکنیم که نتیجۀ حاصل از آن بدین ترتیب خواهد بود:
5 5 5 5 5 5 5 . . .
همانطور که میبینید، برنامۀ فوق هیچ نقطۀ پایانی نداشته و تا بینهایت ادامه مییابد که این مسئله در فرآیند توسعهٔ نرمافزار یک نقطهٔ ضعف محسوب میشود و ممکن است تحت شرایطی خاص پرفورمنس اپلیکیشن را کاهش دهد.