Емуляція типів контейнерів
Оновлено: 28.04.2023
Наступні методи можуть бути визначені для реалізації контейнерних об’єктів. Зазвичай контейнерами є послідовності (такі як списки або кортежі) або відображення (наприклад, словник), але його представляють також інші контейнери. Перший набір методів використовується або для емуляції послідовності, або для емуляції відображення; різниця полягає в тому, що для послідовності дозволеними ключами мають бути цілі числа k, для яких 0 <= k < N, де N — довжина послідовності, або об’єкти slice, які визначають діапазон предметів. Також рекомендується, щоб зіставлення передбачало методи keys(), values(), items(), get(), clear(), setdefault() , pop(), popitem(), copy() і update() поводяться подібно до об’єктів стандарту Python dictionary. Модуль collections.abc надає MutableMapping abstract base class, щоб допомогти створити ці методи з базового набору __getitem__() , __setitem__(), __delitem__() і keys(). Змінні послідовності повинні надавати методи: append(), count(), index(), extend(), insert(), pop(), remove(), reverse() і sort(), як стандартні об’єкти Python list. Нарешті, типи послідовностей повинні реалізовувати додавання (що означає конкатенацію) і множення (що означає повторення) шляхом визначення методів __add__(), __radd__(), __iadd__() , __mul__(), __rmul__() і __imul__(), описані нижче; вони не повинні визначати інші числові оператори. Рекомендується, щоб і відображення, і послідовності реалізовували метод __contains__(), щоб забезпечити ефективне використання оператора in; для відображень in має шукати ключі відображення; для послідовностей слід шукати значення. Крім того, рекомендується, щоб і відображення, і послідовності реалізовували метод __iter__(), щоб забезпечити ефективну ітерацію через контейнер; для відображень __iter__() має виконувати ітерацію по ключах об’єкта; для послідовностей він повинен перебирати значення.
object.__len__(self) Викликається для реалізації вбудованої функції len(). Має повертати довжину об’єкта, ціле число >= 0. Крім того, об’єкт, який не визначає метод __bool__() і чий метод __len__() повертає нуль, вважається false у логічному контексті. Деталі реалізації CPython: У CPython довжина не повинна перевищувати sys.maxsize. Якщо довжина більша за sys.maxsize, деякі функції (такі як len()) можуть викликати OverflowError. Щоб запобігти виникненню OverflowError шляхом перевірки значення істинності, об’єкт повинен визначити метод __bool__().
object.__length_hint__(self) Викликається для реалізації operator.length_hint(). Має повернути приблизну довжину об’єкта (яка може бути більшою або меншою за фактичну). Довжина має бути цілим числом >= 0. Поверненим значенням також може бути NotImplemented, яке обробляється так само, як якби метод __length_hint__ взагалі не існував. Цей метод є виключно оптимізаційним і ніколи не потрібен для коректності. Нове в версії 3.4.
a[1:2] = b
a[slice(1, 2, None)] = b
object.__getitem__(self, key) Викликається для реалізації оцінки self[key]. Для типів sequence прийнятними ключами мають бути цілі числа та об’єкти зрізу. Зверніть увагу, що спеціальна інтерпретація негативних індексів (якщо клас бажає емулювати тип sequence) залежить від методу __getitem__(). Якщо key має невідповідний тип, може виникнути TypeError; якщо значення знаходиться за межами набору індексів для послідовності (після будь-якої спеціальної інтерпретації від’ємних значень), має бути викликано IndexError. Для типів mapping, якщо key відсутній (не в контейнері), слід викликати KeyError. Примітка for цикли очікують, що IndexError буде викликано для недопустимих індексів, щоб забезпечити належне виявлення кінця послідовності. Примітка Коли індексує клас, спеціальний метод класу __class_getitem__() може викликатися замість __getitem__(). Перегляньте __class_getitem__ проти __getitem__ для отримання додаткової інформації.
object.__setitem__(self, key, value) Викликається для реалізації призначення self[key]. Така сама примітка, як і для __getitem__(). Це має бути реалізовано лише для відображень, якщо об’єкти підтримують зміни значень для ключів, або якщо можна додати нові ключі, або для послідовностей, якщо елементи можна замінити. Для неправильних значень key мають бути викликані ті самі винятки, що й для методу __getitem__().
object.__delitem__(self, key) Викликається для реалізації видалення self[key]. Така сама примітка, як і для __getitem__(). Це слід застосовувати лише для відображень, якщо об’єкти підтримують видалення ключів, або для послідовностей, якщо елементи можна видалити з послідовності. Для неправильних значень key мають бути викликані ті самі винятки, що й для методу __getitem__().
object.__missing__(self, key) Викликається dict.__getitem__() для реалізації self[key] для підкласів dict, коли ключа немає в словнику.
object.__iter__(self) Цей метод викликається, коли для контейнера потрібен iterator. Цей метод має повертати новий об’єкт-ітератор, який може виконувати ітерацію по всіх об’єктах у контейнері. Для зіставлення він повинен перебирати ключі контейнера.
object.__reversed__(self) Викликається (якщо є) вбудованим reversed() для реалізації зворотної ітерації. Він має повернути новий об’єкт-ітератор, який обходить усі об’єкти в контейнері у зворотному порядку. Якщо метод __reversed__() не надано, вбудований reversed() повернеться до використання протоколу послідовності (__len__() і __getitem__()). Об’єкти, які підтримують протокол послідовності, повинні надавати лише __reversed__(), якщо вони можуть забезпечити ефективнішу реалізацію, ніж та, яку надає reversed().
Оператори перевірки членства (in і not in) зазвичай реалізуються як ітерація через контейнер. Однак об’єкти-контейнери можуть надавати наступний спеціальний метод з більш ефективною реалізацією, яка також не вимагає, щоб об’єкт був повторюваним.
object.__contains__(self, item) Викликано реалізувати оператори перевірки членства. Має повертати true, якщо item знаходиться в self, і false в іншому випадку. Для відображення об’єктів це має враховувати ключі відображення, а не значення або пари ключ-елемент. Для об’єктів, які не визначають __contains__(), тест на приналежність спочатку намагається виконати ітерацію через __iter__(), потім старий протокол ітерації послідовності через __getitem__(), див. цей розділ у посилання на мову.