0

Sorry but I can't understand why it gives me in out "ok" even if the second if is not true!

val = ('zxyea')

print("val")

if ("a") or ("b") in val.lower():
    if ("c") or ("d") in val.lower(): `enter code here`
        if ("e") or ("f") in val.lower():
            print("ok")

This is a piece of my code:

if ("accendi") or ("accendere") or ("spegi") or ("spegere") or ("luce") or ("luci") in text.lower:
        
        if ("sala") or ("salone") or ("salotto") in text.lower:
            #luce_sala()
            print("sala")

        elif ("cucina") or ("mensola") in text.lower:
            #luce_cucina
            print("cucina")
            
        elif ("led") or ("diffusa") in text.lower:
            #luce_led
            print("led")
            
        elif ("tutte") or ("tutta")or ("tutto") in text.lower:
            #tutte_le_luci
            print("tutte le luci")
  • 1
    I am working on a speech recognition project and instead of recognizing a single sentence I want to make sure to recognize the words that interest me even if in random order. –  Jan 13 '21 at 20:49
  • You may want to make your comment into a different question. Provide the example of a sentence and words you are trying to match. Include your attempt at code. This is both the more proper way to ask (rather than as a comment to this question), and will also attract more attention (since your current question got closed). Good luck! – Timur Shtatland Jan 13 '21 at 21:11
  • 1
    To check if words are contained in a sentence, split the sentence into a set (not list) of words. Use `re.split` to split on whitespace and punctuation. Then do: `if my_word in word_set: print('ok')` for each word you want to test against the sentence. – Timur Shtatland Jan 13 '21 at 21:17
  • Also, you probably meant `print(val)` in the code above (no quotes). – Timur Shtatland Jan 13 '21 at 21:18

1 Answers1

2

This is because ("a") evaluates to true, as well as the first item in all your if conditions. In each case, the second part (after the or) never gets evaluated at all! So it does not matter whether, for example, ("b") in val.lower() is True, because it is never checked by the lazy or. You probably meant:

if 'a' in val.lower() or 'b' in val.lower():
# etc

Details:
Your original code (with minor formatting changes), explained:

if ("a") or ("b") in val.lower():
    if ("c") or ("d") in val.lower(): 
        if ("e") or ("f") in val.lower():
            print("ok")

Because of operator precedence, it is equivalent to this, which is probably not what you intended:

if ("a") or (("b") in val.lower()):
    if ("c") or (("d") in val.lower()): 
        if ("e") or (("f") in val.lower()):
            print("ok")

Now, there is nothing special about the parenthesis around the strings (most notably, the parenthesis do not make a tuple - comma does), so we can remove them, which yields this:

if "a" or ("b" in val.lower()):
    if "c" or ("d" in val.lower()): 
        if "e" or ("f" in val.lower()):
            print("ok")

Now, any non-empty string is True, according to the docs. And we can also evaluate the other operand to the right of or (for our own interest, not because the Python interpreter evaluates them). Note that val = ('zxyea'). The end result is this:

if True or False:
    if True of False: 
        if True or False:
            print("ok")

Or simply:

if True:
    if True: 
        if True:
            print("ok")

And this, of course, prints ok.

Timur Shtatland
  • 12,024
  • 2
  • 30
  • 47