Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the 'in' keyword claim it needs an iterable object?

Tags:

python

>>> non_iterable = 1
>>> 5 in non_iterable
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'int' object is not iterable

>>> class also_non_iterable:
...     def __contains__(self,thing):
...         return True

>>> 5 in also_non_iterable()
True
>>> isinstance(also_non_iterable(), Iterable)
False

Is there a reason in keyword claims to want an iterable object when what it truly wants is an object that implements __contains__?

like image 903
Juan Iglesias Avatar asked Oct 25 '15 04:10

Juan Iglesias


1 Answers

It claims to want an iterable because, if the object's class does not implement an __contains__ , then in tries to iterate through the object and check if the values are equal to the values yield by it.

An Example to show that -

>>> class C:
...     def __iter__(self):
...         return iter([1,2,3,4])
>>>
>>> c = C()
>>> 2 in c
True
>>> 5 in c
False

This is explained in the documentation -

For user-defined classes which define the __contains__() method, x in y is true if and only if y.__contains__(x) is true.

For user-defined classes which do not define __contains__() but do define __iter__() , x in y is true if some value z with x == z is produced while iterating over y . If an exception is raised during the iteration, it is as if in raised that exception.

like image 154
Anand S Kumar Avatar answered Oct 15 '22 22:10

Anand S Kumar