Во второй части мы рассмотрим доступ к атрибутам, имитацию типов контейнеров и имитацию числовых типов.

Если вы еще не читали, посмотрите Часть 1 этой серии здесь.



Методы доступа к атрибутам

Существует ряд различных методов, которые позволяют настраивать поведение для доступа, назначения и удаления атрибутов класса в экземплярах.

__getattribute__ и __getattr__

__getattribute__ и __getattr__ часто вызывают путаницу из-за схожих имен и поведения. __getattribute__ вызывается перед фактическим поиском свойства объекта, то есть его можно использовать для добавления настраиваемого поведения или перехвата исключений, если они возникают. __getattr__ отличается тем, что он всегда вызывается, только если вызывается напрямую __getattribute__ или если __getattribute__ или __get__ вызывают ошибку AttributeError. Если вы хотите иметь какую-либо специальную обработку для случая, когда атрибут не найден, это следует обрабатывать в __getattr__.

__dir__

__dir__ вызывается, когда dir() вызывается для объекта. __dir__ должен возвращать последовательность допустимых атрибутов объекта. dir () преобразует эту последовательность в список и отсортирует ее перед возвратом. Я не буду здесь рассказывать об этом, просто знайте, что если вам когда-нибудь понадобится переопределить поведение по умолчанию dir() для класса, вы можете сделать это с помощью __dir__ метода dunder.

Контейнерные методы

Python предлагает множество необычных методов для реализации функций контейнера в пользовательских классах. Типы контейнеров в Python включают последовательности (списки, кортежи и т. Д.) И сопоставления (словари и т. Д.). Следует отметить, что, поскольку их много, многие методы могут быть покрыты путем построения на основе абстрактных базовых классов для контейнеров, предлагаемых в стандартном библиотечном модуле collections.abc. Поскольку их несколько, мы просто рассмотрим некоторые из них.

__len__

__len__ - еще один хитрый метод, который вы, вероятно, использовали бесчисленное количество раз, даже не осознавая этого. Он вызывается всякий раз, когда вы используете встроенную функцию len() для объекта.

Обычно этот метод вызывается для некоторой последовательности, такой как список или даже строка, но вы также можете определить его для любого объекта, даже если это не обязательно имеет смысл.

__getitem__

Метод __getitem__ используется для доступа к элементу в коллекции. Если коллекция является последовательным типом, тогда принятый ключевой аргумент должен быть целым числом или срезом (необходимо соблюдать особую осторожность для отрицательных ключевых аргументов). Если коллекция является отображением, она должна принимать значение ключа. В случае, если элемент не может быть найден, для последовательностей должна быть возвращена ошибка IndexError, а из сопоставлений должна быть возвращена ошибка KeyError.

__содержит__

Операторы членства (in и not in) обычно реализуются путем перебора контейнера (сложность O (n)), однако, если в классе контейнера реализован метод __contains__, он будет использовать его. Предполагается, что вы предоставили бы этот метод, если бы существовал более эффективный поиск, который можно было бы использовать для проверки членства.

__iter__

Этот метод позволяет повторять контейнеры. В том случае, если контейнер является последовательностью, он должен возвращать объект-итератор для всех элементов в последовательности, а если контейнер является типом сопоставления, он должен возвращать итератор всех ключей.

Числовые методы

Из всех классификаций ужасных методов ни один не является столь обширным, как числовые методы. Они варьируются от всего, от поддержки сложения и вычитания до выполнения операции исключающего ИЛИ и всего, что между ними.

__Добавить__

Как и следовало ожидать, __add__ - это ужасный метод, реализующий оператор двоичного сложения (т.е. x + y). Когда он называется, на самом деле он имеет структуру x.__add__(y). __radd__ будет обрабатывать добавление в обратном порядке (y + x), хотя __radd__ будет вызываться только в том случае, если в классе для объекта y не реализовано __add__. Наконец, у нас есть __iadd__, который должен присвоить результат первому операнду и вернуть этот объект. __iadd__ можно использовать для отмены оператора +=.

__pow__

__pow__ реализует метод pow(), который также можно выразить как x ** y. Он работает точно так же, как __add__, за исключением того, что вместо выполнения сложения он возводит один операнд в степень второго операнда.

__показатель__

__index__ был изначально добавлен, чтобы любой объект, который его реализовал, можно было использовать при нарезке. Однако на самом деле это сводится к тому, что __index__ должен возвращать целое число, поскольку это единственный тип, изначально поддерживаемый при нарезке.

Вот и все - пока

Надеюсь, вам понравился этот быстрый взгляд на некоторые из распространенных методов dunder. В Части 3 мы рассмотрим вызываемые, контекстные менеджеры и другие специальные атрибуты.



Привет, я Эндрю Скотт, разработчик программного обеспечения и создатель Охрона. Ochrona фокусируется на улучшении безопасности Python, обеспечивая понимание зависимостей вашего проекта и делая это с упором на опыт разработчика (DX). Зарегистрируйтесь для получения нашей рассылки :)