# Programming logic

Martin McBride, 2018-07-24
Tags logical operator de morgan's law truthy value nested if statements tertiary if statement and or not precedence
Categories python language beginning python ## Introduction

In this lesson we will take a deeper look at programming logic and if statements, including:

• Logical operators
• De Morgan's law
• Truthy values
• Nested if statements
• Tertiary if statements

## Logical operators

Sometimes you might need to take more than one factor into account when you write an if statement. We use `and` and `or` operators to do this.

### The and operator

Suppose we wanted to make lemonade. You need lemons, of course, but that isn't all. You need sugar too. It isn't enough to just have sugar or lemons, you need both.

Here is how we test that there are enough lemons and sugar:

```lemons = 12
sugar_kg = 3

if lemons >= 10 and sugar_kg >= 2:
```

The code checks the number of lemons, and the amount of sugar, using the same type of comparison operators we have used before. The `and` operator ensures that the if block only runs if both conditions are true.

### The or operator

The `or` operator combines two comparisons and gives a true result if either (or both) values are true. Here is an example:

```day = 'monday'

if day == 'monday' or day == 'thursday':
print("It's bath night!")
```

In this case, the message will be printed if the day is Monday or Thursday.

### The not operator

Sometimes you need to check if something is not true. The `not` operator can do this. It inverts the sense of the test, swapping true and false. For example:

```if x >=1 and not x > 10:
print('a is between 1 and 10')
```

Of course, `not x > 10` is identical to saying `x <= 10`, you can choose either if you think one is easier to understand. `not` is sometimes useful, for example with truthy values as we will see later in this tutorial.

## Precedence

With an expression like this:

```x = a*3 + b*2
```

we know, of course, that the multiplications are calculated first, and then the addition. That is because multiplication has higher precedence than addition. The same principle applies to logical expressions:

```if lemons >= 10 and sugar_kg >= 2:
```

The comparison operators have higher precedence, so they are calculated first before the `and` is evaluated. The program first checks that there are enough lemons, and if there are, it also checks if there is enough sugar - if both are true, the print statement is executed.

Python is quite clever. If there are not enough lemons, it knows the answer will be false (because `and` cannot be true if the first term is false), so it doesn't waste time checking the amount of sugar. This is a very useful feature, called short circuit evaluation.

## Truthy values

Python has two special values, `True` and `False` that represent, as you would expect, true and false:

```if True:
print('This will always print')
if False:
print('This will never print')
```

In addition, Python has certain other values that count as `True` or `False`. These are called truthy values. The rules are fairly simple.

### Numbers

A numerical value counts as `False` if it is zero, `True` otherwise. So instead of this code:

```x = 3
if x!=0:
print('x is not zero')
```

You can write:

```x = 3
if x:
print('x is not zero')
```

Although this is optional, most Python programmers will naturally use the second method. When you get used to it, the first method will start to look a bit strange.

If you wanted to check if `x` is equal to 0, you can use `not`:

```x = 0
if not x:
print('x is zero')
```

### Collections

A collection is any type of data structure that holds other values. An example we have met already is the list type. A string is also a collection (a collection of characters).

As you learn more Python you will meet tuples, dictionaries, sets, and maybe a few more types.

The general rule is that a collection counts as `False` if it is empty, `True` otherwise.

So for example you should never do this:

```s = 'abc'
if len(s)!=0:
print(s)
```

It is better to do this:

```s = 'abc'
if s:
print(s)
```

### Others

Python has a special value `None` that can be used to represent no particular value. For example, if you want to create a variable but you don't yet know what its value should be, you can set it to `None`. In Python, `None` always counts as `False`.

Any other objects that aren't collections will normally count as `True`. This includes any types of object that you define yourself, unless you add code to change that behaviour.

## Nested if statements

Sometimes it isn't possible to fit the logic into a single if statement. Sometimes they need to be nested.

Imagine a fairground ride has a minimum and maximum height restriction. You can't use the ride if you are less than 1.2m tall, or greater than 1.7m tall. We could check that with code like this:

```print('How tall are you?')
height = float(input())
if height < 1.2:
print('You are not tall enough to use this ride')
elif height > 1.7:
print('You are too tall to use this ride')
else:
print('You can use this ride')
print('done')
```

We might enhance this code. If someone enters their height as 1.15, then they are almost tall enough to ride. You might want to suggest that they come back next year (as well as telling them they cannot ride).

```print('How tall are you?')
height = float(input())
if height < 1.2:
print('You are not tall enough to use this ride')
if height > 1.15:                             #1
print('Please come back next year')       #2
elif height < 1.7:
print('You are too tall to use this ride')
else:
print('You can use this ride')
print('done')
```

Notice that the new if statement (#1) is inside the block of the original if statement. It will only be called if the height is also less than 1.2, so it detects cases of the height between 1.15 and 1.2. Also, the print statement (#2) marks the end of both if statements, so the code indents move back 8 characters rather than just four.

In principle, you can nest if statement to depths of 3, 4, or whatever you need. But complex, nested if statements can be difficult to follow, and it is easy to make mistakes, which cause bugs. Later we will see how to create our own functions, which can help to make the code much easier to understand.

## Tertiary if statements

You will often find yourself writing code a bit like this:

```if x < 0:
s = 'negative'
else:
s = 'positive'
```

The pattern here is that we are setting `s` to one value or the other depending on the value of `x`. Python provides a neat way of doing this:

```s = 'negative' if x < 0 else 'positive':
```

You should generally consider using this, for several reasons:

• It is more readable because the form of the code makes the intent clear - you are setting a single variable `s` to one value or another depending on `x`.
• It is less error-prone. In the first form, you have to name `s` twice. You might accidentally type `t` the second time and introduce a bug.
• It is shorter.

Another more subtle advantage is that it is an expression. So you could avoid using the variable `s` altogether, for example, if you wanted to print the result:

```print('negative' if x < 0 else 'positive'):
```
If you found this article useful, you might be interested in the book Python Quick Start or other books by the same author.

#### Popular tags

2d arrays abstract data type alignment and animation arc array arrays bezier curve built-in function callable object circle classes close closure cmyk colour comparison operator comprehension context context manager conversion creational pattern data types design pattern device space dictionary drawing duck typing efficiency else encryption enumerate fill filter font font style for loop function function composition function plot functools game development generativepy tutorial generator geometry gif gradient greyscale higher order function hsl html image image processing imagesurface immutable object index inner function input installing iter iterable iterator itertools l system lambda function len line linspace list list comprehension logical operator lru_cache magic method mandelbrot mandelbrot set map monad mutability named parameter numeric python numpy object open operator optional parameter or partial application path polygon positional parameter print pure function pycairo radial gradient range recipes rectangle recursion reduce rgb rotation scaling sector segment sequence singleton slice slicing sound spirograph sprite square str stream string stroke subpath symmetric encryption template text text metrics tinkerbell fractal transform translation transparency tuple turtle unpacking user space vectorisation webserver website while loop zip