collections --- انواع داده‌ی ظرف

کد منبع: Lib/collections/__init__.py


این ماژول انواع داده‌ی ظرف تخصصی را پیاده‌سازی می‌کند و جایگزین‌هایی برای ظرف‌های توکار عمومی پایتون، dict، list، set و tuple فراهم می‌کند.

namedtuple()

تابع کارخانه‌ای (factory function) برای ایجاد زیرکلاس‌های تاپل با فیلدهای نام‌دار

deque

ظرفی فهرست‌مانند با امکان افزودن و برداشتن سریع در هر دو انتها

ChainMap

کلاس دیکشنری‌مانند برای ایجاد یک نمای واحد از چندین نگاشت

Counter

زیرکلاس دیکشنری برای شمارش اشیاء hashable

OrderedDict

زیرکلاسی از dict که ترتیب افزوده شدن آیتم‌ها را به خاطر می‌سپارد

defaultdict

زیرکلاس dict که برای تأمین مقادیر گم‌شده، یک تابع کارخانه را فراخوانی می‌کند

UserDict

پوششی دور اشیای دیکشنری برای زیرکلاس‌سازی آسان‌تر از dict

UserList

پوششی بر روی اشیای فهرست برای زیرکلاس‌سازی آسان‌تر فهرست

UserString

پوششی بر روی اشیاء رشته‌ای برای زیرکلاس‌سازی آسان‌تر از رشته

اشیاء ChainMap

اضافه شده در نسخه‌ی 3.3.

کلاس ChainMap برای پیوند سریع تعدادی نگاشت فراهم شده است تا بتوان با آن‌ها به‌عنوان یک واحد رفتار کرد. این کار اغلب بسیار سریع‌تر از ایجاد یک دیکشنری جدید و اجرای چندین فراخوانی update() است.

این کلاس می‌تواند برای شبیه‌سازی محدوده‌های تودرتو استفاده شود و در قالب‌بندی مفید است.

class collections.ChainMap(*maps)

یک ChainMap چندین دیکشنری یا نگاشت‌های دیگر را در کنار هم قرار می‌دهد تا یک نمای واحد و به‌روزرسانی‌پذیر ایجاد کند. اگر هیچ maps مشخص نشده باشد، یک دیکشنری خالی ارائه می‌شود تا یک زنجیره جدید همیشه حداقل یک نگاشت داشته باشد.

نگاشت‌های زیربنایی در یک فهرست ذخیره می‌شوند. آن فهرست عمومی است و می‌توان با استفاده از ویژگی maps به آن دسترسی پیدا کرد یا آن را به‌روزرسانی کرد. هیچ وضعیت دیگری وجود ندارد.

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

یک ChainMap نگاشت‌های زیربنایی را به‌صورت ارجاعی در بر می‌گیرد. بنابراین، اگر یکی از نگاشت‌های زیربنایی به‌روزرسانی شود، آن تغییرات در ChainMap منعکس خواهند شد.

تمام متدهای معمول دیکشنری پشتیبانی می‌شوند. علاوه بر این، یک ویژگی maps، یک متد برای ایجاد زیرزمینه‌های جدید، و یک پراپرتی برای دسترسی به همه نگاشت‌ها به‌جز اولین نگاشت وجود دارد:

maps

فهرستی از نگاشت‌ها که کاربر می‌تواند آن را به‌روزرسانی کند. این فهرست به ترتیب از نخستین مورد جستجوشده تا آخرین مورد جستجوشده مرتب شده است. این تنها وضعیت ذخیره‌شده است و می‌توان آن را برای تغییر نگاشت‌هایی که جستجو می‌شوند، تغییر داد. این فهرست باید همواره شامل دست‌کم یک نگاشت باشد.

new_child(m=None, **kwargs)

یک ChainMap جدید برمی‌گرداند که شامل یک نگاشت جدید و به دنبال آن همه‌ی نگاشت‌های موجود در نمونه فعلی است. اگر m مشخص شده باشد، نگاشت جدید در ابتدای فهرست نگاشت‌ها قرار می‌گیرد؛ اگر مشخص نشده باشد، از یک دیکشنری خالی استفاده می‌شود، به‌طوری که فراخوانی d.new_child() معادل ChainMap({}, *d.maps) است. اگر آرگومان‌های کلیدواژه‌ای مشخص شده باشند، آن‌ها نگاشت داده‌شده یا دیکشنری خالی جدید را به‌روزرسانی می‌کنند. این متد برای ایجاد زیرزمینه‌هایی استفاده می‌شود که می‌توانند بدون تغییر مقادیر هیچ‌یک از نگاشت‌های والد به‌روزرسانی شوند.

تغییر یافته در نسخه‌ی 3.4: پارامتر اختیاری m اضافه شد.

تغییر یافته در نسخه‌ی 3.10: پشتیبانی از آرگومان‌های کلیدواژه‌ای افزوده شد.

parents

ویژگی‌ای که یک ChainMap جدید حاوی همه‌ی نگاشت‌های موجود در نمونه‌ی جاری، به‌جز اولین آن‌ها را برمی‌گرداند. این ویژگی برای پرش از اولین نگاشت در جستجو مفید است. موارد استفاده مشابه موارد استفاده‌ی کلیدواژه‌ی nonlocal است که در محدوده‌های تودرتو استفاده می‌شود. این موارد استفاده همچنین مشابه موارد استفاده‌ی تابع توکار super() است. ارجاع به d.parents معادل است با: ChainMap(*d.maps[1:]).

توجه داشته باشید که ترتیب تکرار یک ChainMap با پیمایش نگاشت‌ها از آخر به اول تعیین می‌شود:

>>> baseline = {'music': 'bach', 'art': 'rembrandt'}
>>> adjustments = {'art': 'van gogh', 'opera': 'carmen'}
>>> list(ChainMap(adjustments, baseline))
['music', 'art', 'opera']

این همان ترتیبی را می‌دهد که یک دنباله از فراخوانی‌های dict.update() با شروع از آخرین نگاشت دارد:

>>> combined = baseline.copy()
>>> combined.update(adjustments)
>>> list(combined)
['music', 'art', 'opera']

تغییر یافته در نسخه‌ی 3.9: پشتیبانی از عملگرهای | و |= که در PEP 584 مشخص شده‌اند، افزوده شد.

همچنین ملاحظه نمائید

نمونه‌ها و دستورپخت‌های ChainMap

این بخش روش‌های مختلفی را برای کار با نگاشت‌های زنجیره‌ای نشان می‌دهد.

مثالی از شبیه‌سازی زنجیره‌ی جست‌وجوی داخلی پایتون:

import builtins
pylookup = ChainMap(locals(), globals(), vars(builtins))

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

import os, argparse

defaults = {'color': 'red', 'user': 'guest'}

parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = {k: v for k, v in vars(namespace).items() if v is not None}

combined = ChainMap(command_line_args, os.environ, defaults)
print(combined['color'])
print(combined['user'])

الگوهای نمونه برای استفاده از کلاس ChainMap جهت شبیه‌سازی زمینه‌های تودرتو:

c = ChainMap()        # Create root context
d = c.new_child()     # Create nested child context
e = c.new_child()     # Child of c, independent from d
e.maps[0]             # Current context dictionary -- like Python's locals()
e.maps[-1]            # Root context -- like Python's globals()
e.parents             # Enclosing context chain -- like Python's nonlocals

d['x'] = 1            # Set value in current context
d['x']                # Get first key in the chain of contexts
del d['x']            # Delete from current context
list(d)               # All nested values
k in d                # Check all nested values
len(d)                # Number of nested values
d.items()             # All nested items
dict(d)               # Flatten into a regular dictionary

کلاس ChainMap فقط به‌روزرسانی‌ها (نوشتن‌ها و حذف‌ها) را روی اولین نگاشت در زنجیره اعمال می‌کند، در حالی که جست‌وجوها کل زنجیره را جستجو می‌کنند. با این حال، اگر نوشتن‌ها و حذف‌ها در عمق بیشتری از زنجیره مورد نظر باشند، ساخت زیرکلاسی که کلیدهای یافت‌شده در عمق بیشتری از زنجیره را به‌روزرسانی کند، آسان است:

class DeepChainMap(ChainMap):
    'Variant of ChainMap that allows direct updates to inner scopes'

    def __setitem__(self, key, value):
        for mapping in self.maps:
            if key in mapping:
                mapping[key] = value
                return
        self.maps[0][key] = value

    def __delitem__(self, key):
        for mapping in self.maps:
            if key in mapping:
                del mapping[key]
                return
        raise KeyError(key)

>>> d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
>>> d['lion'] = 'orange'         # update an existing key two levels down
>>> d['snake'] = 'red'           # new keys get added to the topmost dict
>>> del d['elephant']            # remove an existing key one level down
>>> d                            # display result
DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})

اشیای Counter

یک ابزار شمارنده برای پشتیبانی از شمارش‌های آسان و سریع فراهم شده است. برای مثال:

>>> # Tally occurrences of words in a list
>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
...     cnt[word] += 1
...
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})

>>> # Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
 ('you', 554),  ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]
class collections.Counter(**kwargs)
class collections.Counter(iterable, /, **kwargs)
class collections.Counter(mapping, /, **kwargs)

یک Counter زیرکلاسی از dict برای شمارش اشیای hashable است. این مجموعه‌ای است که در آن عناصر به‌عنوان کلیدهای دیکشنری ذخیره می‌شوند و تعداد آن‌ها به‌عنوان مقادیر دیکشنری ذخیره می‌شود. تعدادها می‌توانند هر مقدار عدد صحیحی باشند، از جمله صفر یا تعدادهای منفی. کلاس Counter مشابه کیسه‌ها (bags) یا چندمجموعه‌ها (multisets) در زبان‌های دیگر است.

عناصر از یک پیمایش‌پذیر شمارش می‌شوند یا از یک نگاشت (یا شمارنده) دیگر مقداردهی اولیه می‌شوند:

>>> c = Counter()                           # a new, empty counter
>>> c = Counter('gallahad')                 # a new counter from an iterable
>>> c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
>>> c = Counter(cats=4, dogs=8)             # a new counter from keyword args

اشیای Counter یک رابط دیکشنری دارند، با این تفاوت که برای آیتم‌های ناموجود، به‌جای پرتاب KeyError، شمارش صفر برمی‌گردانند:

>>> c = Counter(['eggs', 'ham'])
>>> c['bacon']                              # count of a missing element is zero
0

تنظیم یک شمارش روی صفر، یک عنصر را از شمارنده حذف نمی‌کند. برای حذف کامل آن از del استفاده کنید:

>>> c['sausage'] = 0                        # counter entry with a zero count
>>> del c['sausage']                        # del actually removes the entry

اضافه شده در نسخه‌ی 3.1.

تغییر یافته در نسخه‌ی 3.7: به‌عنوان یک زیرکلاس از dict، Counter قابلیت به‌خاطر سپردن ترتیب درج را به ارث برده است. عملیات‌های ریاضی روی اشیای Counter نیز ترتیب را حفظ می‌کنند. نتایج بر اساس نخستین زمان مواجهه با هر عنصر در عملوند چپ و سپس بر اساس ترتیب مواجهه در عملوند راست مرتب می‌شوند.

اشیای Counter علاوه بر متدهای در دسترس برای همه دیکشنری‌ها، از متدهای اضافی نیز پشتیبانی می‌کنند:

elements()

یک پیمایش‌گر بر روی عناصر برمی‌گرداند که هر عنصر را به تعداد آن تکرار می‌کند. عناصر به ترتیبی که برای اولین بار مشاهده شده‌اند برگردانده می‌شوند. اگر تعداد یک عنصر کمتر از ۱ باشد، elements() آن را نادیده می‌گیرد.

>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> sorted(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']
most_common(n=None)

فهرستی از رایج‌ترین n عنصر و تعداد آن‌ها را از رایج‌ترین به کم‌ترین برمی‌گرداند. اگر n حذف شود یا None باشد، most_common() تمام عناصر موجود در شمارنده را برمی‌گرداند. عناصری که تعداد برابر دارند، به ترتیبی که برای اولین بار مشاهده شده‌اند مرتب می‌شوند:

>>> Counter('abracadabra').most_common(3)
[('a', 5), ('b', 2), ('r', 2)]
subtract(**kwargs)
subtract(iterable, /, **kwargs)
subtract(mapping, /, **kwargs)

عناصر از یک پیمایش‌پذیر یا از یک نگاشت دیگر (یا شمارنده) کم می‌شوند. مانند dict.update() است، اما به‌جای جایگزینی شمارش‌ها، آن‌ها را کم می‌کند. هم ورودی‌ها و هم خروجی‌ها می‌توانند صفر یا منفی باشند.

>>> 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})

اضافه شده در نسخه‌ی 3.2.

total()

مجموع شمارش‌ها را محاسبه کنید.

>>> c = Counter(a=10, b=5, c=0)
>>> c.total()
15

اضافه شده در نسخه‌ی 3.10.

متدهای معمول دیکشنری برای اشیای Counter در دسترس هستند، به‌جز دو مورد که برای شمارنده‌ها متفاوت عمل می‌کنند.

fromkeys(iterable)

این متد کلاس برای اشیای Counter پیاده‌سازی نشده است.

update(**kwargs)
update(iterable, /, **kwargs)
update(mapping, /, **kwargs)

المان‌ها از یک پیمایش‌پذیر شمرده می‌شوند یا از یک نگاشت (یا شمارنده) دیگر افزوده می‌شوند. مانند dict.update() است، اما به‌جای جایگزین کردن شمارش‌ها، آن‌ها را می‌افزاید. همچنین، انتظار می‌رود پیمایش‌پذیر دنباله‌ای از المان‌ها باشد، نه دنباله‌ای از جفت‌های (key, value).

شمارنده‌ها از عملگرهای مقایسه‌ای غنی برای روابط برابری، زیرمجموعه و ابرمجموعه پشتیبانی می‌کنند: ==، !=، <، <=، >، >=. همه‌ی این مقایسه‌ها عناصر ناموجود را دارای تعداد صفر در نظر می‌گیرند، به‌طوری که Counter(a=1) == Counter(a=1, b=0) مقدار درست برمی‌گرداند.

