ddlj
ddlj

Reputation: 141

Can `in` operator in Python be used other than checking for membership in a sequence?

in operator in Python is a membership operator that tests for membership in a sequence.

Description of in operator

Evaluates to true if it finds a variable in the specified sequence and false otherwise.

Now consider the code:

>>>s = 'HELLO'
>>>char = 'M'
>>>char in s
False
>>>for char in s:
....    print(char)
H
E
L
L
O

Please correct me here: I think the statement for char in s should check for 'M' in 'HELLO' which should be evaluated to False and the loop should be terminated. But here, instead of checking for the membership, it is assigning every character to the variable char and thus the loop is printing the every character. My question is, how in operator can be used other than checking the membership?

Upvotes: 2

Views: 1167

Answers (3)

Right leg
Right leg

Reputation: 16720

The in keyword is used in two different contexts:

  • Membership test
  • Iteration

The first, as you said, checks if something belongs to a sequence, by calling that sequence's __contains__. When using this syntax, a boolean value is returned.

x = 1
l = [0, 1, 2]
if x in l:
    print("x is in l")
else:
    print("x is not in l")
> x is in l

Since in looks for the __contains__ method, x in seq is valid as long as seq implements a __contains__ method. You can implement this, even though it does not make logical sense, regarding the concept of membership.

class Foo:
    def __contains__(self, x):
        return x == 12

f = Foo()
if 12 in f:
    print("12 is in f")
> 12 is in f

The second is actually more often used. According to an iteration protocol, it enumerates the elements of an iterable object, so that actions can be performed on them.

You can iterate over a list:

l = [0, 1, 2]
for x in l:
    print(x)
> 0
> 1
> 2

Over a string:

s = "hello"
for c in s:
    print(c)
> h
> e
> l
> l
> o

And over any object implementing the __iter__ method, as long as the latter returns an object that implements the __next__ method.

The following example is a basic (not to say "poor") range-like class, whose you can iterate over the instances.

class Bar:
    def __init__(self, first, last):
        self.first = first
        self.last = last
        self.current = first

    def __iter__(self):
        return self

    def __next__(self):
        if self.current == self.last:
            raise StopIteration
        result = self.current
        self.current += 1
        return result

b = Bar(0, 5)
for i in b:
    print(i)
> 0
> 1
> 2
> 3
> 4

A lot of native types are iterable: dictionaries, ranges, sets...


Semantically speaking, it makes sense to use the same in word for both contexts. "Is this thing in that stuff?" is a valid question, as long as "stuff" is a collection, which is capable of containing things. Henceforth, "do this for every thing in that stuff" seems pretty natural.

Hence the use of "in" for both contexts.

This is however quite a simplification of the reality, which is actually more vast. I invite you to read the documentation, and for an in-depth understanding of the in keyword, read Python's grammar.

Upvotes: 6

Keef Baker
Keef Baker

Reputation: 641

The main thing you need to think here is that the keyword in if you use it in a for loop then it'll redefine char or every line in the loop.

so to test every character individually in a loop you'd need:

s = 'HELLO'
char = 'M'
for chr in s:
    if char in chr:
        print chr

but that's kind of pointless. You might as well use if char=chr

But you can test for characters in list elements like this so:

s = ['HELLO', 'MIKE', 'BOB']
char = 'M'
for word in s:
    if char in word:
        print word

would test every list element for the presence of "M"

Upvotes: 0

anarchokawaii
anarchokawaii

Reputation: 116

any object that has the __contains__() method can use the "in" operator. by using the dir() function or the hasattr() function you can check if you can use the "in" operator on that object

>>>dir(hw)
[...,__contains__,...]
>>>hasattr(hw,"__contains__")
True

Upvotes: 0

Related Questions