I implemented the __contains__ method on a class for the first time the other day, and the behavior wasn't what I expected. I suspect there's some subtlety to the in operator that I don't understand and I was hoping someone could enlighten me.
It appears to me that the in operator doesn't simply wrap an object's __contains__ method, but it also attempts to coerce the output of __contains__ to boolean. For example, consider the class
class Dummy(object):
def __contains__(self, val):
# Don't perform comparison, just return a list as
# an example.
return [False, False]
The in operator and a direct call to the __contains__ method return very different output:
>>> dum = Dummy()
>>> 7 in dum
True
>>> dum.__contains__(7)
[False, False]
Again, it looks like in is calling __contains__ but then coercing the result to bool. I can't find this behavior documented anywhere except for the fact that the __contains__ documentation says __contains__ should only ever return True or False.
I'm happy following the convention, but can someone tell me the precise relationship between in and __contains__?
Epilogue
I decided to choose @eli-korvigo answer, but everyone should look at @ashwini-chaudhary comment about the bug, below.