8.7. Operator Contains
a in b
- will call "contains" on objectb
(b.__contains__(a)
)
8.7.1. Syntax
>>> class MyClass:
... def __contains__(self, other): ... # x in self
8.7.2. Problem
>>> class Vector:
... x: int
... y: int
...
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
... def __repr__(self):
... return f'Vector(x={self.x}, y={self.y})'
>>> a = Vector(x=1, y=2)
>>>
>>> 1 in a
Traceback (most recent call last):
TypeError: argument of type 'Vector' is not iterable
>>>
>>> 3 in a
Traceback (most recent call last):
TypeError: argument of type 'Vector' is not iterable
8.7.3. Solution
>>> class Vector:
... x: int
... y: int
...
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
... def __repr__(self):
... return f'Vector(x={self.x}, y={self.y})'
...
... def __contains__(self, item):
... if self.x == item:
... return True
... if self.y == item:
... return True
... return False
>>> a = Vector(x=1, y=2)
>>>
>>> 1 in a
True
>>>
>>> 3 in a
False
8.7.4. Operator
operator.contains(a, b)
- contains -a in b
>>> import operator
>>> operator.contains([1, 2, 3], 2)
True
8.7.5. Use Case - 1
>>> class Group:
... def __init__(self):
... self.users = []
...
... def add_user(self, user):
... self.users.append(user)
...
... def __contains__(self, who):
... for user in self.users:
... if who == user:
... return True
... return False
>>>
>>>
>>> admins = Group()
>>> admins.add_user('mwatney')
>>> admins.add_user('mlewis')
>>> admins.add_user('rmartinez')
>>>
>>> 'mwatney' in admins
True
8.7.6. Use Case - 2
>>> class Group:
... def __init__(self):
... self.members = []
...
... def __iadd__(self, user):
... self.members.append(user)
... return self
...
... def __contains__(self, user):
... return user in self.members
>>>
>>>
>>> admins = Group()
>>> admins += 'mwatney'
>>> admins += 'mlewis'
>>> admins += 'rmartinez'
>>>
>>> admins.members
['mwatney', 'mlewis', 'rmartinez']
>>>
>>> 'mwatney' in admins
True
>>>
>>> 'avogel' in admins
False
8.7.7. Assignments
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Operator Comparison Contains
# - Difficulty: easy
# - Lines: 5
# - Minutes: 5
# %% English
# 1. Override operators for code to work correctly
# 2. Do not use `dataclasses`
# 3. Run doctests - all must succeed
# %% Polish
# 1. Nadpisz operatory aby poniższy kod zadziałał poprawnie
# 2. Nie używaj `dataclasses`
# 3. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `object.__contains__()`
# - `object.__eq__()`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> mark = User(firstname='Mark', lastname='Watney', groups=[
... Group(gid=1, name='admins'),
... Group(gid=2, name='staff'),
... Group(gid=3, name='managers'),
... ])
>>> Group(gid=1, name='admins') == Group(gid=1, name='admins')
True
>>> Group(gid=1, name='admins') == Group(gid=2, name='staff')
False
>>> Group(gid=1, name='admins') == Group(gid=3, name='managers')
False
>>> Group(gid=1, name='admins') == Group(gid=0, name='root')
False
>>> Group(gid=1, name='admins') in mark
True
>>> Group(gid=2, name='staff') in mark
True
>>> Group(gid=0, name='root') in mark
False
"""
class Group:
gid: int
name: str
def __init__(self, gid: int, name: str) -> None:
self.gid = gid
self.name = name
class User:
firstname: str
lastname: str
groups: list[Group]
def __init__(self, firstname: str, lastname: str, groups: list) -> None:
self.firstname = firstname
self.lastname = lastname
self.groups = groups