حلقه

حلقه while ساده ترین و پرکاربرد ترین روش موجود در زبان پایتون برای تکرار قطعه کدی خاص می باشد . این قطعه کد خاص تا زمانی که شرط مورد نظر و از پیش تعیین شده ای درست باشد اجرا می گردد . زمانی که شرط مورد بررسی نادرست شد اجرای برنامه از حلقه خارج شده و به اولین دستور بعد از حلقه یعنی اولی خطی که دقیقا زیر عبارت while باشد منتقل می گردد . اگر هنگام اولین اجرا شرط مورد بررسی نادرست باشد کد های داخل قطعه تکرار هیچ وقت اجرا نخواهد شد .

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

ساختار کلی حلقه while

در پیچیده ترن حالت ممکنه این حلقه شامل یک شروع کننده با عبارت while به همراه یک شرط اجرا می باشد که با دو نقطه به پایان می رسد . سپس در ادامه بدنه اصلی حلقه ظاهر می گردد که همگی دارای تورفتگی یکسان و برابر نسبت به خط آغازین می باشند . این قطعه کد و بدنه اصلی تا زمانی که شرط مقابل عبارت while درست باشد اجرا می گردد . بخش بعدی این دستور یعنی بخش else آن اختیاری می باشد . یعنی می توانید از این بخش بنابه نیاز برنامه استفاده نکنید . این بخش از کد در صورتی که حلقه بطور کامل اجرا خاتمه یابد اجرا می گردد . در ادامه درس با دستور break آشنا خواهید شد که کار آن خاتمه دادن حلقه بدون بررسی شرط اجرای آن می باشد که در این صورت دستروات داخل بخش else اجرا نشده و برنامه از دستور بعدی حلقه به اجرای خود ادامه می دهد . شاید بهتر بود بجای عبارت else در این دستور از done یا on_completion استفاده می شد . اگر قبلا با زبانهای دیگری برنامه نوشته باشید حتما با حالتی مواجه شدید که پس از اتمام اجرای حلقه و در صورت کامل اجرا شدن آن کار خاصی را انجام دهید . که در این حالت معمولا شمارنده حلقه با مقدار پایانی مقایسه می شد . اما با فراهم دستور else برای حلقه این کار بصورت بسیار راحتتر و منطقی تری قابل اجرا می باشد .

while <test>:     # شرط حلقه
    <statements1> # بدنه اصلی حلقه
else:             # بخش انتخابی
    <statements2> # اجرا زمانی که حلقه با روند عادی خاتمه یابد 

مثال های while

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

>>> while 1:
...     print 'Press Ctrl+C to stop me!'
...
Press Ctrl+C to stop me!
Press Ctrl+C to stop me!
Press Ctrl+C to stop me!
.....

بمثال بعدی برنامه ای است که از مقدار متغییر a تا متغییر b را می شمارد . منطق استفاده شده بسیار شبیه زبان C می باشد و معمولا از چنین روش هایی در زبان پایتون استفاده نمی شود . بلکه با دستورات معادل و بسیار راحتتر و قابل فهم تر می توان براحتی این برنامه را پیاده سازی کرد .

>>> a=0; b=10
>>> while a < b:
…     print a,
…     a = a+1
…
0 1 2 3 4 5 6 7 8 9

دراین مثال با استفاده از کاراکتر ";" دو دستور در سطر اول نوشته شده است . این کاراکتر در زبان C برای نمایش پایان دستور استفاده می گردد . در پایتون نیز می توان از این کاراکتر و با همان هدف استفاده کرد . نکته بعدی موجود استفاده از یک ویرگول در انتهای دستور چاپ می باشد . در حالت عادی دستور چاپ بعد از هر بار اجرا به سطر پایین می رود ولی با استفاده از ویرگول عملایت چاپ از خط فعلی ادامه می یابد .

دستورات break, continue, pass و else حلقه

