1 - تابع input() چگونه کار می‌کند؟

بیشتر برنامه‌ها برای این نوشته می‌شوند که مشکل یک کاربر را حل کنند. برای چنین منظوری شما باید برخی اطّلاعات را از کاربر بگیرید. به عنوان یک مثالِ ساده فرض کنید کسی می‌خواهد بداند که آیا برای رای دادن به سنّ قانونی رسیده یا نه. اگر برنامه‌ای برای پاسخ دادن به این پرسش بنویسید، پیش از ارائه‌ی هر پاسخی باید از سن کاربر اطّلاع داشته باشید. این برنامه باید از کاربر بخواهد که سن خود را وارد کند، برنامه به محض دریافت این ورودی، می‌تواند آن را با سن رای‌گیری مقایسه کند تا تعیین کند که آیا سن کاربر مناسب است یا نه و سپس خروجی را گزارش کند.

در این فصل می‌آموزید که چگونه ورودی کاربر را بپذیرید تا برنامه‌ی شما بتواند با آن کار کند. زمانی که برنامه‌ی شما به یک نام احتیاج دارد، می‌تواند آن نام را از کاربر درخواست کند. اگر برنامه‌ی شما به لیستی از نام‌ها نیاز داشته باشد، می‌تواند از کاربر دنباله‌ای از نام‌ها را بخواهد. برای انجام چنین کاری از تابع input() استفاده خواهید کرد.

همچنین یاد خواهید گرفت که چگونه برنامه‌ها را تا زمانی که کاربر بخواهد در حالِ اجرا نگه دارید، تا آن‌ها بتوانند هر چه‌قدر اطّلاعات نیاز دارند وارد کنند؛ و برنامه‌ی شما بتواند با این داده‌ها کار کند. از حلقه‌ی while پایتون برای در حال اجرا نگه‌داشتنِ برنامه‌ها تا زمانِ برقراریِ شرط‌های مشخّصی، استفاده خواهید کرد.

با وجودِ دو قابلیّتِ کار کردن با ورودی کاربر و امکان کنترل مدّت‌زمان اجرای برنامه، می‌توانید برنامه‌های کاملاً تعاملی بنویسید.

تابع input() چگونه کار می‌کند؟

تابع input() برنامه‌ی شما را متوقّف می‌کند و منتظر می‌ماند تا کاربر متنی وارد کند. پایتون به محضِ دریافت ورودیِ کاربر، آن را به متغیّری منسوب می‌کند تا کار کردن با آن ساده شود.

برای نمونه برنامه‌ی زیر از کاربر می‌خواهد تا متنی را وارد کند و سپس همان را به کاربر نمایش می‌دهد:

1
2
3
message = input("Tell me something, and I will repeat it back to you: ")

print(message)

تابع input() تنها یک نشان‌وند می‌پذیرد: اعلان یا دستور‌العمل‌هایی، که می‌خواهیم به کاربر نشان دهیم تا بداند چه باید بکند. در این مثال، هنگامی که پایتون خطّ اوّل را اجرا می‌کند کاربر اعلانِ Tell me something, and I will repeat it back to you را می‌بیند. برنامه منتظر می‌ماند تا کاربر پاسخ خود را وارد کند و پس از فشرده شدن دکمه‌ی ENTER کار را ادامه می‌دهد. پاسخ به متغیّر message منسوب می‌شود و سپس print(message) ورودی را به کاربر برمی‌گرداند:

1
2
3
Tell me something, and I will repeat it back to you: Hello everyone!

Hello everyone!
نکته
Sublime Text و بسیاری دیگر از ویرایشگرها برنامه‌هایی را که از کاربر ورودی می‌خواهند، اجرا نمی‌کنند. می‌توانید از این ویرایشگرها برای نوشتن چنین برنامه‌هایی استفاده کنید امّا باید آن‌ها را در یک ترمینال اجرا کنید.

2 - نوشتن اعلان‌های شفّاف

هر بار که از تابع input() استفاده می‌کنید باید پیامی شفاّف و قابل درک را ضمیمه کنید تا به کاربر بگوید دقیقاً به دنبال چه اطّلاعاتی هستید. هر عبارتی که به کاربر بگوید که چه باید وارد کند، مناسب است. برای مثال:

1
2
3
name = input("Please enter your name: ")

print(f"\nHello, {name}!")

یک فاصله‌ی خالی بعد از اعلان‌های خود بگذارید (در این مثال بعد از دونقطه) تا اعلان را از پاسخ کاربر جدا کند و محلِّ وارد کردن متن را برای او روشن کند. برای مثال:

1
2
3
Please enter your name: Eric

Hello, Eric!

گاهی نیاز دارید اعلانی طولانی‌تر از یک خط بنویسید. مثلاً می‌خواهید به کاربر بگویید که چرا به دنبال چنین ورودی‌ای هستید. می‌توانید اعلان خود را به یک متغیّر نسبت دهید و آن متغیّر را به تابع input() بدهید. با این کار ساختن اعلان‌هایی در چند خط و سپس نوشتن یک عبارت input() مرتّب، ممکن می‌شود.

1
2
3
4
5
6
prompt = "If you tell us who you are, we can personalize the messages you see."
prompt += "\nWhat is your first name? "

name = input(prompt)

print(f"\nHello, {name}!")

این مثال یکی از روش‌های ساختن رشته‌ی چندخطّی را نشان می‌دهد. خطّ اوّل بخش اوّل پیام را به متغیّر prompt نسبت می‌دهد. در خطّ دوم عملگر += رشته‌ی متغیّر prompt را گرفته و رشته‌ی جدید را به انتهای آن اضافه می‌کند.

اعلان اکنون دو خط را در برمی‌گیرد و همچنان برای وضوح بیشتر یک فاصله‌ی خالی بعد از علامت سوال قرار داده شده است:

1
2
3
4
5
If you tell us who you are, we can personalize the messages you see.

What is your first name? Eric

Hello, Eric!

استفاده از int() برای پذیرفتن ورودی‌های عددی

هنگامی که از تابع input() استفاده می‌کنید، پایتون هر آن چه را که کاربر وارد کرده به عنوان رشته تفسیر می‌کند. این نشستِ مفسّر را در نظر بگیرید که از کاربر سنّ او را می‌پرسد:

1
2
3
4
>>> age = input("How old are you? ")
How old are you? 21
>>> age
'21'

کاربر عدد ۲۱ را وارد می‌کند امّا زمانی که از پایتون مقدار age را می‌خواهیم ‘21’ را برمی‌گرداند که بیانِ رشته‌ایِ مقدارِ عددی است که وارد شده. ما می‌دانیم که پایتون ورودی را به عنوان رشته تفسیر کرده زیرا عدد را داخل علامت نقل قول قرار داده است. اگر چاپ کردنِ ورودی همه‌ی کاری باشد که می‌خواهید انجام دهید، این کد به درستی کار می‌کند. امّا اگر بخواهید از آن به عنوان عدد استفاده کنید به خطا می‌خورید:

1
2
3
4
5
6
>>> age = input("How old are you? ")
How old are you? 21
>>> age >= 18
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() >= int()

زمانی که در 1 تلاش می‌کنید ورودی را با عددی مقایسه کنید، پایتون اعلام خطا می‌کند زیرا نمی‌تواند رشته را با یک عدد صحیح مقایسه کند: رشته‌ی ‘21’ که به age منسوب شده قابلِ مقایسه با مقدارِ عددیِ ۱۸ نیست.

این مشکل را می‌توان با به‌کارگیری تابع int() مرتفع کرد. این تابع از پایتون می‌خواهد که با ورودی مثلِ یک مقدارِ عددی رفتار کند. تابع int() نمایش رشته‌ای یک عدد را به نمایش عددیِ آن تبدیل می‌کند، همانگونه که اینجا دیده می‌شود:

1
2
3
4
5
>>> age = input("How old are you? ")
How old are you? 21
>>> age = int(age)
>>> age >= 18
True

در این مثال زمانی که در اعلانِ ورودی ۲۱ را وارد می‌کنیم، پایتون آن را رشته در نظر می‌گیرد امّا در ادامه در 1 این مقدار به کمک int()، به نمایش عددی تبدیل می‌شود. اکنون پایتون می‌تواند مقایسه‌ی عددی را اجرا کند.

چگونه از int() در یک برنامه‌ی واقعی استفاده کنیم؟ برنامه‌ای را در نظر بگیرید که تعیین می‌کند آیا قدّ افراد برای سوار شدن به یک ترن هوایی به اندازه‌ی کافی بلند است یا نه:

1
2
3
4
5
6
7
8
height = input("How tall are you, in inches? ")
height = int(height)

if height >= 48:
    print("\nYou're tall enough to ride!")

else:
    print("\nYou'll be able to ride when you're a little older.")

این برنامه می‌تواند height را با ۴۸ مقایسه کند زیرا height = int(height) مقدار ورودی را پیش از انجامِ مقایسه به یک نمایش عددی تبدیل می‌کند. اگر عددِ واردشده بزرگتر از یا مساوی با ۴۸ باشد به کاربر می‌گوییم که قد او مناسب است:

1
2
3
How tall are you, in inches? 71

You're tall enough to ride!

اگر از ورودی‌های عددی برای انجام محاسبات یا مقایسه‌ها استفاده می‌کنید مطمئن شوید که ابتدا مقدار ورودی را به نمایش عددی تبدیل کرده‌اید.

3 - عملگر پیمانه

یک ابزار سودمند برای کار کردن با داده‌های عددی عملگر پیمانه (%) است که عددی را بر یک عدد دیگر تقسیم کرده و باقیمانده‌ی آن را برمی‌گرداند:

