Logical operators, lust like arithmetic ones, have relative precedence. *
happens before +
; in
happens before and
, which happens before or
.
In your first case, in "Lorem" and "aliqua" in string
, evaluation happens as if parenthesis were put like this "Lorem" and ("aliqua" in string)
. First "aliqua" in string
evaluates to True
, then "Lorem" and True
evaluates to boolean True
.
In your second case, in "Lorem" or "aliqua" in string
evaluation order is the same: "Lorem" or ("aliqua" in string)
-> "Lorem" or True
-> "Lorem".
Now, however, we have to talk about one small optimization, that is used in many languages besides Python.
Logically speaking, expression True and A
is fully equivalent to A
(you can derive that mathematically). So, when Python sees that the first part of and
is True (or true-ish) it just gives you the second argument. (In Python non-zeros, non-empty arrays/dictionaries, etc., are said to be "truthy", as in they give True when passed to bool(x)
). Similarly with or
— if it sees that we have something like "True-ish X and something" it just gives you back that X. Take a look:
In : True and "a"
Out: 'a'
In : "a" and True
Out: True
In : True or "a"
Out: True
In : "a" or True
Out: 'a'
That's why in your first case "Lorem" and True
evaluates to True
("Lorem" is true-ish, so Python just gives back the second argument), while in the second case "Lorem" or True
evaluates to "Lorem"
(Python gives back the first argument).
If you want to check whether both substrings are in a string, you can construct a longer expression
"Lorem" in string and "aliqua" in strign
or use loops/arrays
string = "Lorem ipsum dolor sit ..."
words = ["Lorem", "ipsum", "dolor"]
# `all` checks whether everything is True
print(all(word in string for word in words))
# True
# `any` checks whether at least something is True
print(any(word in string for word in words))
# True