تغییر یافته در نسخه‌ی 3.10: عملیات‌های مقایسه غنی افزوده شدند.

تغییر یافته در نسخه‌ی 3.10: در آزمون‌های برابری، عناصر غایب به‌عنوان دارای تعداد صفر در نظر گرفته می‌شوند. پیش از این، Counter(a=3) و Counter(a=3, b=0) متمایز در نظر گرفته می‌شدند.

الگوهای رایج برای کار با اشیای Counter:

c.total()                       # total of all counts
c.clear()                       # reset all counts
list(c)                         # list unique elements
set(c)                          # convert to a set
dict(c)                         # convert to a regular dictionary
c.items()                       # access the (elem, cnt) pairs
Counter(dict(list_of_pairs))    # convert from a list of (elem, cnt) pairs
c.most_common()[:-n-1:-1]       # n least common elements
+c                              # remove zero and negative counts

چند عملیات ریاضی برای ترکیب اشیای Counter و تولید چندمجموعه‌ها (شمارنده‌هایی که شمارش‌های بزرگ‌تر از صفر دارند) ارائه شده است. جمع و تفریق، شمارنده‌ها را با افزودن یا کم کردن شمارش‌های عناصر متناظر ترکیب می‌کنند. اشتراک و اجتماع، کمینه و بیشینه‌ی شمارش‌های متناظر را برمی‌گردانند. برابری و شمول، شمارش‌های متناظر را مقایسه می‌کنند. هر عملیات می‌تواند ورودی‌هایی با شمارش‌های علامت‌دار بپذیرد، اما خروجی، نتایجی را که شمارش آن‌ها صفر یا کمتر است شامل نمی‌شود.

>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d                       # add two counters together:  c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d                       # subtract (keeping only positive counts)
Counter({'a': 2})
>>> c & d                       # intersection:  min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>> c | d                       # union:  max(c[x], d[x])
Counter({'a': 3, 'b': 2})
>>> c == d                      # equality:  c[x] == d[x]
False
>>> c <= d                      # inclusion:  c[x] <= d[x]
False

جمع و تفریق یک‌عملوندی، میان‌برهایی برای افزودن یک شمارنده خالی یا کم کردن از یک شمارنده خالی هستند.

>>> c = Counter(a=2, b=-4)
>>> +c
Counter({'a': 2})
>>> -c
Counter({'b': 4})

اضافه شده در نسخه‌ی 3.3: پشتیبانی از عملگرهای یک‌عملوندی مثبت و منفی و عملیات‌های چندمجموعه‌ای درجا افزوده شد.

توجه

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

  • خود کلاس Counter زیرکلاسی از دیکشنری است و هیچ محدودیتی روی کلیدها و مقادیر آن ندارد. مقادیر در نظر گرفته شده‌اند که اعدادی برای نمایش شمارش‌ها باشند، اما شما می‌توانید هر چیزی را در فیلد مقدار ذخیره کنید.

  • متد most_common() تنها نیاز دارد که مقادیر قابل مرتب‌سازی باشند.

  • برای عملیات‌های درجا مانند c[key] += 1، نوع مقدار فقط باید از جمع و تفریق پشتیبانی کند. بنابراین کسرها، اعداد اعشاری و اعداد صحیح قابل استفاده هستند و مقادیر منفی نیز پشتیبانی می‌شوند. همین موضوع برای update() و subtract() نیز صادق است، که مقادیر منفی و صفر را برای هر دو ورودی و خروجی می‌پذیرند.

  • متدهای چندمجموعه فقط برای موارد استفاده با مقادیر مثبت طراحی شده‌اند. ورودی‌ها ممکن است منفی یا صفر باشند، اما فقط خروجی‌هایی با مقادیر مثبت ایجاد می‌شوند. هیچ محدودیت نوعی وجود ندارد، اما نوع مقدار باید از جمع، تفریق و مقایسه پشتیبانی کند.

  • متد elements() به شمارش‌های عدد صحیح نیاز دارد. این متد شمارش‌های صفر و منفی را نادیده می‌گیرد.

همچنین ملاحظه نمائید

  • کلاس Bag در Smalltalk.

  • مدخل ویکی‌پدیا برای چندمجموعه‌ها.

  • آموزش چندمجموعه‌های C++ همراه با مثال‌ها.

  • برای عملیات ریاضی بر روی چندمجموعه‌ها و موارد استفاده‌ی آن‌ها، Knuth, Donald. The Art of Computer Programming Volume II, Section 4.6.3, Exercise 19 را ببینید.

  • برای برشمردن تمام چندمجموعه‌های متمایز با اندازه‌ی مشخص بر روی یک مجموعه‌ی مشخص از عناصر، itertools.combinations_with_replacement() را ببینید:

    map(Counter, combinations_with_replacement('ABC', 2)) # --> AA AB AC BB BC CC
    

اشیای deque

class collections.deque([iterable[, maxlen]])

یک شیء deque جدید بازمی‌گرداند که از چپ به راست (با استفاده از append()) با داده‌های iterable مقداردهی اولیه شده است. اگر iterable مشخص نشده باشد، deque جدید خالی است.

صف‌های دوطرفه (deque) تعمیمی از پشته‌ها و صف‌ها هستند (این نام به‌صورت «deck» تلفظ می‌شود و کوتاه‌شده‌ی «double-ended queue» است). صف‌های دوطرفه از افزودن و برداشتن ایمن برای نخ‌ها و کارآمد از نظر حافظه از هر طرف صف دوطرفه، با کارایی تقریباً یکسان O(1) در هر جهت پشتیبانی می‌کنند.

اگرچه اشیای list از عملیات مشابهی پشتیبانی می‌کنند، اما برای عملیات سریع با طول ثابت بهینه‌سازی شده‌اند و برای عملیات pop(0) و insert(0, v) که هم اندازه و هم موقعیت نمایش داده‌های زیرین را تغییر می‌دهند، مستلزم هزینه‌های جابه‌جایی حافظه با مرتبه‌ی O(n) هستند.

اگر maxlen مشخص نشده باشد یا None باشد، صف‌های دوطرفه (deque) می‌توانند تا طول دلخواهی رشد کنند. در غیر این صورت، صف دوطرفه به حداکثر طول مشخص‌شده محدود می‌شود. هنگامی که یک صف دوطرفه با طول محدود پر شد، با افزودن آیتم‌های جدید، تعداد متناظری از آیتم‌ها از سمت مخالف دور ریخته می‌شوند. صف‌های دوطرفه با طول محدود، عملکردی مشابه فیلتر tail در Unix ارائه می‌دهند. آن‌ها همچنین برای پیگیری تراکنش‌ها و سایر مخازن داده‌ای که تنها جدیدترین فعالیت مورد توجه است، مفید هستند.

صف‌های دوطرفه (deque) نسبت به نوع محتوای خود عام هستند.

اشیای Deque از متدهای زیر پشتیبانی می‌کنند:

append(item, /)

item را به سمت راست deque می‌افزاید.

appendleft(item, /)

item را به سمت چپ deque اضافه کنید.

