Operators ``++in++`` and ``++not in++``, also called https://docs.python.org/3/reference/expressions.html#membership-test-operations["membership test operators"], require that the right operand supports membership protocol.


In order to support this membership protocol a user-defined class should implement at least one of the following methods: ``++__contains__++``, ``++__iter__++``, ``++__getitem__++``.


This rule raises an issue when operators ``++in++`` and ``++not in++`` are called with a right operand not supporting membership protocol.


== Noncompliant Code Example

----
myint = 42

if 42 in myint:  # Noncompliant. Integers don't support membership protocol
    pass

class A:
    def __init__(self, values):
        self._values = values

if "mystring" in A(["mystring"]):  # Noncompliant. Class A doesn't support membership protocol
    pass
----


== Compliant Solution

----
mylist = [42]

if 42 in mylist:
    pass

class MyContains:
    def __init__(self, values):
        self._values = values

    def __contains__(self, value):
        return value in self._values

if "mystring" in MyContains(["mystring"]):  # Noncompliant. Class A don't support membership protocol
    pass

# OR

class MyIterable:
    def __init__(self, values):
        self._values = values

    def __iter__(self):
        return iter(self._values)

if "mystring" in MyIterable(["mystring"]):  # Noncompliant. Class A don't support membership protocol
    pass

# OR

class MyGetItem:
    def __init__(self, values):
        self._values = values

    def __getitem__(self, key):
        return self._values[key]

if "mystring" in MyGetItem(["mystring"]):  # Noncompliant. Class A don't support membership protocol
    pass
----


== See

* https://docs.python.org/3/reference/expressions.html#membership-test-operations[Python documentation - Membership test operations]