پس از آشنایی با حلقه ها در پایتون اکنون با دو عبارت نسبتا پر کاربرد آشنا می شویم که در داخل حلقه ها کاربرد فراوانی دارد . دو عبارت مهم ذکر شده عبارتند از continue و break . اگر شما آشنای با این موارد در زبانی چون C دارید اکر مطالب این بخش برای شما آشنا خواد بود . عبارت break مکمل یا نقطه مخالف دستور یا قطعه else در حلقه ها می باشد . یعنی در صورت وجود بخش else یک حلقه و زمانی که از طریق دستور break روند عادی اجرای یک حلقه را قبل از اتمام عادی آن پایان می دهیم قطعه کد درون else اجرا می گردد . عبارت بعدی دستور pass می باشد که در حقیقت با اجرای این دستور هیچ اتفاق خاصی رخ نخواهد داد . از این دستور زمانی استفاده می کنیم که در شرایطی خاص نیاز به انجام هیچ کاری نباشد ! مثلا برای تغریف یک تابع خالی تا بعدا کد های آن نوشته شود . یا زمانی که بخواهیم هنگام بروز یک خطای خاص آن مشکل نادیده گرفته شده و برنامه به روند عادی خود ادامه دهد .

break
خروج آنی و بدون تست شرط از داخلی ترین حلقه در حال اجرا
continue
پرش به اول قطعه کد حلقه و تست شرط اجرای داخلی ترین حلقه . اگر شرط درست باشد کد های درون قطعه دوباره اجرا می گردد . در غیر اینصورت حلقه خاتمه می یابد .
pass
باعث بروز هیچ اتفاقی نمی شود . نام دیگر این عبارت عبارت تهی می باشد .
قطعه else حلقه
کد های این قطعه فقط و فقط زمانی اجرا خواهد شد که حلقه با روند عادی خاتمه یابد (با دستور break نا تمام نماند)

ساختار عمومی و اصلی حلقه while

زمانی که از دستورات break و continue نیز در داخل حلقه استفاده گردد حالت کلی آن به صورت زیر خواهد بود :

while <test>:
	<statements1>
	if <شرط>: break    # else خروج آنی از حلقه و عدم اجرای قطعه 
	if <شرط>: continue # پرش به اول قطعه شرط و بررسی شرط اجرا
else:
	<statements2> # اجرا نشده و حلقه بصورت عادی خاتمه یابد  'break' اجرا در مواقعی که دستور 

دستورات break و continue در هر بخش حلقه می توانند ظاهر شوند ولی معمولا این دو دستور در داخل یک عبارت شرطی قرار می گیرند پس در صورت صحت شرط اجرا می گردند .

مثال

همانطور که گفته شد معمولا از دستور pass برای تعریف توابع یا کلاس های یا سایر قطعه های خالی استفاده می گردد . مثلالی بسیار ساده از این دستور می تواند به صورت زیر باشد .

while 1: pass # type Ctrl-C to stop me!

این حلقه یک حلقه بی نهایت می باشد که هیچ کاری را نیز انجام نمی دهد ! در مثال بالا دستور و کد درون حلقه مستقیما و در مقابل شروع کننده حلقه یعنی عبارت while قرار دارد . همانند دستور شرطی if اگر دستور مورد نظر فقط یک سطر باشد این کار امکان پذیر می باشد .

در مثال بعدی قصد داریم اعداد زوج موجود بین ده تا صفر را با شروع از بزرگترین عدد چاپ کنیم . از دستور continue برای رد شدن از اعداد فرد استفاده می گردد .

x = 10
while x:
    x = x-1
    if x % 2 != 0: continue
    print x,

خروجی مثال فوق :

8 6 4 2 0

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

از دستور break معمولا به عنوان کنترل کننده و خاتمه دهنده یک جستجو یا خاتمه آنی حلقه به محض وقوع یک شرط خاص استفاده می گردد . برای مثال کد زیر یک عدد را از لحاظ اول بودن تست می کند .

x=y/2
while x > 1:
    if y % x == 0:               # بررسی اول بودن عدد
        print y, 'has factor', x
        break                    # else خروج آنی حلقه و عدم اجرای 
    x = x-1
else:                            # اجرا به هنگام خروج عادی
	print y, 'is prime'

بجای قرار دادن یک نشانگر یا پرچم (flag) برای تست در شرط حلقه از دستور break برای خروج آنی در اولین رخداد استفاده می گردد . یعنی زمانی که عدد مورد بررسی قابل تقسیم بر یک عدد باشد . در این صورت بخش else نیز اجرا نخواهد شد . در این مثال برای بهینه تر کردن جستجو و الگوریتم از بررسی عدد از نصف آن شروع می گردد . در صورتی که باقیمانده تقسیم عدد مورد نظر بر اعداد کوچکتر از نصف خود برابر صفر نباشد دسترو break اجرا نشده و حلقه در حالت طبیعی و با حداکثر حالت های ممکنه اجرا شده و دستورات داخل else نیز اجرا می شود . بخاطر داشته باشید که بخش else اگر حلقه اصلا اجرا نگردد نیز اجرا خواهد شد . یعنی زمانی که در اولین اجرا شرط نادرست بوده و اصلا دستورات داخل حلقه اجرا نگردد . مثلا اگر متغییر y عدد یک یا کوچکتر باشد مستقیما دستور داخل else اجرا می گردد و عبارت "is prime" نمایش داده می شود .

حلقه for

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

ساختار کلی حلقه for

حلقه for در پایتون با یک شروع کننده آغاز می گردد که کار اصلی آن تعریف یک (یا چند) متغییر به عنوان پیمایشگر و مشخص کردن آرایه مورد نظر برای پیمایش می باشد .

for <متغییر پیمایشگر> in <object>:  # به متغییر پیمایشگر object مقدار دهی تک تک اعضای 
    <statements>   # تکرار کد های داخل حلقه با متغیر پیمایشگر مقدار دهی شده 
else:
    <statements>   # اجرا نگردد  break اجرا زمانی که دستور 

زمانی که حلقه for در پایتون به اجرا در می آید تک تک عناصر توالی یا آرایه موجود با متغییر پیمایشگر نسبت داده شده و در حقیقت دستورات داخل حلقه برای تک تک عناصر اجرا می گردد . این نوع خاص حلقه بسیار بهینه تر و ساده تر از حلقه های موجود در زبانی چون C می باشد که برای پیمایش یه آرایه به یک متغییر به عنوان پیمایشگر یا ایندکس و نیز اطلاع از طول آرایه نیاز بود . حلقه for نیز درست مانند حلقه while دارای بخش else می باشد که نحوه اجرای آن دقیقا مثل حلقه while می باشد . دستورات continue و break نیز که در بالا توضیح داده شد به همان صورت مشابه مورد استفاده قرار می گیرد . با در نظر گرفتن این موارد ساختار عمومی و کلی حلقه for به صورت زیر می باشد .

for <پیمایشگر> in <object>:
    <statements>
    if <test>: break
    if <test>: continue
else:
    <statements>

حلقه های شمارنده

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

>>> range(5), range(2, 5), range(0, 10, 2)
([0, 1, 2, 3, 4], [2, 3, 4], [0, 2, 4, 6, 8])

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

>>> for i in range(3): 
	print i, 'Pythons'
…
0 Pythons
1 Pythons
2 Pythons

مثال های for

پیمایش یک لیست

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

>>> for x in ["spam", "eggs", "ham"]:
…     print x,
…
spam eggs ham

متغییر پیمایشگر x هر بار برابر با یکی از اعضای داخل لیست شده و دستورات داخل حلقه به ازای همان مقدار اجرا می گردند . ظاهر دستور بسیار شبیه به زبان انگلیسی می باشد . برای مشخص شدن سهولت دستور فوق سعی کنید معادل آن را در زبان دیگری بنویسید .