clear()

همه‌ی عناصر را از صف دوطرفه (deque) حذف می‌کند و طول آن را به ۰ می‌رساند.

copy()

یک کپی سطحی از deque ایجاد می‌کند.

اضافه شده در نسخه‌ی 3.5.

count(value, /)

تعداد عناصر deque برابر با value را می‌شمارد.

اضافه شده در نسخه‌ی 3.2.

extend(iterable, /)

سمت راست deque را با افزودن المان‌ها از آرگومان پیمایش‌پذیر گسترش دهید.

extendleft(iterable, /)

سمت چپ صف دوطرفه (deque) را با الحاق عناصری از iterable گسترش دهید. توجه داشته باشید که دنباله‌ی الحاق‌های سمت چپ، باعث معکوس شدن ترتیب عناصر در آرگومان پیمایش‌پذیر می‌شود.

index(value[, start[, stop]])

موقعیت value را در صف دوطرفه (deque) برمی‌گرداند (در اندیس start یا پس از آن و پیش از اندیس stop). نخستین تطابق را برمی‌گرداند یا در صورت پیدا نشدن، ValueError را پرتاب می‌کند.

اضافه شده در نسخه‌ی 3.5.

insert(index, value, /)

value را در موقعیت index در صف دوطرفه (deque) درج کنید.

اگر درج موجب شود که یک deque کران‌دار بزرگ‌تر از maxlen شود، یک IndexError پرتاب می‌شود.

اضافه شده در نسخه‌ی 3.5.

pop()

یک المان را از سمت راست deque حذف کرده و برمی‌گرداند. اگر هیچ المانی وجود نداشته باشد، یک IndexError پرتاب می‌شود.

popleft()

یک عنصر را از سمت چپ deque حذف می‌کند و آن را برمی‌گرداند. اگر هیچ عنصری وجود نداشته باشد، یک IndexError پرتاب می‌شود.

remove(value, /)

اولین رخداد value را حذف می‌کند. اگر پیدا نشد، یک ValueError پرتاب می‌کند.

reverse()

عناصر deque را به‌صورت درجا معکوس می‌کند و سپس None را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.2.

rotate(n=1, /)

deque را n گام به راست بچرخانید. اگر n منفی باشد، به چپ بچرخانید.

هنگامی که deque خالی نیست، چرخاندن یک گام به راست معادل d.appendleft(d.pop()) است، و چرخاندن یک گام به چپ معادل d.append(d.popleft()) است.

اشیای Deque همچنین یک ویژگی فقط‌خواندنی ارائه می‌دهند:

maxlen

حداکثر اندازه‌ی یک deque یا None در صورت نامحدود بودن.

اضافه شده در نسخه‌ی 3.1.

علاوه بر موارد بالا، صف‌های دوطرفه (deques) از تکرار، پیکل‌کردن، len(d)، reversed(d)، copy.copy(d)، copy.deepcopy(d)، بررسی عضویت با عملگر in، و ارجاع‌های اندیسی مانند d[0] برای دسترسی به اولین عنصر پشتیبانی می‌کنند. دسترسی اندیسی در هر دو انتها O(1) است، اما در میانه به O(n) کند می‌شود. برای دسترسی تصادفی سریع، به‌جای آن از فهرست‌ها استفاده کنید.

از نسخه 3.5 به بعد، صف‌های دوطرفه (deque) از __add__()، __mul__() و __imul__() پشتیبانی می‌کنند.

مثال:

>>> from collections import deque
>>> d = deque('ghi')                 # make a new deque with three items
>>> for elem in d:                   # iterate over the deque's elements
...     print(elem.upper())
G
H
I

>>> d.append('j')                    # add a new entry to the right side
>>> d.appendleft('f')                # add a new entry to the left side
>>> d                                # show the representation of the deque
deque(['f', 'g', 'h', 'i', 'j'])

>>> d.pop()                          # return and remove the rightmost item
'j'
>>> d.popleft()                      # return and remove the leftmost item
'f'
>>> list(d)                          # list the contents of the deque
['g', 'h', 'i']
>>> d[0]                             # peek at leftmost item
'g'
>>> d[-1]                            # peek at rightmost item
'i'

>>> list(reversed(d))                # list the contents of a deque in reverse
['i', 'h', 'g']
>>> 'h' in d                         # search the deque
True
>>> d.extend('jkl')                  # add multiple elements at once
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> d.rotate(1)                      # right rotation
>>> d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
>>> d.rotate(-1)                     # left rotation
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])

>>> deque(reversed(d))               # make a new deque in reverse order
deque(['l', 'k', 'j', 'i', 'h', 'g'])
>>> d.clear()                        # empty the deque
>>> d.pop()                          # cannot pop from an empty deque
Traceback (most recent call last):
    File "<pyshell#6>", line 1, in -toplevel-
        d.pop()
IndexError: pop from an empty deque

>>> d.extendleft('abc')              # extendleft() reverses the input order
>>> d
deque(['c', 'b', 'a'])

دستور پخت‌های deque

این بخش روش‌های مختلفی را برای کار با صف‌های دوطرفه (deque) نشان می‌دهد.

صف‌های دوطرفه (deque) با طول محدود، عملکردی مشابه فیلتر tail در یونیکس فراهم می‌کنند:

def tail(filename, n=10):
    'Return the last n lines of a file'
    with open(filename) as f:
        return deque(f, n)

رویکرد دیگر برای استفاده از صف‌های دوطرفه (deque)، نگهداری دنباله‌ای از المان‌های به‌تازگی اضافه‌شده با افزودن به راست و برداشتن از چپ است:

def moving_average(iterable, n=3):
    # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
    # https://en.wikipedia.org/wiki/Moving_average
    it = iter(iterable)
    d = deque(itertools.islice(it, n-1))
    d.appendleft(0)
    s = sum(d)
    for elem in it:
        s += elem - d.popleft()
        d.append(elem)
        yield s / n

A round-robin scheduler can be implemented with input iterators stored in a deque. Values are yielded from the active iterator in position zero. If that iterator is exhausted, it can be removed with popleft(); otherwise, it can be cycled back to the end with the rotate() method:

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    iterators = deque(map(iter, iterables))
    while iterators:
        try:
            while True:
                yield next(iterators[0])
                iterators.rotate(-1)
        except StopIteration:
            # Remove an exhausted iterator.
            iterators.popleft()

متد rotate() راهی برای پیاده‌سازی اسلایس و حذف deque فراهم می‌کند. برای مثال، یک پیاده‌سازی پایتون خالص از del d[n] برای قرار دادن عناصر در موقعیت مناسب جهت خارج کردن، به متد rotate() متکی است:

def delete_nth(d, n):
    d.rotate(-n)
    d.popleft()
    d.rotate(n)

برای پیاده‌سازی اسلایس deque، از رویکرد مشابهی با اعمال rotate() استفاده کنید تا یک عنصر هدف به سمت چپ deque برسد. آیتم‌های قدیمی را با popleft() حذف کنید، آیتم‌های جدید را با extend() اضافه کنید و سپس چرخش را معکوس کنید. با تغییرات جزئی در این رویکرد، پیاده‌سازی دستکاری‌های پشته به سبک Forth مانند dup، drop، swap، over، pick، rot و roll آسان است.

