جانشین های پرسرعت برای loop ها در پایتون!

اول کلام سلام .در این مقاله سعی کردم یه موضوعی که شاید خیلیاتون بلد باشید ولی در عمل بکار نمیبرید رو بنویسم (بماند که خودمم تازه دارم عملی استفاده میکنم :)))) )نمیگم حلقه ها بده ولی تا وقتی داده های ما کم و کوچیک هستن پاسخگوی مناسبی هست .ولی تکلیف Data science چی میشه ؟ اونایی که با داده های خیلی بزرگ کار میکنن و استفاده از حلقه ها سرعت برنامشون رو به شدت پایین میاره !!خب بزن بریم چنتا چیز جدید یاد بگیریم که جایگزین خوبی برای حلقه ها به حساب میاد ?1 - استفاده از Filter :با توجه به اسمش فکر کنم حدس زدید که چیکار میکنه .اشیای iterable را برای ما فیلتر می کنه. ما می خوایم شرایط فیلتر را به صورت یک تابع منتقل کنیم و از این تابع برای فیلتر کردن هر عنصر در شی iterable استفاده می شه .Syntax:filter(function, iterable)خب حالا بریم یه مقایسه ای داشته باشیم بین حلقه های for و while با Filter.در اینجا، من لیستی از 100000 مورد متوالی دیدم که فاکتوریل اعداد زوج را انجام می ده. در پایان این مقادیر فاکتوریل را جمع می کنه.!!!!!!دقت کنید که نتایج بسته به سیستم شما متغیر است !!!!!!!!# Using for loopimport mathimport timeimport resourceimport systime_start = time.perf_counter()sys.set_int_max_str_digits(0)def factorial(n): return math.factorial(n)test_list = list(range(1, 100000))result = []for i in range(len(test_list)) : if test_list[i] % 2 == 0: result.append(test_list[i]) print(sum(result))time_elapsed = (time.perf_counter() - time_start)memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0print ("%f secs %f MByte" % (time_elapsed,memMb))# Output24999500000.041538 secs 1.082287 MByte# Using while loopimport mathimport timeimport resourceimport systime_start = time.perf_counter()sys.set_int_max_str_digits(0)def factorial(n): return math.factorial(n)test_list = list(range(1, 100000))result = []i=0while i < len(test_list) : if test_list[i] % 2 == 0: result.append(test_list[i]) i = i + 1 print(sum(result))time_elapsed = (time.perf_counter() - time_start)memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0print ("%f secs %f MByte" % (time_elapsed,memMb))# Output24999500000.047446 secs 1.085056 MByte# Using Filterimport mathimport timeimport resourceimport systime_start = time.perf_counter()sys.set_int_max_str_digits(0)def factorial(n): return math.factorial(n)test_list = list(range(1, 100000))result = filter(lambda x: x % 2 == 0, test_list)print(sum((result)))time_elapsed = (time.perf_counter() - time_start)memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0print ("%f secs %f MByte" % (time_elapsed,memMb))# Output24999500000.022666 secs 1.087833 MByteبریم سراغ بعدی 2 - استفاده از Map:این تابع برای وقتی که بخواهید عملی رو روی تک تک اعضای iterable مثل لیست و تاپل و ... اعمال کنید .syntax :map(function, iterable)حالا مثل قبلی یه مقایسه تر و تمیز مشاهده خواهیم کرددددد :# Using for loopimport mathimport timeimport resourceimport systime_start = time.perf_counter()sys.set_int_max_str_digits(0)def factorial(n): return math.factorial(n)test_list = list(range(1, 10000))result = 0for i in range(len(test_list)) : test_list[i] = factorial(test_list[i]) print(sum(test_list))time_elapsed = (time.perf_counter() - time_start)memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0print ("%f secs %f MByte" % (time_elapsed,memMb))#output284654436382457541 .....................042094031312.229430 secs 0.167130 MByte# Using while loopimport mathimport timeimport resourceimport systime_start = time.perf_counter()sys.set_int_max_str_digits(0)def factorial(n): return math.factorial(n)test_list = list(range(1, 10000))result = 0i=0while i < len(test_list) : test_list[i] = factorial(test_list[i]) i = i + 1 print(sum(test_list))time_elapsed = (time.perf_counter() - time_start)memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0print ("%f secs %f MByte" % (time_elapsed,memMb))#output284654436382457541 .....................042094031311.263874 secs 1.013439 MByte# Using Mapimport mathimport timeimport resourceimport systime_start = time.perf_counter()sys.set_int_max_str_digits(0)def factorial(n): return math.factorial(n)test_list = list(range(1, 10000))result = map(factorial, test_list)print(sum((result)))time_elapsed = (time.perf_counter() - time_start)memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0#Output284654436382457541 .....................042094031310.069755 secs 1.013439 MByte2 - استفاده از Reduce:پایتون تابعی به نام ()reduce ارائه می دهد که به شما امکان می دهد لیست را به روشی مختصرتر کاهش دهید. این تابع محاسبات تابعی را با در نظر گرفتن یک تابع و قابل تکرار مانند لیست، تاپل، سری و غیره به عنوان آرگومان انجام می دهد و یک مقدار واحد را به عنوان خروجی برمی گرداند.Syntax:reduce(function, iterable)تابع ()reduce تابع دو آرگومان را به صورت تجمعی برای آیتم های لیست، از چپ به راست اعمال می کند تا لیست را به یک مقدار کاهش دهد.برخلاف توابع map() و filter() , تابع reduce() یک تابع داخلی نیست و متعلق به ماژول functools است.# Using for loopimport mathimport timeimport resourceimport systime_start = time.perf_counter()sys.set_int_max_str_digits(0)def addition(x,y): return x + ytest_list = list(range(1, 1000000))result = 0for i in range(len(test_list)) : result = addition(result, test_list[i]) print(result)time_elapsed = (time.perf_counter() - time_start)memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0print ("%f secs %f MByte" % (time_elapsed,memMb))# Output4999995000000.289569 secs 0.167500 MByteو # Using while loopimport mathimport timeimport resourceimport systime_start = time.perf_counter()sys.set_int_max_str_digits(0)def addition(x,y): return x + ytest_list = list(range(1, 1000000))result = 0i=0while i < len(test_list) : result = addition(result, test_list[i]) i = i + 1 print(result)time_elapsed = (time.perf_counter() - time_start)memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0print ("%f secs %f MByte" % (time_elapsed,memMb))# Output4999995000000.429485 secs 0.167500 MByteTesting with a reduce function,# Using Reduce from functools import reduce import time import resource import sys time_start = time.perf_counter() sys.set_int_max_str_digits(0) def addition(x,y): return x + y test_list = list(range(1, 1000000)) result = reduce(addition, test_list) print(result) time_elapsed = (time.perf_counter() - time_start) memMb=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0 print (&quot%f secs %f MByte&quot % (time_elapsed,memMb)) # Output 499999500000 0.120981 secs 0.167500 MByte در حال حاضر، تفاوت تنها در میلی ثانیه است. اما اگر مجموعه داده‌ای واقعاً بزرگ داشته باشیم، این میلی‌ثانیه‌ها به ثانیه و ساعت تبدیل می‌شوند.