محاسبه حاصل جمع عناصر لیست

در مثال بعدی با استفاده از حلقه for حاصل جمع اعداد داخل یک لیست محاسبه می گردد .

>>> sum = 0
>>> for x in [1, 2, 3, 4]:
…     sum = sum + x
…
>>> sum
10

محاسبه حاصل ضرب عناصر لیست

با حلقه ای فشرده تر حاصل ضرب اعداد درون لیست محاسبه می گردد :

>>> prod = 1
>>> for item in [1, 2, 3, 4]: prod = prod * item
…
>>> prod
24

پیمایش رشته

رشته نیز نوعی آرایه یا توالی از کاراکتر ها بوده و همانند یک آرایه یا لیست می توان با استفاده از حلقه for به تک تک عناصر آن دسترسی داشت .

>>> x = 'Python'
>>> for item in x: 
	print item,
…
P  y  t  h  o  n

استفاده از چندین پیمایشگر

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

>>> T = [(1, 2), (3, 4), (5, 6)]
>>> for (a, b) in T:
…     print a, b
…
1 2
3 4
5 6

مقایسه حلقه های for و while

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

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

یک مثال برای مقایسه

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

خواندن فایل با استفاده از while

خواند اطلاعات فایل بصورت خط به خط با استفاده از while :

file = open("test.txt", "r")
while 1:
    line = file.readline() # خواندن یک خط از فایل
    if not line: break     # خروج از حلقه در صورت اتمام فایل
    Process line here

در این روش یک حلقه بی نهایت ایجاد شده و تا زمانی که فایل به انتهای خود نرسد عمل خواندن انجام می گیرد . در صورتی که فایل خاتمه یابد مقدار تابع readline برابر تهی یا None می گردد و مقدار not line با فرض اینکه مقدار متغییر None باشد مقدار درست شده بنابراین دستور break اجرا می گردد و حلقه خاتمه می یابد .

خواندن فایل با استفاده از for

در حلقه for از تابع readlines استفاده شده که بر خلاف تابع readline کل فایل را بیکباره می خواند .

file = open("name", "r")
for line in file.readlines():
  Process line here

حجم کد و خوانایی دو روش را مقایسه کنید ! باز برای درک سهولت فوق العاده کد های فوق سعی کنید تا همین کار را با یک زبان برنامه نویسی دیگر پیاده سازی کنید ! متوجه فوق بسیار زیاد و سهولت و در عین حال قدرت بسیار زیاد زبان پایتون خواهید شد .

 

مثال هایی سخت تر و عملی تر

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

>>> omelet=>>> ingredients = omelet.keys()
>>> ingredients
[‘cheese’, ‘pepper’, ‘egg’, ‘milk’, ‘mushroom’]
>>> while len(ingredients) > 0:
...      current = ingredients.pop()
...      print “Adding %d %s to the mix” % (omelet[current],current)
...
Adding 5 mushroom to the mix
Adding 1 milk to the mix
Adding 2 egg to the mix
Adding 1 pepper to the mix
Adding 1 cheese to the mix

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

دستور بعدی برای حلقه ... for ... in می باشد . که شبیه به دستور while می باشد با این تفاوت که در این حالت نیازی به تعیین شرط پایان حلقه نبوده و در ضمن متغییری که به تک تک عناصر لیست اشاره می کند ایجاد می گردد که می توانید از آن در داخل حلقه استفاده کنید . معادل مثال بالا را با for به صورت زیر می باشد :

>>> for ingredient in omelet.keys():
...     print “adding %d %s to the mix” % (omelet[ingredient],ingredient)

همانطور که مشاهده می کنید کد نوشته شده با for بسیار بهینه تر و کوتاهتر می باشد .


صفحه قبلی: پایتون
صفحه بعدی: PyGTK