اشیای defaultdict

class collections.defaultdict(default_factory=None, /, **kwargs)
class collections.defaultdict(default_factory, mapping, /, **kwargs)
class collections.defaultdict(default_factory, iterable, /, **kwargs)

یک شیء دیکشنری‌مانند جدید برمی‌گرداند. defaultdict زیرکلاسی از کلاس توکار dict است. این کلاس یک متد را بازتعریف می‌کند و یک متغیر نمونه قابل‌نوشتن اضافه می‌کند. سایر قابلیت‌ها مانند کلاس dict هستند و در اینجا مستند نشده‌اند.

نخستین آرگومان مقدار اولیه‌ی ویژگی default_factory را فراهم می‌کند؛ مقدار پیش‌فرض آن None است. با تمام آرگومان‌های باقی‌مانده همان‌گونه رفتار می‌شود که گویی به سازنده‌ی dict ارسال شده باشند، از جمله آرگومان‌های کلیدواژه‌ای.

defaultdictها نسبت به دو نوع عام هستند که (به‌ترتیب) بیانگر انواع کلیدها و مقادیر دیکشنری هستند.

اشیای defaultdict علاوه بر عملیات استاندارد dict، از متد زیر نیز پشتیبانی می‌کنند:

__missing__(key, /)

اگر ویژگی default_factory برابر None باشد، این عمل یک استثنای KeyError را با key به‌عنوان آرگومان پرتاب می‌کند.

اگر default_factory برابر None نباشد، بدون آرگومان فراخوانی می‌شود تا مقدار پیش‌فرضی برای کلید داده‌شده فراهم کند؛ این مقدار در دیکشنری برای کلید درج می‌شود و برگردانده می‌شود.

اگر فراخوانی default_factory باعث پرتاب استثنایی شود، این استثنا بدون تغییر انتشار می‌یابد.

این متد توسط متد __getitem__() از کلاس dict زمانی فراخوانی می‌شود که کلید درخواست‌شده یافت نشود؛ هر آنچه برگرداند یا پرتاب کند، سپس توسط __getitem__() برگردانده یا پرتاب می‌شود.

توجه داشته باشید که __missing__() برای هیچ عملیاتی به جز __getitem__() فراخوانی نمی‌شود. این بدان معناست که get() مانند دیکشنری‌های معمولی، به جای استفاده از default_factory، None را به‌عنوان مقدار پیش‌فرض برمی‌گرداند.

اشیای defaultdict از متغیر نمونه‌ی زیر پشتیبانی می‌کنند:

default_factory

این ویژگی توسط متد __missing__() استفاده می‌شود؛ در صورت وجود اولین آرگومان سازنده، از آن مقداردهی اولیه می‌شود و در غیر این صورت به None مقداردهی اولیه می‌شود.

تغییر یافته در نسخه‌ی 3.9: عملگرهای ادغام (|) و به‌روزرسانی (|=)، مشخص‌شده در PEP 584، افزوده شدند.

مثال‌های defaultdict

با استفاده از list به‌عنوان default_factory، به‌آسانی می‌توان دنباله‌ای از جفت‌های کلید-مقدار را در یک دیکشنری از فهرست‌ها گروه‌بندی کرد:

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

هنگامی که هر کلید برای نخستین بار مشاهده می‌شود، از قبل در نگاشت وجود ندارد؛ بنابراین یک آیتم به‌طور خودکار با استفاده از تابع default_factory ایجاد می‌شود که یک list خالی برمی‌گرداند. سپس عملیات list.append() مقدار را به فهرست جدید اضافه می‌کند. هنگامی که کلیدها دوباره مشاهده می‌شوند، جست‌وجو به‌طور عادی انجام می‌شود (فهرست مربوط به آن کلید را برمی‌گرداند) و عملیات list.append() مقدار دیگری را به فهرست اضافه می‌کند. این روش ساده‌تر و سریع‌تر از روش معادلی است که از dict.setdefault() استفاده می‌کند:

>>> d = {}
>>> for k, v in s:
...     d.setdefault(k, []).append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

با تنظیم default_factory روی int، defaultdict برای شمارش مفید می‌شود (مانند bag یا multiset در زبان‌های دیگر):

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> sorted(d.items())
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]

هنگامی که برای نخستین بار با حرفی مواجه می‌شوید، آن حرف در نگاشت وجود ندارد، بنابراین تابع default_factory، تابع int() را فراخوانی می‌کند تا یک شمارش پیش‌فرض برابر با صفر فراهم کند. سپس عملیات افزایش، شمارش هر حرف را به‌تدریج افزایش می‌دهد.

تابع int() که همیشه صفر را برمی‌گرداند، تنها حالت خاصی از توابع ثابت است. راهی سریع‌تر و انعطاف‌پذیرتر برای ایجاد توابع ثابت، استفاده از یک تابع لامبدا است که می‌تواند هر مقدار ثابتی را ارائه کند (نه فقط صفر):

>>> def constant_factory(value):
...     return lambda: value
...
>>> d = defaultdict(constant_factory('<missing>'))
>>> d.update(name='John', action='ran')
>>> '%(name)s %(action)s to %(object)s' % d
'John ran to <missing>'

با تنظیم default_factory روی set، defaultdict برای ساختن یک دیکشنری از مجموعه‌ها مفید می‌شود:

>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
>>> d = defaultdict(set)
>>> for k, v in s:
...     d[k].add(v)
...
>>> sorted(d.items())
[('blue', {2, 4}), ('red', {1, 3})]

namedtuple() تابع کارخانه برای تاپل‌های دارای فیلدهای نام‌دار

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

collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)

یک زیرکلاس جدید از تاپل به نام typename برمی‌گرداند. زیرکلاس جدید برای ایجاد اشیایی شبیه به تاپل به کار می‌رود که فیلدهایی قابل دسترسی از طریق جست‌وجوی ویژگی دارند و همچنین قابل اندیس‌گذاری و پیمایش‌پذیر هستند. نمونه‌های این زیرکلاس همچنین یک رشته مستند مفید (شامل typename و field_names) و یک متد مفید __repr__() دارند که محتویات تاپل را در قالب name=value فهرست می‌کند.

field_names دنباله‌ای از رشته‌ها مانند ['x', 'y'] است. به‌عنوان جایگزین، field_names می‌تواند یک رشته واحد باشد که در آن هر نام فیلد با فضای خالی و/یا کاما جدا شده باشد، برای مثال 'x y' یا 'x, y'.

هر شناسه معتبر پایتون را می‌توان برای نام فیلد به کار برد، به‌جز نام‌هایی که با زیرخط شروع می‌شوند. شناسه‌های معتبر از حروف، ارقام و زیرخط تشکیل می‌شوند، اما با رقم یا زیرخط شروع نمی‌شوند و نمی‌توانند یک keyword مانند class، for، return، global، pass یا raise باشند.

اگر rename مقدار true داشته باشد، نام‌های فیلد نامعتبر به‌طور خودکار با نام‌های جایگاهی جایگزین می‌شوند. برای مثال، ['abc', 'def', 'ghi', 'abc'] به ['abc', '_1', 'ghi', '_3'] تبدیل می‌شود و کلیدواژه def و نام فیلد تکراری abc حذف می‌شوند.

defaults می‌تواند None یا یک پیمایش‌پذیر از مقادیر پیش‌فرض باشد. از آن‌جا که فیلدهای دارای مقدار پیش‌فرض باید بعد از فیلدهای بدون مقدار پیش‌فرض بیایند، defaults به راست‌ترین پارامترها اعمال می‌شود. برای مثال، اگر نام فیلدها ['x', 'y', 'z'] و مقادیر پیش‌فرض (1, 2) باشند، x یک آرگومان ضروری خواهد بود، مقدار پیش‌فرض y برابر 1 خواهد بود، و مقدار پیش‌فرض z برابر 2 خواهد بود.

اگر module تعریف شده باشد، ویژگی __module__ تاپل نام‌دار (named tuple) برابر آن مقدار قرار می‌گیرد.

نمونه‌های تاپل نام‌دار، دیکشنری‌های به‌ازای هر نمونه ندارند، بنابراین سبک هستند و به حافظه بیشتری نسبت به تاپل‌های معمولی نیاز ندارند.

برای پشتیبانی از پیکل‌کردن، کلاس تاپل نام‌دار (named tuple) باید به متغیری اختصاص داده شود که با typename مطابقت داشته باشد.

تغییر یافته در نسخه‌ی 3.1: پشتیبانی از rename افزوده شد.

تغییر یافته در نسخه‌ی 3.6: پارامترهای verbose و rename به آرگومان‌های فقط کلیدواژه‌ای تبدیل شدند.

تغییر یافته در نسخه‌ی 3.6: پارامتر module اضافه شد.

تغییر یافته در نسخه‌ی 3.7: پارامتر verbose و ویژگی _source حذف شدند.

تغییر یافته در نسخه‌ی 3.7: پارامتر defaults و ویژگی _field_defaults اضافه شد.

>>> # Basic example
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(11, y=22)     # instantiate with positional or keyword arguments
>>> p[0] + p[1]             # indexable like the plain tuple (11, 22)
33
>>> x, y = p                # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y               # fields also accessible by name
33
>>> p                       # readable __repr__ with a name=value style
Point(x=11, y=22)

تاپل‌های نام‌دار به‌ویژه برای اختصاص نام‌های فیلد به تاپل‌های نتیجه‌ای که از ماژول‌های csv یا sqlite3 بازگردانده می‌شوند، مفید هستند:

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
    print(emp.name, emp.title)

import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
    print(emp.name, emp.title)

علاوه بر متدهای به ارث برده‌شده از تاپل‌ها، تاپل‌های نام‌دار از سه متد و دو ویژگی اضافی پشتیبانی می‌کنند. برای جلوگیری از تداخل با نام فیلدها، نام متدها و ویژگی‌ها با یک زیرخط شروع می‌شوند.

classmethod somenamedtuple._make(iterable, /)

متد کلاسی که یک نمونه جدید را از یک دنباله یا پیمایش‌پذیر موجود می‌سازد.

>>> t = [11, 22]
>>> Point._make(t)
Point(x=11, y=22)
somenamedtuple._asdict()

یک dict جدید برمی‌گرداند که نام فیلدها را به مقادیر متناظر آن‌ها نگاشت می‌کند:

>>> p = Point(x=11, y=22)
>>> p._asdict()
{'x': 11, 'y': 22}

تغییر یافته در نسخه‌ی 3.1: یک OrderedDict به‌جای یک dict معمولی برمی‌گرداند.

تغییر یافته در نسخه‌ی 3.8: یک dict معمولی را به‌جای یک OrderedDict بازمی‌گرداند. از پایتون 3.7 به بعد، ترتیب دیکشنری‌های معمولی تضمین شده است. اگر امکانات اضافی OrderedDict مورد نیاز باشد، راه‌حل پیشنهادی، تبدیل نتیجه به نوع دلخواه است: OrderedDict(nt._asdict()).

somenamedtuple._replace(**kwargs)

یک نمونه جدید از تاپل نام‌دار (named tuple) برمی‌گرداند که در آن فیلدهای مشخص‌شده با مقدارهای جدید جایگزین شده‌اند:

>>> p = Point(x=11, y=22)
>>> p._replace(x=33)
Point(x=33, y=22)

>>> for partnum, record in inventory.items():
...     inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())

تابع عام copy.replace() نیز از تاپل‌های نام‌دار (named tuples) پشتیبانی می‌کند.

تغییر یافته در نسخه‌ی 3.13: برای آرگومان‌های کلیدواژه‌ای نامعتبر، به‌جای ValueError، TypeError ایجاد می‌کند.

somenamedtuple._fields

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

>>> p._fields            # view the field names
('x', 'y')

>>> Color = namedtuple('Color', 'red green blue')
>>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
>>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)
somenamedtuple._field_defaults

دیکشنری‌ای که نام فیلدها را به مقادیر پیش‌فرض نگاشت می‌کند.

>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
>>> Account._field_defaults
{'balance': 0}
>>> Account('premium')
Account(type='premium', balance=0)

برای بازیابی فیلدی که نام آن در یک رشته ذخیره‌شده است، از تابع getattr() استفاده کنید:

>>> getattr(p, 'x')
11

برای تبدیل یک دیکشنری به یک تاپل نام‌دار (named tuple)، از عملگر دو ستاره‌ای (double-star-operator) استفاده کنید (همان‌طور که در واگشایی آرگومان‌ها توضیح داده شده است):

>>> d = {'x': 11, 'y': 22}
>>> Point(**d)
Point(x=11, y=22)

از آن‌جا که تاپل نام‌دار (named tuple) یک کلاس معمولی پایتون است، افزودن یا تغییر قابلیت با یک زیرکلاس آسان است. در این‌جا نحوه افزودن یک فیلد محاسبه‌شده و یک قالب چاپ با عرض ثابت آمده است:

>>> class Point(namedtuple('Point', ['x', 'y'])):
...     __slots__ = ()
...     @property
...     def hypot(self):
...         return (self.x ** 2 + self.y ** 2) ** 0.5
...     def __str__(self):
...         return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)

>>> for p in Point(3, 4), Point(14, 5/7):
...     print(p)
Point: x= 3.000  y= 4.000  hypot= 5.000
Point: x=14.000  y= 0.714  hypot=14.018

زیرکلاسی که در بالا نشان داده شد، __slots__ را برابر با یک تاپل خالی قرار می‌دهد. این کار با جلوگیری از ایجاد دیکشنری‌های نمونه‌ها، به پایین نگه داشتن میزان حافظه مورد نیاز کمک می‌کند.

زیرکلاس‌سازی برای افزودن فیلدهای ذخیره‌شده‌ی جدید مفید نیست. در عوض، به‌سادگی یک نوع جدید named tuple از ویژگی _fields ایجاد کنید:

>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))

می‌توانید رشته مستندات را با انتساب مستقیم به فیلدهای __doc__ سفارشی کنید:

