Conditions

Sometimes, often while looping, you only want to do things depending on something’s value. Specifying conditions like this is pretty simple in Python.

>>> pizzas = ['Pineapple', 'Cheese', 'Pepperoni', 'Hot dog']
>>> for p in pizzas:
...     if p == 'Cheese':
...         print('Nice pizza!')
...     elif p == 'Pepperoni':
...         print('Amazing pizza!')
...     else:
...         print('Weird pizza.')
...
Weird pizza.
Nice pizza!
Amazing pizza!
Weird pizza.

Like the “body” of the for loop, called a block, the block in the if, elif, and else statements must be indented. The convention we adopt is to use four spaces for indentation.

The if statement starts with if (duh!) and what follows is a condition. If this condition isn’t met, the next elif (for “else-if”) condition is evaluated. If this also isn’t met, the else block is run. You can use as many elif conditions as you like, or none at all, and the else block is optional.

Ternary conditional operator

You can use a succinct one-line syntax for conditional assignments like this:

>>> x = 'ok' if pizzas[0] == 'Cheese' else 'not ok'
>>> x
'not ok'

Make sure your line does not get too long in order not to impair its readability!

Python evaluates a condition and sees whether it is truth-like or not. If it is truth-like, the code in the block is run.

>>> if pizzas[0] == 'Cheese':
...     print('It is cheese, my dudes.')
...
>>> pizzas[0] == 'Cheese'
False
>>> pizzas[1] == 'Cheese'
True

False and True are variables and they can actually be reassigned to some other value (though it is quite pointless and dangerous to do that!) They correspond to the possible values a boolean variable can have. Here is why you should never touch those variables:

>>> True = 1
>>> True
1
>>> True = False
>>> True == False
True

The result of a comparison is True or False, and we can perform comparisons using several operators, like == for equality, != for inequality, > and < for relative magnitude, and so on.

>>> True, False
(True, False)
>>> False
False
>>> True == False
False
>>> True != False
True
>>> 1 > 2
False
>>> (1 > 2) == False
True

This shows that we can combine comparison operators, just like with + and friends. We can also use and to require multiple conditions, or to require at least one, and not to negate a result.

x = 2
>>> 1 < x and x < 3
>>> 3 < x or 1 < x
True
>>> not 1 < x
False

Note that and, or and not have lower precedence than >, < and ==, but you can use parentheses to be more explicit.

Of course, we can compare everything we have played around with so far.

>>> x = [1, 2]
>>> y = [1, 2]
>>> z = {'hero': 'thor'}
>>> x == y
True
>>> y == z
False

For collection objects like lists, tuples, and dictionaries, we can easily ask them if they contain something in particular using the in operator.

>>> 3 in x
False
>>> 2 in y
True
>>> 'thor' in z
False

The last statement is False because in queries a dictionaries keys, not its values. This is useful if you want to access a key in a dictionary that might not exist:

>>> z['pizza']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'z' is not defined
>>> if 'pizza' in z:
...     print('We have pizza', z['pizza'])
... else
...     print('No pizza :(')

Note that in doesn’t dive into nested collections, but only looks at the top level.

>>> 1 in [[1, 2], [3, 4]]
False
>>> [1, 2] in [[1, 2], [3, 4]]
True

The in operator

Find the double-underscore method on lists and dictionaries that corresponds to the in operator, and check that it does the same thing as the operator.

Solution

Taking lists as an example, the dir method can tell us what methods are available. The __contains__ method sounds promising.

>>> x= [1]
>>> x.__contains__(1)
True
>>> x.__contains__(2)
False

Strings work a lot like lists, which makes sense because they are effectively collections of single characters. This means we can also query string contents with in.

>>> fact = 'The best hero is Thor.'
>>> 'Thor' in fact
True
>>> 'Iron Man' in fact
False

Truthiness

It’s conventional not to explicitly compare a condition to True, because the if statement already does that for us.

>>> if ('Pineapple' in pizzas) == True:
...     print('Weird.')
...
>>> if 'Pineapple' in pizzas:
...     print('Not weird.')
...

Likewise, rather than comparing for False, we just use not.

>>> if ('Pineapple' in pizzas) == False:
...     print ('Weird.')
...
>>> if not 'Pineapple' in pizzas:
...     print ('Not weird.')
...
>>> not 'Pineapple' in pizzas:
>>> 'Pineapple' not in pizzas:

The last two lines show that we can use not in for checking that something is not in a collection. This reads more naturally.

All Python objects are truth-like unless they are the value False, the value None, or are empty collections (such as "", [], (), {}).

>>> if list() or dict() or tuple() or str():
...     print ("You won’t see me!")

The value None, which is available as the variable named None, is often used as placeholder for an empty value.

>>> favourite = None
>>> for p in pizzas:
...     if 'Olives' in p:
...         favourite = p
...
>>> if favourite:
...     print ('Found favourite: {0}'.format(favourite))
... else:
...     print ('No favourite :(')
No favourite :(

It behaves as false-y value in conditions.

Conditions in loops

for loops and comprehensions are the most common ways of iterating in Python. We’ve already seen that using conditions in these can be useful.

>>> not_cheesy = [p for p in pizzas if 'cheese' not in p.lower()]
>>> not_cheesy
['Pineapple', 'Pepperoni', 'Hot dog']

Another way of iterating is with while.

>>> i = 5
>>> while i > 0:
...     print 'T-minus {0} seconds'.format(i)
...     # Equivalent to `i = i - 1`
...     i -= 1
... print ('Blast off!')
T-minus 5 seconds
T-minus 4 seconds
T-minus 3 seconds
T-minus 2 seconds
T-minus 1 seconds
Blast off!

The while loop checks the condition, runs the block, and then re-checks the condition. If we don’t do something in the loop to change the result of the condition, we will end up looping forever!

>>> i = 5
>>> while i > 0:
...     print('All work and no play makes Jack a dull boy')

Because we do not change the value of i in the loop, the condition always evaluates to True, so we’re stuck. You can stop Python running the code by typing the Ctrl-c key combination.

Sometimes you want to stop iterating when some condition is met. You could achieve this with a while loop.

>>> ok = False
>>> i = 0
>>> while not ok:
...     ok =  'cheese' in pizza[i].lower()
...     # Equivalent to `i = i + 1`
...     i += 1
...
>>> i
2
>>> pizza[i - 1]
'Cheese'

It is not nice to have to keep track of these ok and i variables. Instead, we can use a for loop, which feels much more natural when iterating over a collection, and break to stop looping.

>>> for pizza in pizzas:
...     if 'cheese' in pizza.lower():
...         yum = pizza
...         break
...
>>> yum
'Cheese'