1
2
3
4
5
6
7
8
>>> 4 % 3
1
>>> 5 % 3
2
>>> 6 % 3
0
>>> 7 % 3
1

عملگر پیمانه حاصلِ تقسیم را، یعنی تعداد باری که یک عدد در عدد دیگر جا می‌گیرد، برنمی‌گرداند بلکه تنها می‌گوید که باقیمانده‌ی تقسیم چیست.

زمانی که عددی بر عدد دیگری بخش‌پذیر باشد، باقیمانده ۰ است بنابراین عملگر پیمانه عدد صفر را برمی‌گرداند. می‌توانید از این حقیقت برای تعیین زوج یا فرد بودنِ عددی استفاده کنید:

1
2
3
4
5
6
7
8
number = input("Enter a number, and I'll tell you if it's even or odd: ")
number = int(number)

if number % 2 == 0:
    print(f"\nThe number {number} is even.")

else:
    print(f"\nThe number {number} is odd.")

اعدادِ زوج همواره برای ۲ بخش‌پذیرند پس اگر باقیمانده‌ی تقسیم یک عدد بر ۲، ۰ باشد (در اینجا if number % 2 == 0) آن عدد زوج است. در غیر این صورت فرد خواهد بود:

1
2
3
Enter a number, and I'll tell you if it's even or odd: 42

The number 42 is even.

خودآزمایی

برنامه‌ی ماشین کرایه‌ای

برنامه‌ای بنویسید که از کاربر بپرسد چه‌جور ماشین کرایه‌ای دوست دارد. پیامی درباره‌ی آن ماشین چاپ کنید، مثلاً: “Let me see if I can find you a Subaru.”.

جاگرفتن در رستوران

برنامه‌ای بنویسید که از کاربر بپرسد چند نفر در گروه شام او حضور دارد. اگر پاسخ بیش از هشت بود، پیامی چاپ کند که باید منتظر خالی شدن یک میز بمانند. در غیر این صورت بگوید که میز آن‌ها حاضر است.

مضرب‌های ده

از کاربر عددی بپرسید و سپس گزارش دهید که آیا آن عدد مضربی از ۱۰ است یا نه؟

4 - آشنایی با حلقه‌های while

حلقه‌ی for مجموعه‌ای را می‌گیرد و قطعه‌کدی را یک بار برای هر عضو آن اجرا می‌کند. در مقابل، حلقه‌ی while تا زمانی که شرط خاصی درست باشد، اجرا می‌شود.

حلقه‌ی while در عمل

می‌توانید از یک حلقه‌ی while برای شمردن دنباله‌ای از اعداد استفاده کنید. برای مثال حلقه‌ی while زیر از ۱ تا ۵ می‌شمرد:

1
2
3
4
5
current_number = 1

while current_number <= 5:
    print(current_number)
    current_number += 1

در خطّ اوّل شمردن از ۱ را با انتساب مقدار ۱ به متغیّر current_number شروع می‌کنیم. سپس حلقه‌ی while طوری تنظیم می‌شود که تا زمانِ کمتر یا مساوی بودنِ current_number از ۵، اجرا شود. کدِ داخلِ حلقه مقدارِ current_number را چاپ کرده و سپس با += آن را یکی زیاد می‌کند. (عملگر += کوتاه‌شده‌ی current_number = current_number + 1 است.)

پایتون تا زمانی حلقه را اجرا می‌کند که شرطِ current_number <= 5 برقرار باشد. پایتون ۱ را چاپ می‌کند سپس یکی به آن اضافه می‌کند تا عدد فعلی ۲ شود. چون ۲ کمتر از ۵ است، آن را چاپ کرده و مجدّداً یکی به آن اضافه می‌کند تا عدد فعلی ۳ شود و به همین ترتیب ادامه می‌دهد. به محض بیشتر شدنِ مقدارِ current_number از ۵، اجرای حلقه متوقّف شده و برنامه پایان می‌یابد:

1
2
3
4
5
1
2
3
4
5

بیشتر برنامه‌هایی که هرروزه استفاده می‌کنید شامل حلقه‌های while‌اند. برای مثال، یک بازی به حلقه‌ی while احتیاج دارد که تا زمانی که می‌خواهید به بازی ادامه دهید، به اجراشدن ادامه دهد و به محض رسیدنِ درخواستِ خروج اجرا شدن را متوقّف کند.

اجازه دادن به کاربر برای انتخاب زمان خروج

برای این که برنامه‌ی parrot.py تا زمانی که کاربر می‌خواهد، اجرا شود می‌توانیم بیشتر خط‌های آن را در یک حلقه‌ی while قرار دهیم. یک مقدارِ خروج تعریف می‌کنیم و تا زمانی که کاربر آن را وارد نکرده باشد، اجرای برنامه ادامه می‌یابد:

1
2
3
4
5
6
7
8
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "

message = ""

while message != 'quit':
    message = input(prompt)
    print(message)

در 1 اعلانی تعریف می‌کنیم تا به کاربران بگوییم که دو گزینه پیشِ رو دارند: وارد کردن یک پیام یا وارد کردن مقدارِ خروج (در اینجا، ‘quit’). سپس در 2 متغیّر message را مقداردهی می‌کنیم تا هر مقداری را که کاربر وارد می‌کند، پیگیری کنیم. متغیّر message را یک رشته‌ی خالی "" قرار می‌دهیم تا پایتون در اوّلین اجرای حلقه چیزی برای مقایسه کردن داشته باشد. حلقه‌ی while (3) تا زمانی که مقدار message برابر با ‘quit’ نباشد اجرا می‌شود.

در اوّلین ورود به حلقه، message تنها یک رشته‌ی خالی است، پس پایتون می‌تواند وارد حلقه شود. در message = input(prompt) پایتون اعلان را نمایش می‌دهد و منتظر پاسخ کاربران می‌ماند. هر آن‌چه وارد کنند به message نسبت داده شده و چاپ می‌شود؛ سپس پایتون شرطِ عبارتِ while را دوباره ارزیابی می‌کند. سرانجام زمانی که کاربران ‘quit’ را وارد می‌کنند، پایتون اجرای حلقه‌ی while را متوقّف کرده و برنامه پایان می‌یابد:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. Hello everyone!

Hello everyone!

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. Hello again.

Hello again.

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. quit

quit

این برنامه به خوبی کار می‌کند، تنها ایراد آن این است که واژه‌ی ‘quit’ را مثل یک پیام واقعی چاپ می‌کند. یک آزمون if ساده این مشکل را حل می‌کند:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "

message = ""

while message != 'quit':
    message = input(prompt)

    if message != 'quit':
        print(message)

اکنون برنامه پیش از نمایش پیام یک بررسی سریع انجام می‌دهد و تنها در صورتی آن را چاپ می‌کند که با مقدارِ خروج برابر نباشد:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. Hello everyone!

Hello everything!

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. Hello again.

Hello again.

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. quit

5 - به‌کارگیری پرچم

در مثالِ پیشین برنامه را واداشتیم که تا زمانِ برقرار بودنِ شرطی مشخّص، به انجام وظایفی بپردازد. امّا در برنامه‌های پیچیده که در‌آنها رخدادهای مختلفی ممکن است باعث توقّف اجرا شوند، چه باید کرد؟

برای مثال در یک بازی رخدادهای مختلف و فراوانی می‌توانند به بازی خاتمه دهند. وقتی تمام کشتی‌های کاربر غرق می‌شود، زمان او به پایان می‌رسد یا شهرهایی که باید از آن‌ها محافظت می‌کرده همگی نابوده شده‌اند، بازی باید پایان یابد. بازی باید با رخ دادن هر کدام از این رویدادها به پایان برسد. اگر امکان وقوع رخدادهای مختلفی برای پایان دادن به برنامه وجود دارد، آزمودن همه‌ی ‌آن‌ها در یک عبارت while ممکن است پیچیده و مشکل باشد.

در برنامه‌ای که فقط باید تا زمان برقراری شرط‌هایی اجرا شود، می‌توانید یک متغیّر تعریف کنید که تعیین کند کل برنامه فعّال است یا نه. این متغیّر که به آن پرچم گویند، در برنامه مانند یک نشانه عمل می‌کند. می‌توانیم برنامه را به نحوی بنویسیم که تا زمان درست (True) بودن پرچم اجرا شود و هنگامی که یکی از چندین رخداد مقدار آن را نادرست (False) کند، اجرای برنامه متوقّف شود.

بیایید پرچمی به parrot.py از بخش قبل، اضافه کنیم. این پرچم که آن را active می‌نامیم (و هر نامی که بخواهید می‌توانید به آن بدهید) نگاه می‌کند که آیا اجرای برنامه باید ادامه یابد یا نه:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "

active = True

while active:
    message = input(prompt)

    if message == 'quit':
        active = False

    else:
        print(message)

در 1 متغیّر active را برابر True می‌گذاریم تا برنامه در وضعیّت فعّال قرار گیرد. انجام چنین کاری عبارت while را ساده‌تر می‌کند زیرا هیچ مقایسه‌ای در خود عبارت صورت نمی‌پذیرد؛ منطق برنامه در دیگر بخش‌های آن مورد نظر قرار می‌گیرد. تا زمانی که متغیّر active مقدار True دارد اجرای حلقه ادامه می‌یابد (2).

به محض این که کاربران ورودی خود را اعمال کنند مقدار message را در گزاره‌ی if داخل حلقه‌ی while بررسی می‌کنیم. اگر در 3 کاربر ‘quit’ را وارد کرد، active را False می‌کنیم و حلقه‌ی while متوقّف می‌شود. اگر کاربر چیزی جز ‘quit’ وارد کند، 4، ورودی او را در قالب پیامی چاپ می‌کنیم.

خروجی این برنامه مشابه خروجی مثال قبلی است. حال که ما پرچمی داریم که نشان می‌دهد کل برنامه در وضعیّت فعّال است یا نه، افزودن آزمون‌های بیشتر (مثلاً با عبارت‌های elif) برای رخ‌دادهایی که باید active را False کنند، ساده خواهد بود.

6 - استفاده از break و continue

استفاده از break برای خروج از حلقه

برای این که بدون اجرای کدهای باقیمانده در حلقه‌ی while و صرفِ نظر از نتایج هر آزمون شرطی‌ای، فوراً از آن خارج شوید از break استفاده کنید. عبارت break جریان برنامه‌ی شما را هدایت می‌کند؛ می‌توانید از آن برای مدیریّت اجرا شدن یا نشدن خط‌هایی از کد استفاده کنید.

برای نمونه برنامه‌ای را در نظر بگیرید که از کاربران می‌پرسد از چه مکان‌هایی دیدن کرده‌اند. در این برنامه به محضی که کاربر مقدار ‘quit’ را وارد می‌کند، حلقه‌ی while را با فراخوانی break متوقّف می‌کنیم:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
prompt = "\nPlease enter the name of a city you have visited:"
prompt += "\n(Enter 'quit' when you are finished.) "

while True:
    city = input(prompt)

    if city == 'quit':
        break

    else:
        print(f"I'd love to go to {city.title()}!")

حلقه‌ای که مانند 1 با while True آغاز شود تا ابد اجرا می‌شود مگر این که به عبارت break برسد. پرسیدنِ نام شهرهایی که کاربران در آن‌ها بوده‌اند تا زمانی که ‘quit’ را وارد کنند در حلقه‌ی این برنامه ادامه می‌یابد. هنگامی که کاربران ‘quit’ را وارد می‌کنند عبارت break اجرا می‌شود که باعث می‌شود پایتون از حلقه خارج شود:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Please enter the name of a city you have visited:
(Enter 'quit' when you are finished.) New York

I'd love to go to New York!

Please enter the name of a city you have visited:
(Enter 'quit' when you are finished.) San Francisco

I'd love to go to San Francisco!

Please enter the name of a city you have visited:
(Enter 'quit' when you are finished.) quit
نکته
می‌توانید از break در تمام حلقه‌های پایتون استفاده کنید. برای مثال با به‌کارگیری break می‌توانید از حلقه‌ی for‌ای که داخل یک لیست یا دیکشنری در حال کار کردن است، خارج شوید.

به‌کارگیری continue در یک حلقه

به جای این که بدونِ اجرای باقیمانده‌ی کد، از حلقه‌ای به کلّی خارج شوید، می‌توانید از عبارت continue استفاده کنید تا بر اساس نتیجه‌ی یک آزمون شرطی به ابتدای حلقه برگردید. برای نمونه حلقه‌ای را در نظر بگیرید که از ۱ تا ۱۰ می‌شمرد امّا تنها اعداد فردِ این بازه را چاپ می‌کند:

1
2
3
4
5
6
7
8
9
current_number = 0

while current_number < 10:
    current_number += 1

    if current_number % 2 == 0:
        continue

    print(current_number)

ابتدا مقدار current_number را برابر با ۰ می‌گذاریم. چون این مقدار کمتر از ۱۰ است پایتون وارد حلقه می‌شود. با ورود به حلقه در 1 مقدار را یکی افزایش می‌دهیم، پس current_number برابر با ۱ خواهد بود. سپس گزاره‌ی if باقیمانده‌ی current_number بر ۲ را بررسی می‌کند. اگر باقیمانده ۰ باشد (یعنی current_number بر ۲ بخش‌پذیر باشد)، عبارت continue از پایتون می‌خواهد که باقیِ حلقه‌ی را نادیده بگیرد و به ابتدای آن برگردد. اگر عدد فعلی برای ۲ بخش‌پذیر نباشد ادامه‌ی حلقه اجرا شده و پایتون آن را چاپ می‌کند:

1
2
3
4
5
1
3
5
7
9

7 - پرهیز از حلقه‌های بی‌پایان

هر حلقه‌ی while به روشی برای توقّف اجرا نیاز دارد تا اجرای آن برای همیشه ادامه نیابد. برای مثال این حلقه‌ی شمارنده باید از ۱ تا ۵ بشمارد:

1
2
3
4
5
x = 1

while x <= 5:
    print(x)
    x += 1

امّا اگر همان‌طور که در ادامه می‌آید، سهواً خط x += 1 را حذف کنید حلقه تا ابد اجرا می‌شود:

1
2
3
4
5
# This loop runs forever!
x = 1

while x <= 5:
    print(x)