>>> Book = namedtuple('Book', ['id', 'title', 'authors'])
>>> Book.__doc__ += ': Hardcover book in active collection'
>>> Book.id.__doc__ = '13-digit ISBN'
>>> Book.title.__doc__ = 'Title of first printing'
>>> Book.authors.__doc__ = 'List of authors sorted by last name'

تغییر یافته در نسخه‌ی 3.5: رشته‌مستندهای پراپرتی قابل‌نوشتن شدند.

همچنین ملاحظه نمائید

  • برای روشی جهت افزودن راهنمای نوع به تاپل‌های نام‌دار، typing.NamedTuple را ببینید. این کلاس همچنین یک نمادگذاری آراسته با استفاده از کلیدواژه‌ی class ارائه می‌کند:

    class Component(NamedTuple):
        part_number: int
        weight: float
        description: Optional[str] = None
    
  • برای یک فضای نام تغییرپذیر که به‌جای یک تاپل، مبتنی بر یک دیکشنری زیربنایی است، types.SimpleNamespace() را ببینید.

  • ماژول dataclasses یک دکوراتور و توابعی را برای افزودن خودکار متدهای ویژه‌ی تولیدشده به کلاس‌های تعریف‌شده توسط کاربر فراهم می‌کند.

اشیای OrderedDict

دیکشنری‌های ترتیب‌دار دقیقاً مانند دیکشنری‌های معمولی هستند، اما قابلیت‌های اضافی مربوط به عملیات ترتیب‌دهی دارند. اکنون که کلاس توکار dict توانایی به‌خاطر سپردن ترتیب درج را به دست آورده است، اهمیت کمتری یافته‌اند (این رفتار جدید در Python 3.7 تضمین شد).

هنوز برخی تفاوت‌ها با dict باقی مانده‌اند:

  • dict معمولی طراحی شده است تا در عملیات نگاشت بسیار کارآمد باشد. پیگیری ترتیب درج، اولویت دوم بود.

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

  • الگوریتم OrderedDict می‌تواند عملیات مکرر بازچینش را بهتر از dict مدیریت کند. همان‌طور که در دستورات زیر نشان داده شده است، این امر آن را برای پیاده‌سازی انواع مختلفی از نهانگاه‌های LRU مناسب می‌سازد.

  • عملیات برابری برای OrderedDict یکسان بودن ترتیب را بررسی می‌کند.

    یک dict معمولی می‌تواند آزمون برابری حساس به ترتیب را با p == q and all(k1 == k2 for k1, k2 in zip(p, q)) شبیه‌سازی کند.

  • متد popitem() در OrderedDict امضای متفاوتی دارد. این متد یک آرگومان اختیاری می‌پذیرد تا مشخص کند کدام آیتم خارج می‌شود.

    یک dict معمولی می‌تواند od.popitem(last=True) مربوط به OrderedDict را با d.popitem() شبیه‌سازی کند، که تضمین می‌شود آیتم سمت راست (آخرین آیتم) را خارج کند.

    یک dict معمولی می‌تواند od.popitem(last=False) مربوط به OrderedDict را با (k := next(iter(d)), d.pop(k)) شبیه‌سازی کند، که چپ‌ترین (نخستین) آیتم را در صورت وجود برمی‌گرداند و حذف می‌کند.

  • OrderedDict یک متد move_to_end() برای جابه‌جایی کارآمد یک عنصر به یک پایانه دارد.

    یک dict معمولی می‌تواند od.move_to_end(k, last=True) در OrderedDict را با d[k] = d.pop(k) شبیه‌سازی کند، که کلید و مقدار مرتبط با آن را به جایگاه انتهایی (آخرین) منتقل می‌کند.

    یک dict معمولی معادل کارآمدی برای od.move_to_end(k, last=False) در OrderedDict ندارد که کلید و مقدار مرتبط با آن را به چپ‌ترین (اولین) جایگاه منتقل می‌کند.

  • تا پیش از پایتون 3.8، dict فاقد متد __reversed__() بود.

class collections.OrderedDict(**kwargs)
class collections.OrderedDict(mapping, /, **kwargs)
class collections.OrderedDict(iterable, /, **kwargs)

نمونه‌ای از یک زیرکلاس dict برمی‌گرداند که دارای متدهایی اختصاصی برای بازآرایی ترتیب دیکشنری است.

اضافه شده در نسخه‌ی 3.1.

popitem(last=True)

متد popitem() برای دیکشنری‌های ترتیب‌دار یک جفت (کلید، مقدار) را برمی‌گرداند و حذف می‌کند. اگر last درست باشد، جفت‌ها به ترتیب LIFO و اگر نادرست باشد، به ترتیب FIFO برگردانده می‌شوند.

move_to_end(key, last=True)

یک key موجود را به یکی از دو انتهای یک دیکشنری ترتیب‌دار منتقل می‌کند. اگر last برابر true باشد (پیش‌فرض)، آیتم به انتهای سمت راست منتقل می‌شود و اگر last برابر false باشد، به ابتدا منتقل می‌شود. در صورتی که key وجود نداشته باشد، KeyError پرتاب می‌شود:

>>> d = OrderedDict.fromkeys('abcde')
>>> d.move_to_end('b')
>>> ''.join(d)
'acdeb'
>>> d.move_to_end('b', last=False)
>>> ''.join(d)
'bacde'

اضافه شده در نسخه‌ی 3.2.

علاوه بر متدهای معمول نگاشت، دیکشنری‌های ترتیبی نیز از پیمایش معکوس با استفاده از reversed() پشتیبانی می‌کنند.

آزمون‌های برابری میان اشیای OrderedDict به ترتیب حساس هستند و تقریباً معادل list(od1.items())==list(od2.items()) هستند.

آزمون‌های برابری بین اشیای OrderedDict و سایر اشیای Mapping مانند دیکشنری‌های معمولی، نسبت به ترتیب حساس نیستند. این امر امکان می‌دهد که اشیای OrderedDict در هر جایی که از یک دیکشنری معمولی استفاده می‌شود، جایگزین شوند.

تغییر یافته در نسخه‌ی 3.5: نماهای آیتم‌ها، کلیدها و مقادیر OrderedDict اکنون از پیمایش معکوس با استفاده از reversed() پشتیبانی می‌کنند.

تغییر یافته در نسخه‌ی 3.6: با پذیرش PEP 468، ترتیب برای آرگومان‌های کلیدواژه‌ای ارسال‌شده به سازنده‌ی OrderedDict و متد update() آن حفظ می‌شود.

تغییر یافته در نسخه‌ی 3.9: عملگرهای ادغام (|) و به‌روزرسانی (|=)، مشخص‌شده در PEP 584، افزوده شدند.

OrderedDict مثال‌ها و دستورهای پخت

ایجاد گونه‌ای از دیکشنری مرتب که ترتیب آخرین بار درج کلیدها را به خاطر می‌آورد، ساده است. اگر یک آیتم جدید، یک آیتم موجود را بازنویسی کند، موقعیت درج اصلی تغییر می‌کند و به انتها منتقل می‌شود:

class LastUpdatedOrderedDict(OrderedDict):
    'Store items in the order the keys were last added'

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        self.move_to_end(key)

