Переопределение оператора 'in' в Python: функция
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Чтобы переопределить оператор 'in' в собственном классе, вам нужно реализовать метод __contains__
. Данный метод даёт возможность указать собственные условия проверки вхождения элемента в объект этого класса.
Вот пример простого класса:
class OddContainer:
def __contains__(self, item):
return item % 2 != 0
# Пример использования:
print(1 in OddContainer()) # True, потому что 1 – нечётное число.
print(2 in OddContainer()) # False, 2 – чётное число.
Настройка проверки принадлежности с помощью contains
Метод __contains__
применяется для определения логики проверки принадлежности элемента вашему классу. Разберём пример, в котором этот метод используется для проверки наличия объекта в коллекции:
class PortfolioItem:
def __init__(self, ticker):
self.ticker = ticker
class Portfolio:
def __init__(self, *args):
self._holdings = list(args)
def __contains__(self, item):
return any(item.ticker == obj.ticker for obj in self._holdings)
# Пример использования:
portfolio = Portfolio(PortfolioItem('AAPL'), PortfolioItem('GOOG'), PortfolioItem('TSLA'))
print(PortfolioItem('AAPL') in portfolio) # True, т.к. AAPL присутствует в портфолио.
print(PortfolioItem('MSFT') in portfolio) # False, MSFT отсутствует в портфолио.
Когда contains недостаточно
Если в классе не определён метод __contains__
, Python по умолчанию использует метод __iter__
для проверки принадлежности. Это неплохой вариант для больших структур данных, однако он может быть неэффективным в некоторых ситуациях.
Визуализация
Вы можете сравнить стандартную проверку оператора 'in' с поиском ключа под ковриком у двери:
Стандартный 'in': Дом (🏠) --(🔑?)--> Коврик (🚪)
# Есть ли ключ (🔑) под ковриком (🚪)? [Да/Нет]
Переопределённый 'in': Дом (🏠) --(🔑?)--> Специализированная проверка (🗝️)
Переопределение метода позволяет задать свой алгоритм поиска.
Сложные условия принадлежности
Метод __contains__
способен обрабатывать сложные условия, не ограничиваясь базовой проверкой вхождения:
class FancyContainer:
def __init__(self):
self._data = set()
def __contains__(self, item):
return (item in self._data or some_other_complex_condition(item))
def add(self, item):
self._data.add(item)
Не забывайте про тестирование!
Важно проводить тестирование разных сценариев использования метода __contains__
, чтобы гарантировать его корректное функционирование.
Поддерживайте pythonic-стиль
При создании метода __contains__
не забывайте об основных принципах Python, а именно: стремитесь к простоте и логичности вашей реализации.
Полезные материалы
- 3. Data model — Python 3.12.2 documentation
- Operator and Function Overloading in Custom Python Classes – Real Python
- PEP 3119 – Introducing Abstract Base Classes | peps.python.org
- Enriching Your Python Classes With Dunder (Magic, Special) Methods – dbader.org
- Educative: Interactive Courses for Software Developers
- [Keeping References to Bound Methods Without Inhibiting Garbage Collection – Python Cookbook [Book]](https://www.oreilly.com/library/view/python-cookbook/0596001673/ch05s15.html)