Python __contains__() Magic Method

Syntax and Definition

object.__contains__(self, element)

The Python __contains__() magic method implements the membership operation, i.e., the in keyword. Semantically, the method returns True if the argument object exists in the sequence on which it is called, and False otherwise. For example, 3 in [1, 2, 3] returns True as defined by the list method [1, 2, 3].__contains__(3).

We call this a “Dunder Method” for Double Underscore Method” (also called “magic method”). To get a list of all dunder methods with explanation, check out our dunder cheat sheet article on this blog.

Basic Example Overriding Membership

You can overload the “in” operator by overriding the __contains__(self, item) method and return a Boolean value True or False whether the item exists in the custom class object or not.

Here’s a generalized example:

class MyClass:
    def __init__(self, my_collection):
        self.my_collection = my_collection

    def __contains__(self, item):
        return item in self.my_collection


my = MyClass('hello world')
print('hello' in my)
# True

The custom class MyClass wouldn’t generally support membership. But by defining the __contains__() “dunder” method, you can reduce membership of an object in the class to the problem of checking membership of an object in a collection using the “in” operator. Now, you can check, for example, if a string is a member of a custom class object.

Python Membership Background

Membership Without __contains__()

But what if the __contains__() dunder method is not defined?

In this case, Python falls back to the __iter__() iterator method to iterate over the object and compare each element individually using the == operator.

In the following example, you create a custom class Data and overwrite the __init__(), __iter__(), and __next__() methods so that you can create your own iterator over a Data object.

Then, you attempt to check membership on this custom object—it works!

See the highlighted code part:

class Data:
    def __init__(self, data):
        self.data = data # an iterable

    def __iter__(self):
        self.current_index = 0
        return self

    def __next__(self):
        if self.current_index < len(self.data):
            x = self.data[self.current_index]
            self.current_index += 1
            return x
        raise StopIteration



my_sequence = Data(['Alice', 'Bob', 'Carl'])

print('Chris' in my_sequence)
# False

print('Alice' in my_sequence)
# True

To improve your basic Python understanding, feel free to check out this related video on the iter() built-in function: