Search code examples
pythonlogical-operatorsnotin

Logical Expressions: Why does "str1 in str2 or str2 not in str1" return True for my print statement?


Firstly, I apologise for the stupid question or any errors in my post! (This is my first post!)

Secondly, I have tried to look up the answer to this on Stack Overflow and also the RealPython website (Logical Expressions) but I still can't seem to wrap my head around why this piece of code returns a "True" to the last (uncommented) function call?

I am trying to answer the following question from the Ebook "Introduction to computation and programming using Python" -

"Write a function isIn that accepts two strings as arguments and returns True if either string occurs anywhere in the other, and False otherwise. Hint: you might want to use the built-in str operation in."

If anyone can explain (in layman terms) why the below piece of code is returning "True" to the last function call, I would be very grateful - Again apologies for the stupid question!

def isIn(string1, string2):
    """Input two strings 
       Returns 'True' if either strings are within each other
    """

    if string1 in string2 or string2 not in string1:
        return True
    else:
        return False

# isIn('hello', 'hello')           # Prints True
# isIn('hello', 'hello world')     # Prints True   
isIn('hello world', 'world hello') # Prints True

Solution

  • Why your functions returns True ?

    The if statement if string1 in string2 or string2 not in string1 is made of 3 parts:

    1. string1 in string2
    2. or
    3. string2 not in string1

    And you have:

    string1 = 'hello world'
    string2 = 'world hello'
    
    • Part 1 (string1 in string2) :

      It evaluates to False, because 'hello world' isn't in 'world hello'

    • Part 3 (string2 not in string1):

      It evaluates to True, because 'world hello' is effectively not present in 'hello world'

    • Part2, or:

      The or will give you:

      • True if at least one of the expression evaluates to True
      • False if all the expression evaluate to False

    So you get True

    But if you have used and, you would have get False

    If sometimes you are in doubt, try some print like these:

    # or:
    print(True or True) # True
    print(True or False) # True
    print(False or False) # False
    
    # and:
    print(True and True) # True
    print(True and False) # False
    print(False and False) # false
    

    Answering your comment:

    No, 'hello world' isn't in 'world hello' So, what is in 'world hello' ?

    • 'world', 'hello', ' ' (space) and '' (the empty string).
    • And all possible substrings (characters and consecutive characters in the source string, so for example 'h', 'he', 'hel', ' wo', etc.). And note that all items in fact 'world', 'hello', ' ' and '' are substrings to :-)

    So, all of this evaluates to true:

    # string2 = 'world hello'
    'world' in string2
    'hello' in string2
    ' ' in string2
    '' in string2
    'h' in string2
    'e' in string2
    'llo' in string2
    'llo 'wo' in string2
    # etc.
    

    In computer science, a string is a sequence of characters. Each sub-sequence is a substring.

    So now, you should have a better understanding of what is a string and what is a substring and you could/should search some informations on the internet if you're interested.

    So, what does the in expression ? The in expression, in fact, when working with strings, tells you if the character of the string you're searching in another string, is a substring of this string or not.

    To conclude, the sequence of characters 'hello world' is not in the sequence of characters 'world hello'.