معرفی، نصب و مفاهیم اولیه

عملگر، مقدار و متغیر

ساختار شرط و حلقه‌های تکرار

توابع و متدها

مقدارهای پیمایش‌پذیر

مجموعه و دیکشنری

شرط و حلقه

فهرست

گزاره شرطی if

اگر تعریف متغیر و ذخیره کردن فایل برنامه نخستین قدم در فراتر رفتن از ماشین حساب به عنوان یک ماشین برنامه‌ثابت باشد، گزاره شرطی (if statement) اولین جایی است که می‌توانیم هوشمندی مستتر در برنامه‌های کامپیوتری را درک کنیم. 

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

اگر چیزی در محدوده دید حسگرها حرکت کرد،

          چراغ روشن شود.

در غیر این صورت،

          چراغ خاموش بماند.

در پایتون ساختارهایی برای کنترل جریان مقادیر وجود دارد که یکی از پایه‌ای‌ترین‌ آن‌ها گزاره‌ شرطی if است. با استفاده از این کلیدواژه مقدار خروجی را به مقادیر مختلف ورودی مشروط می‌کنیم.

				
					
if condition:
    # True Block of Code
else:
    # False Block of Code
    

				
			

گزاره شرطی از کلیدواژه‌های if و else، :، عبارت شرط (condition) که در نهایت به یک مقدار bool تقلیل می‌کند، و قطعه‌کدهای مربوط به True یا False بودن عبارت شرط که با فاصله از ابتدای سطر شروع می‌شوند تشکیل می‌شود. 

برنامه نمونه ۱. شاخص bmi

فرض کنید می‌خواهیم برنامه ساده‌ای بنویسیم که قد و وزن کاربر را به عنوان ورودی دریافت کند و اگر شاخص bmi او بیشتر از 25 بود، عبارت 'overweight' و در غیر این صورت عبارت 'not overweight' را چاپ کند. bmi شاخصی برای بررسی وضعیت وزن فرد در مقایسه با قد او به دست می‌دهد و از حاصل تقسیم وزن (با واحد کیلوگرم) به قد (با واحد متر) به توان دو به دست می‌آید. این برنامه را می‌توان به صورت زیر نوشت:

				
					w = int(input('please enter your weight in kg: '))
h = int(input('please enter your height in cm: '))

h = h / 100
bmi = w / h**2

print('bmi = ' + str(round(bmi, 2)))

if bmi > 25:
    print('overweight')
else: 
    print('not overweight')
				
			

اما کاربر از شما می‌خواهد که وضعیت او را دقیق‌تر گزارش کنید. شاخص bmi تنها به دو دسته دارای اضافه وزن و بدون اضافه تقسیم نمی‌شود. مثلا برای مقدار کمتر از 18.5 و مقدار بیشتر از 30 از برچسب‌های under weight و obese استفاده می‌شود. 

برای این کار لازم است تعداد شاخه‌های برنامه را به بیش از یک افزایش دهیم. آیا می‌توان با استفاده از if گزاره‌ای شرطی نوشت که تعداد قطعه کدهای آن‌ بتواند بیشتر از دو باشد و  وضعیت‌های بیشتری را پوشش دهد؟ 

اضافه کردن شرط‌های بیشتر در پایتون با استفاده از کلیدواژه elif امکان‌پذیر است. با استفاده از این کلیدواژه‌ می‌توان تعداد شاخه‌های برنامه را بیشتر کرد و با توجه به شرایط، گزاره‌ها و عبارت‌های متنوع‌تری را اجرا کرد. 

در همین نمونه اگر بخواهیم علاوه بر وضعیت overweight، وضعیت‌های underweight، normal و obese را هم در خروجی برنامه بگنجانیم کد آن به صورت زیر خواهد بود.

				
					w = int(input('please enter your weight in kg: '))
h = int(input('please enter your height in cm: '))

h = h / 100
bmi = w / h**2

print('bmi = ', round(bmi, 2))

