با 5 ویژگی پیشرفته زبان پایتون و نحوه استفاده از آنها آشنا شوید
زبان پایتون ، زبان فوقالعادهای است. این زبان تفسیری و استفاده از آن آسان است. اما آیا شما از تمامی ویژگیها و قابلیتهای این زبان برنامه نویسی استفاده میکنید؟
معمولاً ویژگیهای پیشرفته تمامی زبانهای برنامهنویسی را با تکرار و تمرین مداوم میتوان کشف کرد. فرض کنید در حال کدنویسی پروژه پیچیدهای هستید و در Stack Overflow به دنبال چیزی میگردید و در نهایت برای حل مشکل خود به راهحلی میرسید که از یکی از ویژگیهای پیشرفته زبان پایتون استفاده میکند و شما از وجود چنین قابلیتی اطلاع نداشتید.
در ادامه به معرفی 5 ویژگی پیشرفته و پرکاربرد زبان پایتون میپردازیم و علاوه بر آن نحوه استفاده از آنها را شرح میدهیم.
ویژگی های پیشرفته زبان پایتون
1) توابع لامبدا
تابع لامبدا Lambda functions، تابعی کوچک و بی نام است. دلیل اینکه این توابع بینام هستند این است که بدون نام تعریف میشوند.
توابع پایتون اغلب با فرمت ” Def نام_ تابع ()” تعریف میشوند اما توابع لامبدا را به صورت بینام استفاده میکنیم و نامی برای آن تعیین نمیکنیم. دلیل اینکه برای این توابع نام تعیین نمیکنیم این است که از توابع لامبدا برای اجرای نوعی عبارت (Expression) و عملیات ساده استفاده میشود که برای انجام آنها نیازی به تعریف کامل یک تابع نیست.
تابع لامبدا میتواند آرگومانهای متعددی داشته باشد اما فقط میتواند یک عبارت (Expression) داشته باشد:
1 x = lambda a, b : a * b 2 print(x(5, 6) # prints '30' 3 4 x = lambda a : a*3 + 3 5 print(x(3)) # prints '12' 6
استفاد از این تابع بسیار آسان است. با استفاده از این تابع توانستیم بدون تعریف کامل یک تابع، بخشی از یک عملیات ریاضی ساده را انجام دهیم. تابع لامبدا یکی از چندین ویژگی زبان پایتون است که استفاده از این زبان برنامهنویسی را آسان میکند.
2) نگاشتها
Map() یکی از توابع توکار پایتون است که از آن برای اجرای تابعی بر روی توالیای از عناصر، از قبیل یک فهرست و یا دیکشنری استفاده میشود. این تابع بسیار آسان است و مهمتر آنکه روشی خوانا برای اجرای چنین عملیاتی است.
1 def square_it_func(a): 2 return a * a 3 4 x = map(square_it_func, [1, 4, 7]) 5 print(x) # prints '[1, 16, 49]' 6 7 def multiplier_func(a, b): 8 return a * b 9 10 x = map(multiplier_func, [1, 4, 7], [2, 5, 8]) 11 print(x) # prints '[2, 20, 56]'
به مثال فوق توجه کنید. ما میتوانیم تابع خود را بر روی یک یا چند لیست اجرا کنیم. به عبارت دیگر میتوانید یک map را به همراه هر یک از توابع پایتون که تصورش را میکنید، استفاده کنید. البته به شرطیکه این تابع با توالیای که بر روی آن عملیات را انجام میدهید، سازگار باشد.
[irp posts=”12723″]3) فیلتر کردن
تابع توکار Filter شباهت زیادی به تابع Map دارد. به بیانی دیگر، Filter نیز همانند Map تابعی بر روی یک توالی (لیست، مجموعه چندتایی Tuple، دیکشنری) اجرا میکند. تفاوت کلیدی میان این دو قابلیت در این است که filter() فقط عناصری را باز میگرداند که تابع اعمال شده آنها را با مقدار True باز گردانده است.
1 # Our numbers 2 numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] 3 4 # Function that filters out all numbers which are odd 5 def filter_odd_numbers(num): 6 7 if num % 2 == 0: 8 return True 9 else: 10 return False 11 12 filtered_numbers = filter (filter_odd_numbers, numbers) 13 14 print(filtered_numbers) 15 # filtered_numbers = [2, 4, 6, 8, 10, 12, 14] 16
در کد فوق True یا False بودن هر یک از عناصر موجود در فهرست را بررسی کردیم و علاوه بر آن تابع filter() تمامی عناصری که مقدار آنها True بوده را باز گردانده است. از این تابع میتوانیم برای ساخت فهرست بازگشتی پس از رعایت دو شرط لازم استفاده کنیم.
4) Itertools
ماژول Itertools زبان پایتون مجموعهای از ابزارها است که تکرارکنندهها Iterators را مدیریت و کنترل میکند. تکرارکننده نوعی داده است که میتوان از آن در یک حلقه for از جمله لیستها، مجموعههای چندتایی tuples و دیکشنریها dictionaries استفاده کرد.
استفاده از توابع در ماژول Itertools این امکان را برای شما فراهم میکند تا عملیاتهای تکرارکننده زیادی انجام دهید که در حالت عادی برای انجام آنها به توابع چندخطی و خلاصه لیستهای List comprehension پیچیده نیاز دارید. برای آشنایی بیشتر با ماژول فوقالعاده Itertools به مثال مقابل توجه کنید:
1 from itertools import * 2 3 # Easy joining of two lists into a list of tuples 4 for i in izip([1, 2, 3], ['a', 'b', 'c']): 5 print i 6 # ('a', 1) 7 # ('b', 2) 8 # ('c', 3) 9 10 # The count() function returns an interator that 11 # produces consecutive integers, forever. This 12 # one is great for adding indices next to your list 13 # elements for readability and convenience 14 for i in izip(count(1), ['Bob', 'Emily', 'Joe']): 15 print i 16 # (1, 'Bob') 17 # (2, 'Emily') 18 # (3, 'Joe') 19 20 # The dropwhile() function returns an iterator that returns 21 # all the elements of the input which come after a certain 22 # condition becomes false for the first time. 23 def check_for_drop(x): 24 print 'Checking: ', x 25 return (x > 5) 26 27 for i in dropwhile(should_drop, [2, 4, 6, 8, 10, 12]): 28 print 'Result: ', i 29 30 # Checking: 2 31 # Checking: 4 32 # Result: 6 33 # Result: 8 34 # Result: 10 35 # Result: 12 36 37 38 # The groupby() function is great for retrieving bunches 39 # of iterator elements which are the same or have similar 40 # properties 41 42 a = sorted([1, 2, 1, 3, 2, 1, 2, 3, 4, 5]) 43 for key, value in groupby(a): 44 print(key, value), end=' ') 45 46 # (1, [1, 1, 1]) 47 # (2, [2, 2, 2]) 48 # (3, [3, 3]) 49 # (4, [4]) 50 # (5, [5])
5) Generator
تابع Generator این امکان را برای ما فراهم میکند تا تابعی را که همانند تکرارکننده عمل میکند را تعریف کنیم؛ به عبارت دیگر میتوان از این تابع در حلقه for استفاده کرد. استفاده از این تابع، کد را تا حد زیادی آسان میکند و نسبت به حلقه for فضای کمتری از حافظه را اشغال میکند.
فرض کنید میخواهیم اعداد 1 تا 1000 را با هم جمع کنیم. بخش اول کد مقابل نشان میدهد که چگونه میتوانید با استفاده از یک حلقه for این عملیات ریاضی را انجام دهید.
[irp posts=”9052″]این کد در مواردی که فهرست کوچک باشد، برای مثال اگر فهرست شامل 1000 عنصر باشد، عملکرد مناسبی دارد. اما زمانیکه فهرست بسیار بزرگ باشد، برای مثال اگر فهرست از 1 میلیارد عدد اعشار تشکیل شده باشد، کارایی این کد تضعیف میشود. در این حالت اگر از یک حلقه for استفاده کنیم، این فهرست بزرگ که حجم بالایی از حافظه را اشغال میکند، در حافظه (memory) ذخیره میشود –همه افراد که RAM نامحدودی در اختیار ندارد تا بتوانند چنین چیزی را بر روی آن ذخیره کنند. تابع range() در زبان پایتون همین عملیات را انجام میدهد و فهرست را در حافظه ایجاد میکند.
بخش دوم این کد با استفاده از یک generator پایتون، عمل جمع کردن لیست هایی از اعداد را به نمایش میگذارد. Generatorها فقط در صورتی عناصر را ایجاد و در حافظه ذخیره میکنند که به آنها نیاز داشته باشند. به عبارت دیگر اگربخواهید 1 میلیارد عدد با ممیز اعشاری Floating point number ایجاد کنید، فقط یکبار آنها را در حافظه ذخیره خواهید کرد. تابع xrange() در زبان پایتون برای ایجاد لیستها از generatorها استفاده میکند.
نکته مهم: اگر عناصر بسیار زیادی دارید و تصمیم دارید فهرستی برای آنها ایجاد کنید، از generator و یا تابع xrange استفاده کنید. به ویژه در مواردی که سیستمی دارید که تا حد زیادی به حافظه متکی است، برای مثال تلفن همراه و یا رایانش پیشرفته، به کارگیری این روش بسیار سودمند خواهد بود.
از سوی دیگر اگر تصمیم دارید این فهرست را چندین بار تکرار کنید و فهرست به اندازهای کوچک است که در حافظه جای میگیرد، بهتر است از حلقههای for و یا تابع range استفاده کنید. دلیل انجام چنین کاری این است که هر بار که به generatorها و xrange دسترسی پیدا میکنید، آنها مقادیر لیست را از نو ایجاد میکنند، درصورتی که تابع range لیستی ثابت است و اعداد صحیح برای دسترسی سریع از قبل در حافظه قرار دارند.
1 # (1) Using a for loop 2 numbers = list() 3 4 for i in range(1000): 5 numbers.append(i+1) 6 7 total = sum(numbers) 8 9 # (2) Using a generator 10 def generate_numbers(n): 11 num = 0 12 while num < n: 13 yield num 14 num += 1 15 total = sum(generate_numbers(1000)) 16 17 # (3) range() vs xrange() 18 total = sum(range(1000 + 1)) 19 total = sum(xrange(1000 + 1))