یک OrderedDict همچنین می‌تواند برای پیاده‌سازی انواعی از @functools.lru_cache مفید باشد:

from collections import OrderedDict
from time import monotonic

class TimeBoundedLRU:
    "LRU Cache that invalidates and refreshes old entries."

    def __init__(self, func, maxsize=128, maxage=30):
        self.cache = OrderedDict()      # { args : (timestamp, result)}
        self.func = func
        self.maxsize = maxsize
        self.maxage = maxage

    def __call__(self, *args):
        if args in self.cache:
            self.cache.move_to_end(args)
            timestamp, result = self.cache[args]
            if monotonic() - timestamp <= self.maxage:
                return result
        result = self.func(*args)
        self.cache[args] = monotonic(), result
        if len(self.cache) > self.maxsize:
            self.cache.popitem(last=False)
        return result
class MultiHitLRUCache:
    """ LRU cache that defers caching a result until
        it has been requested multiple times.

        To avoid flushing the LRU cache with one-time requests,
        we don't cache until a request has been made more than once.

    """

    def __init__(self, func, maxsize=128, maxrequests=4096, cache_after=1):
        self.requests = OrderedDict()   # { uncached_key : request_count }
        self.cache = OrderedDict()      # { cached_key : function_result }
        self.func = func
        self.maxrequests = maxrequests  # max number of uncached requests
        self.maxsize = maxsize          # max number of stored return values
        self.cache_after = cache_after

    def __call__(self, *args):
        if args in self.cache:
            self.cache.move_to_end(args)
            return self.cache[args]
        result = self.func(*args)
        self.requests[args] = self.requests.get(args, 0) + 1
        if self.requests[args] <= self.cache_after:
            self.requests.move_to_end(args)
            if len(self.requests) > self.maxrequests:
                self.requests.popitem(last=False)
        else:
            self.requests.pop(args, None)
            self.cache[args] = result
            if len(self.cache) > self.maxsize:
                self.cache.popitem(last=False)
        return result

اشیای UserDict

کلاس UserDict به‌عنوان پوششی برای اشیای دیکشنری عمل می‌کند. نیاز به این کلاس تا حدی با امکان ایجاد زیرکلاس مستقیماً از dict جایگزین شده است؛ با این حال، کار با این کلاس می‌تواند آسان‌تر باشد، زیرا دیکشنری زیرین به‌عنوان یک ویژگی قابل دسترسی است.

class collections.UserDict(**kwargs)
class collections.UserDict(mapping, /, **kwargs)
class collections.UserDict(iterable, /, **kwargs)

کلاسی که یک دیکشنری را شبیه‌سازی می‌کند. محتویات نمونه در یک دیکشنری معمولی نگهداری می‌شود، که از طریق ویژگی data نمونه‌های UserDict قابل دسترسی است. اگر آرگومان‌هایی ارائه شوند، از آن‌ها برای مقداردهی اولیه‌ی data استفاده می‌شود، مانند یک دیکشنری معمولی.

علاوه بر پشتیبانی از متدها و عملیات نگاشت‌ها، نمونه‌های UserDict ویژگی زیر را فراهم می‌کنند:

data

یک دیکشنری واقعی که برای ذخیره‌ی محتویات کلاس UserDict استفاده می‌شود.

اشیاء UserList

این کلاس به‌عنوان پوششی برای اشیای فهرست عمل می‌کند. این کلاس، کلاس پایه مفیدی برای کلاس‌های فهرست‌مانند خودتان است که می‌توانند از آن‌ها ارث‌بری کنند، متدهای موجود را بازنویسی کنند یا متدهای جدیدی اضافه کنند. به این ترتیب، می‌توان رفتارهای جدیدی به فهرست‌ها اضافه کرد.

نیاز به این کلاس تا حدی با امکان زیرکلاس‌گیری مستقیم از list جایگزین شده است؛ با این حال، کار با این کلاس می‌تواند آسان‌تر باشد، زیرا فهرست زیربنایی به‌عنوان یک ویژگی قابل دسترسی است.

class collections.UserList([list])

کلاسی که یک فهرست را شبیه‌سازی می‌کند. محتوای نمونه در یک فهرست معمولی نگهداری می‌شود، که از طریق ویژگی data در نمونه‌های UserList قابل دسترسی است. محتوای نمونه در ابتدا به یک کپی از list تنظیم می‌شود، که به‌طور پیش‌فرض فهرست خالی [] است. list می‌تواند هر پیمایش‌پذیری باشد، برای مثال یک فهرست واقعی پایتون یا یک شیء UserList.

علاوه بر پشتیبانی از متدها و عملیات دنباله‌های تغییرپذیر، نمونه‌های UserList ویژگی زیر را ارائه می‌دهند:

data

یک شیء واقعی list که برای ذخیره‌ی محتوای کلاس UserList استفاده می‌شود.

الزامات زیرکلاس‌سازی: انتظار می‌رود زیرکلاس‌های UserList سازنده‌ای ارائه دهند که بتوان آن را بدون آرگومان یا با یک آرگومان فراخوانی کرد. عملیات فهرستی که دنباله‌ی جدیدی بازمی‌گردانند، تلاش می‌کنند نمونه‌ای از کلاس پیاده‌سازی واقعی ایجاد کنند. برای این کار، فرض می‌شود که سازنده می‌تواند با یک پارامتر فراخوانی شود، که یک شیء دنباله است و به‌عنوان منبع داده استفاده می‌شود.

اگر یک کلاس مشتق مایل به رعایت این الزام نباشد، لازم است تمام متدهای ویژه‌ای که این کلاس از آن‌ها پشتیبانی می‌کند، بازنویسی شوند؛ لطفاً برای اطلاع از متدهایی که در آن حالت باید فراهم شوند، به منابع مراجعه کنید.

اشیاء UserString

کلاس UserString به‌عنوان پوششی برای اشیای رشته عمل می‌کند. نیاز به این کلاس تا حدی با امکان ایجاد زیرکلاس به‌طور مستقیم از str جایگزین شده است؛ با این حال، کار با این کلاس می‌تواند آسان‌تر باشد، زیرا رشته زیرین به‌عنوان یک ویژگی قابل دسترسی است.

class collections.UserString(seq)

کلاسی که یک شیء رشته را شبیه‌سازی می‌کند. محتوای نمونه در یک شیء رشته معمولی نگه داشته می‌شود، که از طریق ویژگی data نمونه‌های UserString قابل دسترسی است. محتوای نمونه در ابتدا روی یک کپی از seq تنظیم می‌شود. آرگومان seq می‌تواند هر شیءای باشد که بتوان آن را با استفاده از تابع توکار str() به رشته تبدیل کرد.

علاوه بر پشتیبانی از متدها و عملیات رشته‌ها، نمونه‌های UserString ویژگی زیر را فراهم می‌کنند:

data

یک شیء واقعی از نوع str که برای ذخیره‌ی محتوای کلاس UserString استفاده می‌شود.

تغییر یافته در نسخه‌ی 3.5: متدهای جدید __getnewargs__، __rmod__، casefold، format_map، isprintable و maketrans.