if bmi < 18.5:
    print('underweight')
elif bmi < 25: 
    print('normal')
elif bmi < 30:
    print('overweight')
else:
    print('obese')

				
			

چنانچه در نمونه‌های بالا نیز دیدید، قطعه کدی که اجرای آن به هر یک از شرط‌ها مشروط شده تو رفتگی دارد و به اندازه چهار کاراکتر (یک تب) از ابتدای سطر (همان‌جایی که گزاره شرطی if شروع شده) فاصله دارد. 

نوشتن else و elif در گزاره شرطی اجباری نیست. اگر در یک برنامه پایتون از شاخه‌های دیگر گزاره شرطی استفاده نشود، در صورت عدم تحقق شرط برنامه بدون هیچ تغییری به اجرای خود ادامه می‌دهد. 

حلقه تکرار for

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

برای تغییر رنگ هر پیکسل‌ یک عملیات ساده تعریف می‌کنیم که در آن مقدار Red و Green در هر پیکسل به 0 تغییر پیدا می‌کنند و مقدار Blue بدون تغییر باقی می‌ماند. بعد از اجرای عملیات تغییر رنگ روی هر پیکسل، پیکسل جدید با پیکسل قدیمی جایگزین می‌شود. تعداد پیکسل‌های موجود در تصویر مشخص است. به همین دلیل می‌توانیم از کامپیوتر بخواهیم این عملیات را برای تمامی پیکسل‌های تصویر تکرار کند.

اگر بخواهیم این ایده را شبیه به یک الگوریتم بیان کنیم، چیزی شبیه به عبارت زیر می‌شود:

برای تمامی پیسکل‌های تصویر،

          عملیات تغییر رنگ اجرا شود.

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

				
					for pixel in picture:
    pixel = change(pixel) 
#
				
			

در شبه کد بالا pixel یک متغیر فرضی است برای پیمایش روی متغیر picture که مقادیر مربوط به تصویر در آن قرار دارند. حواسمان هست که در پایتون تابع پیش‌ساخته‌ای به نام change نداریم. در ادامه همین درس روش به وجود آوردن توابع جدید را فرا خواهیم گرفت. فعلا این شبه کد فرضی را نوشتیم تا ببینیم چگونه باید در پایتون از کامپیوتر بخواهیم تا کاری را چندین بار تکرار کند.

مثلا اگر بخواهیم حروف موجود در کلمه "statistics" را یکی پس از دیگری چاپ کنیم، می‌توانیم عملیات تکراری چاپ کردن حروف را با استفاده از کلیدواژه for به صورت زیر بنویسیم. 

				
					for char in "statistics":
    print(char)
#
				
			
				
					's'
't'
'a'
't'
'i'
's'
't'
'i'
'c'
's'
				
			

