Home > Back-end >  Why is there a difference in how the in operator behaves?
Why is there a difference in how the in operator behaves?

Time:12-25

This works perfectly

def get_count(sentence):
        return sum(1 for letter in sentence if letter in ('aeiou'))

But when I apply the in operator to an array like this, it fails

# Incorrect answer for "aeiou": 0 should equal 5
def get_count(sentence):
        return sum(1 for letter in sentence if letter in ['aeiou'])

CodePudding user response:

In the first snippet, ('aeiou') is a string surrounded by parentheses (which have no syntactic function in this case). The in is applied to the string, which is itself an iterable, and thus checks if letter is one of the characters in that string.

In the second snippet, ['aeoiu'] is a list with a single element, the string 'aeiou'. The in operator applies to the list, and checks if letter is one of the elements in the list. It obviously isn't (since letter is a single character), and thus this condition always evaluates to False.

CodePudding user response:

('aeiou') is a string. You can verify this with

>>> x = ('aeiou')
>>> type(x)
<class 'str'>

['aeiou'] on the other hand is a list containing one element which in turn is a string.

>>> x = ['aeiou']
>>> type(x)
<class 'list'>
>>> len(x)
1
>>> type(x[0])
<class 'str'>

When you write if letter in ('aeiou'), here you are testing if the letter is a substring of the string 'aeiou'. However, when you write if letter in ['aeiou'], you are testing if the letter is an element in the list the contains one element, the string 'aeiou' which is always False for letter that is a single character.

CodePudding user response:

It's is not so much the behavior of in that's different, as the syntax being unexpected for beginners. () is an empty tuple. But that's the only time that parentheses make a tuple. In all other cases, parentheses are needed for grouping, but it's the comma that makes a tuple.

  • ('aeiou') is not a tuple. It's a string with superfluous parentheses. ('aeiou',) is a tuple, and so is 'aeiou',.
  • ['aeiou'] is unambiguously a list with one element.

Letters are length-one strings in python: there are no character objects as such.

  • In the first case, you are searching for each letter in a string, which is a container of length-one strings, so you occasionally find one.
  • In the second case, you are searching for each letter in a list, which is a container of not-length-one strings, so you never find a match.

Compare the second case to list('aeiou'). Instead of making a list of one element as ['aeiou'], this creates a list containing all the letters in the input string.

Unrelated fun fact: sum defaults to a starting value of 0 (the int), and bool is a subclass of int that always equals zero or one. You can therefore rewrite your counter in the following ways:

sum(letter in 'aeiou' for letter in sentence)
sum(map('aeiou'.__contains__, sentence))

CodePudding user response:

('aeiou') equals 'aeiou', brackets like this are redundant.

Second time you are looking if chars from your sentence are in ['aeiou']. This list contains a string of 5 characters, so letter in ['aeiou'] would never return True.

  • Related