پیش نیاز های مقاله
توجه:
ویدیوی قرار داده شده تنها یکی از قسمت های دوره رایگان آموزش پایتون است. اگر میخواید عمیق تر مباحث رو درک کنید میتونید دوره رو به صورت کامل شرکت کنید.
چی شد که نیاز به تابع range احساس شد؟
بیاید همگی با دید یک برنامه نویسی که اولین باره با حلقه for آشنا میشه به این محتوا نگاه کنیم.
خب میخوایم حلقه for ام به یک تعداد دلخواهی تکرار بشه ولی اصلا لیستی در کار نیست فقط میخوام حلقه ام به یک تعدادی تکرار بشه، این دقیقا اولین نقطه ای هستش که به تابع range نیاز پیدا کردید.
خب اگر هنوز با فانکشن رینج آشنا نباشید و بخواید مشکلتون رو خیلی برنامه نویس طور حل کنید احتمالا ذهن خلاق python ای شما اینطور تحلیل میکنه:
من برای حلقه نهاییم نیاز به یک توالی از اعداد دارم به عنوان مثال نیاز به اعداد بین 5 تا 50 دارم.
خب خیلی سریع میگید یک حلقه مینویسم و این لیست رو تولید میکنم و اون لیست رو در حلقه نهاییم استفاده میکنم مثلا اینطوری:
numbers = [] # یک لیست خالی برای نگهداری اعداد
number = 5 # از 5 شروع میکنیم
while number <= 50:
numbers.append(number) # عدد را به لیست اضافه میکنیم
number += 1 # یک واحد جلو میرویم
print(numbers)توالی که ساختیم:
[5, 6, 7, 8, 9, ..., 48, 49, 50]تازه الان میتونیم منطقی که میخواستیم رو شروع کنیم:
for number in numbers:
# اینجا منطق نهایی برنامه را مینویسیم
print(number)پس دیدید که چقدر کد اضافی زده بشه اگر تابع range نمی بود؟!
پس بیاید با هم بیشتر قدر تابع range رو بدونیم.
تابع range در پایتون چیست؟ نحوه استفاده
تابع range برای ساخت دنباله ای از اعداد استفاده میشه، معمولا وقتی میخوایم یک کاری رو چند بار تکرار کنیم یا روی یک سری اعداد پیمایش کنیم و همزمان روی بازه این اعداد هم کنترل داشته باشیم از فانکشن رینج استفاده میکنیم.
به طور کلی این تابع range سه شکل استفاده داره
| شکل استفاده | معنی | مثال | خروجی |
| range(stop) | از ۰ تا یکی کمتر از stop | range(5) | 0, 1, 2, 3, 4 |
| range(start, stop) | از start تا یکی کمتر از stop | range(1, 6) | 1, 2, 3, 4, 5 |
| range(start, stop, step) | با گام دلخواه | range(0, 11, 2) | 0, 2, 4, 6, 8, 10 |
نکته مهم: خود عدد stop هیچوقت تولید نمیشود. پس اگر مثلا میخواید عدد 1 تا 10 را کامل داشته باشید باید range(1, 11) اینطوری تعریف بشه.
پارامتر های تابع range:
- stop: تنها پارامتر اجباری تابع range است. مشخص میکند توالی کجا تمام شود.
- start: اختیاری است. پیشفرض start صفر است. نقطه شروع توالی رو مشخص میکند و خود عدد در توالی قرار خواهد داشت (برعکس stop).
- step: اختیاری است. پیشفرض گام یا step یک است. مشخص کننده گام هایی است که توالی را ایجاد میکند. مقادیر مثبت و منفی دریافت میکند.
مقدار مثبت: توالی افزایشی
مقدار منفی: توالی کاهشی (نزولی یا معکوس)
مثالی برای ساخت توالی معکوس با تابع رینج:
for number in range(10, 0, -2):
print(number)خروجی:
10
8
6
4
2
مثال جمع اعداد 1 تا 100
total = 0
for number in range(1, 101):
total += number
print("جمع اعداد:", total) # 5050
آیا تابع range در پایتون از نظر رفتاری lazy است؟ مهم
بزارید اول چالش رو بندازم توی ذهنتون، پس این کد رو ببینید:
numbers = range(0, 1000000)
print(numbers)خروجی جالب:
range(0, 1000000)چرا وقتی که تابع range رو چاپ کردم توالی اعداد رو نگرفتم؟! چرا توالی یک میلیونی که از تابع رینج خواستم تولید نشده؟ این باگ نیست اشتباه نکنید.
وقتی که شما پارامتر ها رو به تابع range میدید بلافاصله توالی رو نمیسازه، بلکه میاد مقدار شروع، نقطه پایان، و گام توالی رو ذخیره میکنه.
ساده ترین توضیحش اینه که انگار تابع range نقشه ساخت توالی رو ذخیره میکنه و نگهداری میکنه نه اینکه همیشه کل توالی رو بسازه و نگهداری کنه.
اگر یکم بهش فکر کنید کاملا منطقیه، چرا باید بلافاصه python بیاد یک توالی یک میلیونی بسازه و توی حافظه نگهداری کنه؟!
اینکار باعث یک بار اضافی در برنامه میشه و پرفورمنس الکی هدر میره بدون اینکه فعلا توی اون خط کد نیازی به اون توالی باشه پس python چیکار میکنه؟
چرا میگیم تابع range در python رفتار lazy دارد؟
ایده اصلی ارزیابی تنبل یا Lazy Evaluation دقیقا همینه، میگه "چیزی را تا زمانی که به آن نیاز نداریم، از قبل تولید نکنیم".
پس شما وقتی تابع رینج رو به حلقه for میدید، تازه اون زمان توالی شروع به ساخته شدن میکنه، تا قبل از اون range هیچ لیستی تولید نمی کند مگر اینکه دستی اون رو مجبور کنیم.
به این شکل میتونیم رینج رو مجبور به ساخت کامل و نگهداری توالی در همون ابتدا کنیم:
numbers = list(range(0, 1000000))
print(numbers)خروجی:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... , 999990, 999991, ..., 999999]
پس به طور خلاصه:
range به جای اینکه تمام یک توالی رو بسازه و داخل حافظه نگهداری کنه، اطلاعات لازم برای ساخت اون توالی رو نگهداری میکنه که امکان پیمایش با مصرف کم حافظه رو به وجود بیاره.