Decision making with conditionals
After this vast amount of introductory articles with the basic types of variables in Python 3, it is time to go on and introduce conditional operators which help us create an application flow based on different conditions at runtime.
Until now we only had one flow: starting the application, requiring user input (perhaps) and displaying one result. With conditionals this changes. Based on the input or other parameters created at runtime (you know, sometimes no input is required) we can output different results.
Let’s see a simple example of the “game” FizzBuzz.
The description of the game is very simple: if a number is divisible with 3 then we display “Fizz”, when it is divisible with 5 then we display “Buzz”, when the number is divisible with 3 and 5 we display “FizzBuzz”; otherwise we display the number.
Let’s save the following code into a file called fizzbuzz.py:
n = int(input("Enter a number: "))
if n%15 == 0:
print("FizzBuzz")
elif n%3 == 0:
print("Fizz")
elif n%5 == 0:
print("Buzz")
else:
print(n)
As you can see, this application is a bit limited now because it executes only once when started but in the next article I will introduce loops and then we will be unstoppable and can write applications which run and run and run and… I hope you get the idea.
If I run the application some sample output would be like the following:
MB:examples GHajba$ python3 fizzbuzz.py
Enter a number: 5
Buzz
MB:examples GHajba$ python3 fizzbuzz.py
Enter a number: 6
Fizz
MB:examples GHajba$ python3 fizzbuzz.py
Enter a number: 2
2
MB:examples GHajba$ python3 fizzbuzz.py
Enter a number: 45
FizzBuzz
About conditionals
Conditionals change the application flow based on certain conditions. Most of the time this is based on the value of some certain variables, sometimes on the input. This all depends how your application is designed.
Some developers say it is hard to write an application without having branches in the application-flow. Well, we have seen that it is possible but this reduces the user experience a way which is not good. It would be better to have branches based on conditions which would alter the programming state.
The above showed “FizzBuzz” example is a nice script which shows that with branching we can do a lot of difference when coding.
The above example covers, however, the same program flow of the if-then-else construct in Python. The if statement requires an expression which has to evaluate to True or False. If the expression evaluates to True then the code block after this statement is executed. If the statement evaluates to False then this block is skipped.
The elif statements requres again a statement which evaluates to True or to False and is evaluated only if the previous statement was evaluated to False. Otherwise this block is not even evaluated.
The else block executes if the previous if block and all previous elif blocks evaluated to False. Here is no need for any statement to evaluate. The else block is the default case if all previous expressions evaluated to False.
The basic construction of a conditional block is as follows:
- One if block
- Zero to any elif blocks
- Zero or one else block
This means that an if block has to be present always. However this if block does not have to be followed by any elif or else statements. However you cannot have elif or else blocks on their own, without an if block.
if conditional_expression_1:
statement_block_1
elif conditional_expression_2:
statement_block_2
else:
statement_block_3
And if you have multiple if statements then both of them are evaluated. This means for the “FizzBuzz” example you cannot use simple if blocks. That’s because in this case every if statement would be evaluated and would result in a result you do not expect.
n = int(input("Enter a number: "))
if n%15 == 0:
print("FizzBuzz")
if n%3 == 0:
print("Fizz")
if n%5 == 0:
print("Buzz")
else:
print(n)
MB:examples GHajba$ python fizzbuzz_wrong.py
Enter a number: 15
FizzBuzz
Fizz
Buzz
MB:examples GHajba$ python fizzbuzz_wrong.py
Enter a number: 3
Fizz
3
The above code sample demonstrates that every if block is evaluated and the last else is executed only if the previous if block evaluates to False.
The life is not just True or False
Some say unfortunately, others think the opposite, because boolean conditions are not only True or False. With Python 0 evaluates to False in every case and every other number to True.
The same goes for collections (and strings of course too). If a collection is empty then it evaluates in a conditional statement to False, in any other case to True.
None evaluates always to False.
This is why some people say that it is hard to write conditionals in Python. But it always depends on the developers taste. The “Zen of Python” states that
Explicit is better than implicit.
However in this case sometimes implicit is slightly even better. This means that you can avoid constructs like these:
if len(l) == 0:
# do something
if a == 0 or a is None:
# do something else
And replace them with these ones:
if not l:
# do something
if not a:
# do something else