اکنون مقدار x از ۱ شروع می‌شود امّا هرگز تغییر نمی‌کند. در نتیجه آزمون شرطی x <= 5 همواره True ارزیابی می‌شود و حلقه‌ی while برای همیشه اجرا شده و دنباله‌ای از ۱ها چاپ می‌کند:

1
2
3
4
5
1
1
1
1
--snip--

هر برنامه‌نویسی گاه به گاه و به صورت اتّفاقی حلقه‌ی while بی‌پایان می‌نویسد، به ویژه زمانی که حلقه‌های برنامه شرط‌های خروج ظریف و دیرفهمی دارند. اگر برنامه‌ی شما در یک حلقه‌ی بی‌پایان گیر کرد CTRL-C را فشار دهید یا به سادگی پنجره‌ی ترمینالی را که خروجی‌ برنامه را نشان می‌دهد ببندید.

برای پرهیز از نوشتن حلقه‌های بی‌پایان، هر حلقه‌ی while را بیازمایید و مطمئن شوید اجرای آن در زمانی که شما انتظار دارید متوقّف می‌شود. اگر از برنامه می‌خواهید که با دریافت یک ورودی مشخّص پایان یابد، آن را اجرا کنید و آن مقدار را وارد کنید. اگر برنامه پایان نیافت، روش برنامه را پایان دادنِ به حلقه، موشکافانه مورد بررسی قرار دهید.

نکته
Sublime Text و برخی دیگر از ویرایشگرها یک پنجره‌ی خروجی درونی دارند که ممکن است متوقّف کردن یک حلقه‌ی بی‌پایان را مشکل کند و شما را مجبور کند که خود ویرایشگر را برای پایان دادن به حلقه ببندید. سعی کنید پیش از فشردن CTRL+C روی ناحیه‌ی پنجره‌ی خروجی کلیک کنید تا قادر باشید حلقه‌ی بی‌پایان را متوقّف کنید.

خودآزمایی

مواد روی پیتزا

حلقه‌ای بنویسید که از کاربران بخواهد پیش از وارد کردن مقدار ‘quit’، مجموعه‌ای از مواد روی پیتزا را وارد کنند. همزمان که موارد را وارد می‌کنند، پیامی چاپ کنید که می‌گوید شما آن مورد را به پیتزا اضافه خواهید کرد.

بلیت‌های سینما

یک سالن سینما قیمت بلیت‌ها را بر اساس سنّ فرد تعیین می‌کند. اگر فرد کمتر از ۳ سال سن داشته باشد، بلیت او رایگان است؛ اگر بین ۳ تا ۱۲ سال داشته باشند باید ۱۰ دلار بپردازند و اگر بیش از ۱۲ سال سن داشته باشند بلیت آن‌ها ۱۵ دلار خواهد بود. حلقه‌ای بنویسید که در آن سن کاربران پرسیده شده و سپس قیمت بلیت آن‌ها اعلام می‌شود.

سه خروجی

نسخه‌های متفاوتی از تمرین ۷-۴ یا ۷-۵ بنویسید که کارهای زیر را حدّاقل یک بار انجام دهد:

  • در عبارت while یک آزمون شرطی بیاورید که اجرای حلقه را متوقّف کند.
  • از یک متغیّر فعّال بودن استفاده کنید تا مدّت زمان اجرای حلقه را کنترل کنید.
  • هنگامی که کاربر مقدار ‘quit’ را وارد می‌کند، از یک عبارت break برای خروج از حلقه استفاده کنید.

بی‌پایانی

حلقه‌ای بنویسید که هیچ‌گاه پایان نمی‌یابد و آن را اجرا کنید. (برای پایان دادن به این حلقه CTRL+C را فشار دهید یا پنجره‌ای که خروجی را نشان می‌دهد ببندید.)

8 - به‌کارگیری حلقه‌ی while در لیست‌ها و دیکشنری‌ها

تا اینجا هر بار تنها با یک مورد از اطّلاعات کاربر سر و کار داشته‌ایم. ورودی را از کاربر گرفته و همان را یا پاسخی به آن را چاپ کرده‌ایم. پس از آن در یک حلقه‌ی while مقدار ورودیِ دیگری را گرفتیم و به آن پاسخ دادیم. امّا برای نگه‌داری و پیگیری کاربران بیشتر یا اطّلاعات پرتعدادتر در حلقه‌های while، به لیست‌ها و دیکشنری‌ها احتیاج داریم.

به‌کارگیری یک حلقه‌ی for برای حلقه زدن در یک لیست موثّر است امّا نباید لیست را در داخل این حلقه تغییر داد چون پایتون در پیگیری موارد داخل لیست دچار مشکل می‌شود. اگر می‌خواهید هنگام کار کردن با یک لیست آن را تغییر دهید، از حلقه‌ی while استفاده کنید.

انتقال دادن اعضا از یک لیست به لیستِ دیگر

