2

This works as intended:

if c1 in r':6' or c2 in r':6':
    subst_weight = 1

This doesn't:

if (c1 or c2) in r':6':
    subst_weight = 1

Why and what is the differnce? The goal is to find out whether c1 or c2 is in the string. Same here:

Works:

if c1 == '6' or c2 == '6':

Doesn't work:

if (c1 or c2) == '6':

Thanks

doc
  • 127
  • 1
  • 11

5 Answers5

3

The statement one or two will return one if defined, and two if one is not truthy, and I don't see a reason it wouldn't work with your logic because if either is truthy, and is contained in string, it will evaluate to True

>>> a = "6"
>>> b = ":"
>>> (a or b)
'6'
>>> (b or a)
':'
>>> a = None
>>> (a or b)
':'
>>> b
':'

For more than 2 variables it will return the first that's truthy

>>> a = None
>>> b = None
>>> c = 6
>>> a or b or c
6

But note your logic, you want to check if any of the variables is in that string, you can't use this, because the c1 ca be equal to "example" and that's what's gonna be returned to that if statement and it's not in ":6"

Marko Mackic
  • 2,293
  • 1
  • 10
  • 19
  • 'defined' in this context means 'truthy'. If c1 is truthy, but not a substring of r':6', the if statement will be skipped. – folkol Aug 08 '16 at 00:12
2

Although not literally answering your question of why, this is an answer to "how then should I..."

if any(x in r':6' for x in [c1, c2]):
  something

If you ever get more of the 'c's, use a variable to define the list beforehand.

(sauce: Check if multiple strings exist in another string)

Community
  • 1
  • 1
madeddie
  • 271
  • 2
  • 9
1

This expression:

if (c1 or c2) in r':6':

Evaluates from left to right. Assuming that (c1 or c2) is truthy, it's equivalent to this:

if True in r':6':

Which obviously is not what you want. If you want it to work for several variables, this will do nicely:

if any(c in r':6' for c in (c1, c2, c3, c4)):
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • or-chains evaluates to the first truthy operand (or to the last one in the sequence, if none of them are truthy), not to 'True'. – folkol Aug 08 '16 at 00:04
  • Thanks, got it. Any way to make it less ugly? If you have more variables it could get quite tedious. – doc Aug 08 '16 at 00:04
  • This will do, just fill the list with the variables to check in the text: `if any(c in txt for c in [c1, c2, ...]):` – Óscar López Aug 08 '16 at 00:12
1

It has to do with the precedent given to the operators. The use of ()'s means that c1 or c2 is evaluated first. It evaluates to True or False. So your statement converts to

if bool in r':g'

Which is not what you are looking for.

WombatPM
  • 2,561
  • 2
  • 22
  • 22
1

Because (c1 or c1) evaluates as the value of the first variable, if it is not "false"(which means false, 0 or an empty string) or the value of the second variable.

Programming languages don't work like "natural languages".

csabinho
  • 1,579
  • 1
  • 18
  • 28