خانه توسعهدهنده تکنولوژی بکاند پایتون Collections در پایتون
Collections در پایتون
ماژول Collections که یکی از ماژولهای درونهستهی زبان برنامهنویسی پایتون است، انواع مختلف و کارآمدی از کانتینرها را به ما ارائه میدهد. کانتینر یک شیء است که برای ذخیرهسازی اشیاء مختلف استفاده میشود و راهی برای دسترسی به اشیاء موجود و پیمایش روی آنها فراهم میکند. بهطور کلی در برنامهها ما از List ،Tuple ،Dictionary و Set که نوعدادهها و کانتینرهای پیشفرض پایتون هستند استفاده میکنیم. اما وقتی که با دادههای پیچیدهتر و ساختیافته سروکار داریم، نیاز به کانتینرهای هوشمندتری نیز داریم.
در این مقاله با هم نگاهی به برخی از این ساختماندادهها خواهیم داشت و با کاربرد هر یک آشنا خواهیم شد.
فهرست مطالب
Togglenamedtuple
میتوانیم namedtuple را یک نسخهی بهبودیافته از tuple در نظر بگیریم که به ما امکان ایجاد یک کلاس با فیلدهای مشخص را میدهد. کلیدیترین تفاوت بین namedtuple و tuple، نحوهی دسترسی به دادههاست. در tuple ما تنها از طریق ایندکسها میتوانیم به عنصر موردنظر دسترسی پیدا کنیم. در صورتی که در namedtuple علاوه بر ایندکس، از طریق نام هر فیلد نیز میتوانیم به مقدار آن دسترسی پیدا کنیم.
برای ایجاد یک namedtuple و شیءهایی از آن میتوانیم به شکل زیر عمل کنیم:
>>> from collections import namedtuple
>>> movie = namedtuple('movie', ['genre', 'rating', 'lead_actor'])
>>> ironman = movie(genre='action', rating=8.5, lead_actor='robert downey junior')
>>> ironman.rating
8.5
>>> ironman[1]
8.5
در کد بالا، ابتدا از ماژول Collections، کلاس namedtuple را وارد کردیم و در خط دوم، یک namedtuple ساختیم که یک فیلم را با فیلدهای ژانر، امتیاز و هنرپیشهی اصلی تعریف میکند. بهطور کلی برای ایجاد یک namedtuple نیاز به مشخص کردن یک نام (typename) و شناسهی فیلدها داریم. فیلدها میتوانند در قالب لیستی از رشتهها یا رشتهای ساده که با space فیلدها را از یکدیگر جدا کرده است، بیایند. همانطور که در کد بالا مشاهده میکنید، ما با استفاده از شناسهی هر فیلد میتوانیم به مقدار آن دسترسی داشته باشیم و این سهولت دسترسی به داده باعث شده تا کدی خواناتر بنویسیم. از دیگر مزیتهای مهم namedtuple میتوان به مصرف کمتر حافظه نسبت به دیکشنری معادل اشاره کرد؛ بنابراین هنگام کار با حجم زیادی از دادهها استفاده از namedtupleها باعث بهینگی خواهد شد.
namedtuple همچنین دارای متدهای متنوعی هست که میتوانید از آنها استفاده کنید. در اینجا دو مورد از این متدها را باهم بررسی خواهیم کرد:
()asdict_
این متد به شما اجازه میدهد تا شیء namedtuple خود را به یک دیکشنری تبدیل کنید.
>>> ironman._asdict()
{'genre': 'action', 'rating': 8.5, 'lead_actor': 'robert downey junior'}
(kwargs**)replace_
این متد، یک شیء جدید از namedtuple که مقدار فیلدهای آن با kwargs جایگزین شدهاند را برمیگرداند.
>>> ironman = ironman._replace(rating=8)
>>> ironman.rating
8
Counter
این کتابخانه از ماژول Collections پایتون که خود زیرکلاسی از کلاس نوعدادهی dict
است، به ما این امکان را میدهد تا خیلی راحت بتوانیم تعداد تکرار عناصر در اشیای hashable را محاسبه کنیم. شیء Counter یک دیکشنری برمیگرداند که عناصر ما بهعنوان کلیدهای دیکشنری و تعداد تکرارشان بهعنوان مقدار آن کلید قرار گرفتهاند.
>>> from collections import Counter
>>> Counter("abracadabra")
Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
همان طور که اشاره کردیم، Counter از کلاس dict
به ارث رسیده است ولی یکی از تفاوتهای کلیدی Counter با دیکشنری، رفتار آنها در مواجهشدن با کلیدی است که در دیکشنری موجود نباشد. در دیکشنری اکسپشن KeyError
پرتاب میشود ولی در Counter مقدار 0 برمیگردد.
بنابر خاصیت ارثبری، کلاس Counter، تمامی متدهای کلاس dict
را شامل میشود. اما علاوه بر این متدها، چهار متد اضافهتر نیز دارد که در این مقاله به بررسی آنها میپردازیم.
()elements
این متد یک iterator شامل تمامی عنصرها که هرکدام به اندازهی تعدادشان تکرار شدهاند را بر میگرداند. لازم به ذکر است که اگر تعداد یک عنصر کمتر از یک باشد، این متد آن را نادیده میگیرد.
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> sorted(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']
([n])most_common
این متد لیستی از n پرتکرارترین عناصر شیء ما را به همراه تعداد تکرارشان به ترتیب غیرصعودی برمیگرداند. در صورتی که عدد n مشخص نشده باشد، این تابع تمامی عناصر موجود در شیء Counter را برمیگرداند.
>>> Counter('abracadabra').most_common(3)
[('a', 5), ('b', 2), ('r', 2)]
([iterable-or-mapping])subtract
این متد که در پایتون 3.2 معرفی شد، در آرگومان خود یک شیء iterable یا یک شیء mapping میگیرد و تعداد تکرار عنصرها را از آرگومان دادهشده کسر میکند.
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> d = Counter(a=1, b=2, c=3, d=4)
>>> c.subtract(d)
>>> c
Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
()total
این متد که در پایتون 3.10 معرفی شد، مجموع تعداد تکرارها را برمیگرداند.
>>> c = Counter(a=10, b=5, c=0)
>>> c.total()
15
deque
deque که کوتهاهشدهی double-ended queue است، برای ما لیستی را فراهم میکند تا بتوانیم با پیچیدگی زمانی O(1) و مصرف حافظهی بهینه، عملیات pop و append را از هر دو سمت لیست داشته باشیم. این ساختمانداده اولین کتابخانهای بود که به ماژول Collections در زمان انتشار پایتون 2.4 اضافه شد و هدف اصلی آن حل مشکلات کارایی در عملیات pop و append لیست درونهستهی پایتون بود. با حل این مشکلات، این نوعداده به یکی از بهترین گزینهها برای پیادهسازی استک و صف دلخواه در پایتون تبدیل شد.
برای ایجاد یک شیء deque میتوانیم به شکل زیر عمل کنیم:
>>> from collections import deque
>>> queue = deque(['Quera', 'Python', 'Blog'])
deque(['Quera', 'Python', 'Blog'])
جهت اضافه کردن یک عنصر به deque، میتوانیم از توابع append و appendleft استفاده کنیم که بهترتیب یک عنصر را به سمت راست لیست و یک عنصر را به سمت چپ لیست اضافه میکند.
>>> queue.append(18)
>>> queue.appendleft(24)
>>> queue
deque([24, 'Quera', 'Python', 'Blog', 18])
و برای حذف کردن یک عنصر از deque، میتوانیم از تابعهای pop و popleft استفاده کنیم که بهترتیب یک عنصر را از سمت راست لیست و یک عنصر را از سمت چپ لیست حذف میکند.
>>> queue.pop()
18
>>> queue
deque([24, 'Quera', 'Python', 'Blog'])
>>> queue.popleft()
24
>>> queue
deque(['Quera', 'Python', 'Blog'])
همچنین برای شمارش تعداد تکرار یک عنصر داخل لیست از تابع count و برای حذف تمامی عناصر لیست از تابع clear میتوانیم استفاده کنیم. لازم به ذکر است deque متدهای کاربردی فراوانی دارد که در این لینک میتوانید آنها را مطالعه بفرمایید.
defaultdict
استفاده از ساختمان داده دیکشنری برای ذخیرهسازی دادهها یکی از رایجترین انتخابهای هر برنامهنویس است. کتابخانهی defaultdict که یکی دیگر از ساختماندادههایی است که توسط ماژول Collections فراهم شده است، با ارثبری از کلاس درونهستهی dict
پایتون و override کردن یک متد آن (__missing__)، برای کلیدهایی که در دیکشنری وجود ندارد یک مقدار پیشفرض در نظر میگیرد و هیچگاه اکسپشن KeyError
را پرتاب نمیکند.
برای ساخت یک شیء DefaultDict به شکل زیر عمل میکنیم:
>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["Quera"]
[]
آرگومانی که به تابع سازندهی این شیء پاس داده میشود، default_factory
هست که مقدار پیشفرض ما را ایجاد میکند. هنگامی که یک کلید را که در دیکشنری موجود نیست فراخوانی میکنیم، متد __missing__
صدا زده میشود. در این متد ابتدا مقدار default_factory
چک میشود که آیا برابر None
هست یا خیر. اگر برابر None
بود، اکسپشن KeyError
رخ میدهد. در غیر این صورت، default_factory
بدون آرگومان فراخوانی میشود تا مقدار پیشفرض را تهیه کند.
در نهایت از شما دعوت میکنم تا برای حرفهای شدن در زبان برنامهنویسی پایتون، از دوره آموزش پایتون کوئراکالج استفاده کنید.