لیستی از کاربران تازه ثبت‌نام شده‌ی یک وب‌سایت را در نظر بگیرید که هنوز تایید نشده‌اند. چگونه می‌توانیم پس از تایید این کاربران، آن‌ها را به لیستی مجزّا شامل کاربران تاییدشده منتقل کنیم؟ یک روش استفاده کردن از حلقه‌ی while است تا به کمک آن کاربران را از لیست کاربران تاییدنشده بیرون بکشیم، تایید کنیم و سپس به لیستی جداگانه از کاربران تاییدشده اضافه کنیم:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Start with users that need to be verified,
# and an empty list to hold confirmed users.
unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []

# Verify each user until there are no more unconfirmed users.
# Move each verified user into the list of confirmed users.
while unconfirmed_users:
    current_user = unconfirmed_users.pop()

    print(f"Verifying user: {current_user.title()}")
    confirmed_users.append(current_user)

# Display all confirmed users.
print("\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:
    print(confirmed_user.title())

در 1 با لیستِ کاربرانِ تاییدنشده (Alice، Brian و Candace) و لیستی خالی برای نگهداری کاربران تاییدشده شروع می‌کنیم. حلقه‌ی while در 2 تا زمانی که لیست unconfirmed_users خالی نباشد به کار ادامه می‌دهد. داخل این حلقه و در 3، تابع pop() هر بار کاربران تاییدنشده را از انتهای unconfirmed_users برمی‌دارد. اینجا چون Candace آخرین کاربر در unconfirmed_users است، نامش اوّلین نامی خواهد بود که از لیست حذف، به متغیّر current_user منسوب و به لیست confirmed_users اضافه می‌شود (4). بعدی Brian و سپس Alice خواهد بود.

فرآیند تایید کاربران را با چاپ کردن یک پیام تایید شبیه‌سازی می‌کنیم و سپس کاربران را به لیست تاییدشده‌ها می‌افزاییم. همزمان با کوچک شدن لیست کاربران تاییدنشده، لیست تایید‌شده‌ها بزرگ‌تر می‌شود:

1
2
3
4
5
6
7
8
Verifying user: Candace
Verifying user: Brian
Verifying user: Alice

The following users have been confirmed:
Candace
Brian
Alice

حذف کردن مقدارهای مشخّصی از یک لیست

در فصل ۳ از remove() برای حذف کردن یک مقدار مشخّص از لیست استفاده کردیم. این تابع به این دلیل کار می‌کرد که مقدار مورد نظر ما تنها یک بار در لیست ظاهر شده بود. امّا اگر بخواهیم تمام نمونه‌های یک مقدار را از لیستی حذف کنیم، چه؟

فرض کنید لیستی از حیوانات خانگی دارید که ‘cat’ در آن بارها تکرار شده است. برای حذف تمام مشابه‌های این مقدار می‌توانید یک حلقه‌ی while را تا زمانی اجرا کنید که هیچ موردی از ‘cat’ در لیست باقی نمانده باشد:

1
2
3
4
5
6
7
8
pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']

print(pets)

while 'cat' in pets:
    pets.remove('cat')

print(pets)

با لیستی شامل چند عضو مشابه ‘cat’ شروع می‌کنیم. پس از چاپ کردن این لیست، پایتون وارد حلقه‌ی while می‌شود زیرا مقدار ‘cat’ را دستِ کم یک بار در لیست می‌یابد. پس از ورود به حلقه، پایتون اوّلین نمونه‌ی ‘cat’ را حذف کرده و به خطّ while برمی‌گردد. سپس از آن‌جا که هنوز ‘cat’ در لیست وجود دارد، مجدّداً وارد حلقه می‌شود. تا زمانی که دیگر هیچ مقداری مشابه ‘cat’ در حلقه موجود نباشد، هر نمونه‌ی آن را حذف می‌کند:

1
2
3
['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']

['dog', 'dog', 'goldfish', 'rabbit']

پر کردن یک دیکشنری با ورودی کاربر

در هر مرحله‌ی اجرای حلقه‌ی while، می‌توانید هرقدر اطّلاعات که بخواهید دریافت کنید. بیایید یک برنامه‌ی نظرسنجی بسازیم که در آن در هر بار اجرای حلقه یک بار نام و نظر مشارکت‌کنندگان را می‌پرسیم. داده‌های گردآوری‌شده را در یک دیکشنری ذخیره می‌کنیم زیرا می‌خواهیم بین هر کاربر و پاسخ او ارتباط برقرار کنیم:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
responses = {}

# Set a flag to indicate that polling is active.
polling_active = True

while polling_active:
    # Prompt for the person's name and response.
    name = input("\nWhat is your name? ")
    response = input("Which mountain would you like to climb someday? ")

    # Store the response in the dictionary.
    responses[name] = response

    # Find out if anyone else is going to take the poll.
    repeat = input("Would you like to let another person respond? (yes/ no) ")

    if repeat == 'no':
        polling_active = False

# Polling is complete. Show the results.
print("\n--- Poll Results ---")
for name, response in responses.items():
    print(f"{name} would like to climb {response}.")

این برنامه ابتدا یک دیکشنری خالی (responses) تعریف می‌کند و پرچمی (polling_active) را برای نمایش فعّال بودن نظرسنجی مقداردهی می‌کند. تا زمانی که polling_active برابر با True باشد، پایتون کد داخل حلقه‌ی while را اجرا می‌کند.

در داخل حلقه به کاربر اعلام می‌شود که نام و کوه مورد علاقه‌ی خود برای نوردیدن را وارد کند. این اطّلاعات در دیکشنری responses ذخیره می‌شود و از کاربر پرسیده می‌شود که آیا نظرسنجی ادامه یابد یا نه. اگر yes وارد شود، برنامه بار دیگر وارد حلقه‌ی while می‌شود. اگر no وارد شود پرچم polling_active به False تغییر می‌یابد و اجرای حلقه‌ی while متوقّف می‌شود. سرانجام بخش آخر کد نتایج نظرسنجی را نشان می‌دهد.

اگر برنامه را اجرا کرده و چند پاسخ نمونه وارد کنید، باید خروجی‌ای مانند زیر ببینید:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
What is your name? Eric
Which mountain would you like to climb someday? Denali
Would you like to let another person respond? (yes/ no) yes

What is your name? Lynn
Which mountain would you like to climb someday? Devil's Thumb
Would you like to let another person respond? (yes/ no) no

--- Poll Results ---
Lynn would like to climb Devil's Thumb.
Eric would like to climb Denali.

خودآزمایی

غذافروشی

لیستی به نام sandwich_orders بسازید و آن را با نام چند نوع ساندویچ پر کنید. سپس لیستی خالی به نام finished_sandwiches بسازید. در لیست سفارش‌های ساندویچ حلقه بزنید و برای هر کدام پیامی چاپ کنید، مثلاً I made your tuna sandwich.. با درست شدن هر ساندویچ، سفارش آن را به لیست‌های ساندویچ‌های تحویل‌داده‌شده منتقل کنید. پس از آماده شدن تمام ساندویچ‌ها پیامی چاپ کنید و تمام ساندویچ‌های آماده‌شده را فهرست کنید.

تمام شدنِ پاسترامی

لیستِ sandwich_orders در تمرین ۷-۸ را دوباره به کار بگیرید و مطمئن شوید ساندویچ ‘pastrami’ دستِ کم ۳ بار در آن تکرار شده باشد. در ابتدای برنامه‌ی خود پیامی چاپ کنید حاکی از آن‌که موجودیِ پاسترامی در این غذاخوری به پایان رسیده است، سپس به کمک یک حلقه‌ی while تمام موارد ‘pastrami’ را از sandwich_orders حذف کنید. مطمئن شوید که در لیست ساندویچ‌های آماده هیچ نمونه‌ای از ساندویچ پاسترامی نباشد.

سفر رویایی

برنامه‌ای بنویسید که از کاربران درباره‌ی سفر رویایی آن‌ها نظرسنجی کند. اعلانی مانند این چاپ کنید: If you could visit one place in the world, where would you go?. بخشی از کد را به چاپ کردن نتایج نظرسنجی اختصاص دهید.

9 - خلاصه

در این فصل آموختید که چگونه input() را به کار بگیرید تا امکان وارد کردن اطّلاعات را برای کاربران فراهم کنید. یاد گرفتید که چگونه با هر دو نوع ورودی رشته و عددی کار کنید و با حلقه‌های while اجرای برنامه‌های خود را تا زمانی که کاربر بخواهد ادامه دهید. چندین روش را برای کنترل کردن جریان یک حلقه‌ی while آموختید، مانند تعریف یک پرچم active، استفاده از عبارت‌های break و continue. یاد گرفتید که چگونه برای انتقال اعضای یک لیست به لیستی دیگر و همچنین حذفِ تمامِ موارد مشابه با یک مقدار از یک لیست، از حلقه‌ی while استفاده کنید. همچنین دانستید که می‌توان حلقه‌های while را با دیکشنری‌ها هم استفاده کرد.

در فصل ۸ در مورد تابع‌ها خواهید آموخت. توابع به شما امکان می‌دهند که برنامه‌ها را به قسمت‌های کوچک‌تر بشکنید که هر قسمت کار خاصی انجام دهد. می‌توانید یک تابع را هر چند بار که خواستید فراخوانی و آن‌ها را در فایل‌های جداگانه ذخیره کنید. با به‌کارگیری تابع‌ها می‌توانید کد کاراتری بنویسید که عیب‌یابی آن ساده‌تر است و می‌توان آن‌ها را در برنامه‌های مختلف دوباره استفاده کرد.