0

I am checking whether two substrings are contained in another string:

if (substr1 and substr2) in str:
    my_func()

This does not work, the if statement is already being entered when only one substring is part of the string. Can someone explain why?

I found the following workaround, I'd simply like to know why Python behaves that way.

substr_list = [substr1, substr2]
if all(substr in str for substr in substr_list):
    my_func()
Dahlai
  • 695
  • 1
  • 4
  • 17
  • `(substr1 and substr2)` is a boolean. Is the result of this expression in your string? No. Then you need to use separate expressions `if substr1 in str and substr2 in str:` – David Zemens Oct 17 '16 at 14:54
  • 1
    Intro: [shortcircuiting](https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not). The items in the parens are evaluated first and only one is taken. Bonus: Do not use `str` as a name. `str` is a builtin function which gets shadowed after an assignment to the name. – Moses Koledoye Oct 17 '16 at 14:55
  • @Moses Koledoye: Thank you for introducing me to the term shortcircuiting – Dahlai Oct 17 '16 at 15:07
  • @DavidZemens: Thanks I felt like this was some specific behavior of the `in` operator – Dahlai Oct 17 '16 at 15:08

2 Answers2

0

It doesn't work because (substr1 and substr2) return substr2 or operand which can convert to False and after this you verify if substr2 in str

'' and 'Some string'  # ''
'some value' and 'some value 2' # 'some value 2'
# full example
string_variable = 'some value' and 'some value 2' # You get 'some value 2'
string_variable in substr2
Oleksandr Dashkov
  • 2,249
  • 1
  • 15
  • 29
-2

So and works to check if two booleans (True/False values) are True, however (substr1 and substr2) is not a boolean. However, substr1 in str and substr2 in str and both booleans, so you can create a statement:

if substr1 in str and substr2 in str:
    myfunc()

Now in

substr_list = [substr1, substr2]
if all(substr in str for substr in substr_list):
    my_func()

The statement (substr in str for substr in substr_list) creates a generator that will return two boolean values. What all does is takes any iterable such a list of generator of booleans and returns a single boolean checking if they are all True.

beigel
  • 1,190
  • 8
  • 14