Timtam
Timtam

Reputation: 223

multiple condition syntax in python

I have the following code condition

 if len(content_tags) >= 1 or tags_irrelevant == 'yes'\
   and lengthproblem == 0\
   and guess_language.guessLanguage(testlanguage) == 'en'\
   and len(sentences) >= 3:

The problem is about the logic and the syntax. I want this to be evaluated as false no matter if if len(sentences) is not >= 3. But this is not happening. I think I might need some parenthesis somewhere or something. HELP!

Upvotes: 0

Views: 305

Answers (3)

Caleb Hattingh
Caleb Hattingh

Reputation: 9235

The or part is causing your problem. Just encapsulate it:

if (len(content_tags) >= 1 or tags_irrelevant == 'yes')\
   and lengthproblem == 0\
   and guess_language.guessLanguage(testlanguage) == 'en'\
   and len(sentences) >= 3:

In cases like this, I have tended in the past to use intermediate bools to abstract the final logical statement to a higher level, for instance:

multi_tags = len(content_tags) >= 1
ignore_tags = tags_irrelevant == 'yes'
tags_ok = multi_tags or ignore_tags 

length_ok = lengthproblem == 0
is_english = guess_language.guessLanguage(testlanguage) == 'en'
enough_sentences = len(sentences) >= 3

# Notice how much easier the following is to read!
if tags_ok and length_ok and is_english and enough_sentences:
    pass

[This is something one learns to do not from blogs, but from the pain of debugging awful, decades-old legacy code littered with massive conditional clauses in if statements and while loop termination conditions. Oh, and the backslashes are gone too.]

Upvotes: 0

Claudio
Claudio

Reputation: 2217

According to the python operator precedence rules, the and operator has precedence over the or operator. That said, if you want the len(sentences) >= 3 part to dominate the answer you should isolate the rest in parenthes:

if (len(content_tags) >= 1 or tags_irrelevant == 'yes' and lengthproblem ==0 and guess_language.guessLanguage(testlanguage) =='en') and len(sentences) >= 3

Upvotes: 0

Gareth Latty
Gareth Latty

Reputation: 89077

and has a higher precidence than or, so the ands are evaluated first, then the or, meaning that the logic you have described in text is not the logic you have described in code.

If you want the first or to be treated as a single case, then use brackets around it.

if (len(content_tags) >= 1 or tags_irrelevant == 'yes')\
   and lengthproblem == 0\
   and guess_language.guessLanguage(testlanguage) == 'en'\
   and len(sentences) >= 3:

That said, you haven't given us a detailed explanation of the logical behaviour you want from this, so I'd suggest sitting down and working that out properly.

If you need to test your logic, then use a simple test function that prints out so you know what gets evaluated and when.

>>> def test(bool):
...    print(bool)
...    return bool
... 
>>> if test(1) or test(2) and test(3) and test(4) and test(False):
...    print("Success")
... 
1
Success
>>> if (test(1) or test(2)) and test(3) and test(4) and test(False):
...     print("Success")
... 
1
3
4
False

You can clearly see the first thing evaluated is the first and, then it tries to evaluate the left hand side of the and and so gets the or. It tries to evaluate this, gets True for the first value, and so short-circuits, returning True to the and, which also short circuits, returning True (well, actually 1, but True for the purposes of this example). When the brackets are there, it is evaluated in the way you wanted.

Upvotes: 1

Related Questions