این کار با استفاده از کلیدواژه‌های for و in، یک متغیر پیمایش‌پذیر ("statistics")، متغیری که پیمایش را انجام می‌دهد و نقش شمارنده را بازی می‌کند (char: و قطعه کدی که باید اجرای آن چندین و چند بار تکرار شود (متغیر char در حلقه for تعریف می‌شود و نیازی به تعریف آن قبل از شروع حلقه نیست)، انجام می‌شود.

مفهوم حلقه

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

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

برنامه نمونه ۲. عدد اول

می‌خواهیم برنامه‌ای بنویسیم که یک عدد طبیعی بزرگ‌تر از 1 را به عنوان ورودی دریافت کند. اگر این عدد اول بود عبارت 'is prime' و در غیر این صورت عبارت 'is not prime' را به عنوان خروجی چاپ کند. 

برای این کار لازم یک بار دیگر به تعریف عدد اول باز گردیم: عدد اول، عددی است که غیر از خودش و یک هیچ مقسوم‌علیه دیگری ندارد. به عبارت دیگر عدد اول عددیست که تعداد مقسوم‌علیه‌های آن غیر از خودش و یک، صفر است. پس برای اینکه ببینیم یک عدد اول هست یا نیست، بهترین راه این است که تعداد مقسوم‌علیه‌های آن را بشماریم. به بیان دیگر آن عدد را بر تمامی اعداد کوچک‌تر از خودش و بزرگ‌تر یک تقسیم کنیم و در نهایت ببینیم تعداد مقسوم‌علیه‌ها چند است. اگر تعداد مقسوم علیه‌ها صفر بود، عدد اول است و در غیر این صورت عدد اول نیست. این برنامه ‌را می‌توانیم به صورت زیر بنویسیم (تابع پیش‌ساختۀ range(A,B) برای ارائه محدوده‌ای از اعداد صحیح از  A تا B-1  به کار می‌رود).

				
					x = int(input('please enter an integer greater than 1: '))

factors = 0
for a in range(2,x):
    if x % a == 0:
        factors = factors + 1
    
if factors == 0:
    print(x, 'is prime')
else:
    print(x, 'is not prime')
				
			

در کد فوق قبل از شروع حلقه تکرار متغیر factors تعریف می‌شود تا تعداد مقسوم‌علیه‌ها در آن ثبت و به روزرسانی شود. سپس در حلقه for، باقیمانده تقسیم x بر اعداد 2 تا x-1 بررسی می‌شود، اگر x بر a بخش‌پذیر بود، متغیر factors یک واحد زیاد می‌شود و مقدار آن به روزرسانی می‌شود.

منظور از به‌روزرســــــانی متـغــیــر factors این است که مقـــدار آن را 1 واحــد اضــــافه کنیم (factors + 1) و حاصل جمع را دوباره به همان نام (factors) تخصیص دهیم. این کار را به صورت factors = factors + 1 یا فرم خلاصه‌تر آن factors += 1 می‌نویسند.

در این چند سطر، عملیات تکرارشونده، تقسیم x بر اعداد کوچک‌تر از خود است که در مقادیر a خود را نشان می‌دهند و متغیر factors نیز نقش حافظه را برای شمارش تعداد مقسوم‌علیه‌ها در حلقه‌های تکرار بازی می‌کند. تنها متغیرهایی می‌توانند نقش حافظه را برای حلقه‌های تکرار ایفا کنند که مقدار آن‌ها در هر تکرار از مقدار قبلی تاثیر بپذیرند.

پرهیز از محاسبات غیرضروری

اگر مجموعه محاسباتی که برای پیدا کردن عدد اول در برنامه بالا وجود دارد را مورد بررسی قرار دهیم متوجه خواهیم شد که اگر x اول نباشد بخش زیادی از محاسباتی برای پی بردن به اول بودن یا اول نبودن انجام می‌شود، غیرضروری است. به عبارت دیگر، اولین جایی که مقسوم‌علیهی پیدا می‌شود و مقدار factors از 0 به 1 افزایش پیدا می‌کند، نتیجه نهایی برنامه مشخص می‌شود. مثلا اگر عدد ورودی 42 باشد وقتی آن را بر 2 تقسیم می‌کنیم مشخص می‌شود که این عدد اول نیست، تمامی تقسیم‌هایی که بعد از آن انجام می‌شود تاثیری در مقدار خروجی ندارد.

در حقیقت از جایی که مقدار factors غیرصفر می‌شود، باید از هرگونه محاسبه بیشتر پرهیز کرد. این کار با کلیدواژه break در حلقه‌های تکرار به صورت زیر قابل انجام است. هر زمان break در حلقه‌های تکرار مشاهده شود، اجرای حلقه متوقف می‌شود و اجرای دستورات بعد از حلقه در دستور کار قرار می‌گیرد. 

				
					x = int(input('please enter an integer greater than 1: '))

factors = 0
for a in range(2,x):
    if x % a == 0:
        factors = factors + 1
        break
    
if factors == 0:
    print(x, 'is prime')
else:
    print(x, 'is not prime')

				
			

در حلقه‌های تکرار اگر به هر دلیلی بخواهیم برای برخی از مقادیر دستورات اجرا نشوند می‌توانیم با کلیدواژه  continue از اجرای آن صرف نظر کنیم و سراغ تکرارهای بعد برویم. در نمونه زیر دستور print برای i = 3 اجرا نشده است.

				
					for i in range(5):
    if i == 3:
        continue
    print(i)

#
				
			
				
					0
1
2
4
				
			

آیا برنامه‌ای که اکنون برای تشخیص اول بودن یا اول نبودن اعداد در اختیار داریم، پردازش غیرضروری ندارد؟

برای تحلیل این برنامه بهتر است عملکرد کد را به تفکیک ورودی‌های اول و غیر اول بررسی کنیم. با توجه به تغییری که ایجاد کردیم، به نظر می‌رسد از محاسبات غیرضروری تا حد خوبی اجتناب شده است. اما در مورد اعداد اول چطور؟ مثلا اگر عدد ورودی 43 باشد آیا تقسیم آن بر 42 ضرورت دارد؟ بر 40 چطور؟ 

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

حلقه تکرار while

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

کد تشخیص اعداد اول با استفاده از حلقه تکرار while در زبان پایتون را می‌توانیم به صورت زیر بنویسیم.

				
					x = int(input('please enter an integer greater than 1: '))

factors = 0
a = 2

while factors == 0 and a**2 <= x:
    if x % a == 0:
        factors = factors + 1
    a += 1
    
if factors == 0:
    print(x, 'is prime')
else:
    print(x, 'is not prime')

				
			

در حلقه فوق، دو شرط برای اجرای مجدد قطعه کد تکرار قید شده که با توجه به استفاده از عملگرد منطقی and بین آن‌ها، هر کدام نقض شود، اجرای حلقه متوقف می‌شود؛ چه مقسوم‌علیهی پیدا شود (factors == 0) و چه اعدادی  که x را بر آن‌ها تقسیم می‌کنیم و از جذر x بزرگ‌تر شوند (a**2 <= x).

حلقه بی‌نهایت

نکته‌ای که باید هنگام استفاده از کلیدواژه while به آن توجه کرد این است که متغیری که نقشی شبیه به نقش شمارنده در حلقه‌های تکرار بازی می‌کند – مانند a در نمونه برنامه بالا – باید قبل از شروع حلقه تعریف شود و شروط اولیه از آن مستقل نباشد، در تکرارها تغییر کند و این تغییر بالاخره در یکی از حلقه‌ها منجر به نقض شروط اولیه و توقف اجرای حلقه شود. در غیر این صورت، اجرای برنامه بدون اینکه پیام خطا یا هیچ خروجی دیگری صادر شود، تا بی‌نهایت ادامه خواهد یافت و راهی جز کشتن اجرا و ری‌استارت و مانند آن‌ها برای بیرون آمد از آن وضعیت وجود نخواهد داشت.

خلاصه

در این درس با گزاره‌های شرطی و کلیدواژه if به عنوان نخستین امکانات برای ارائه یک رفتار هوشمند آشنا شدیم و سپس سراغ حلقه‌های تکرار رفتیم. فعالیت‌های تکراری هر چند برای ما خسته‌کننده هستند اما کامپیوتر می‌تواند بدون آنکه خم به ابرو بیاورد – البته تا آنجا که حافظه و قدرت پردازشش اجازه دهد – اجرای یک دستور را تکرار کند. متغیرها می‌توانند نقش حافظه را در حلقه‌های تکرار بازی کنند و از این طریق امکانات بی‌نظیری را در برابر برنامه‌نویس قرار می‌دهند. for برای حلقه‌هایی با تعداد تکرار معین و while برای حلقه‌هایی با تعداد تکرار نامعین کاربرد دارد. در حلقه‌های نامعین تکرار، توقف حلقه به نقض شروط اولیه موکول می‌شود. موقع استفاده از while مواظب سیاهچاله حلقه‌های بی‌نهایت باشید!

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors