This post references the 'problem' caused by multiple conditional statements in Python code; it's a frequent question on Stack Overflow with many questions on the topic. e.g "What's the best way to format multiple if conditions in Python?"
This is a simple example of the issue:
if test == 'wrong' and test2 == 'test2' and test3 == 'test3' and test4 == 'test4': # Do something.
Long lines that not only go against PEP8's 80 char rule but are generally hard to read and messy to play with.
This post is actually about one solution to this which I frequently see being suggested with no caveats. and that's the only problem really: it has a pretty big caveat. The solutions in question uses the all() built-in (around since Python 2.5) to take in an iterable of pre-defined conditions; the all built-in then loops through each item and will return
False as soon as one of the items evaluates to
False. Sounds great right? Let's see it in action:
rules = [test == 'wrong', test == 'test2', test == 'test3', test == 'test4']: if all(rules): # Do something.
You'd be forgiven for thinking the first and second examples here give the same result: mostly because they do. It's how they go about it which differs. The first will test
test == 'wrong' and return
False, it will never evaluate the other conditionals after the
and. This is called short-circuit evaluation and is common in many programming languages as a form of optimisation and as a control structure.
You probably see where I'm going with this now: the second example will evaluate all the conditionals on instantiation of the list and then loop through them checking for that boolean status. For the example the speed difference is minuscule and can almost be ignored; however, if your conditions were a bit more resource heavy this could quickly become a problem; it also becomes an issue in cases where a conditional should be required before checking another one - usually this is simply sorted by ordering but as all the conditionals are run with this method, that does not work.
The same obviously applies to replacing
or statements with the
any() built-in in a similar fashion. I hesitated in putting 'gotcha' in the title because I don't think it really classes as such as it's fairly easy to understand why it acts this way - it's just good to point out to anyone new to this pattern.