Motivating Example for Learning Python Conditionals, Logicals & Loops

Again we find ourselves in the role of a teacher in a class on geography. Each of your five students picked a country, and the following table was prepared based on their reports. Once again, Marie did not turn in her report.

Student Country GDP (billion USD) Population In Africa?
Mary Luxembourg 64.2 602005 False
Matthew Eritrea 6.856 4954645 True
Marie None None None None
Manuel Lesotho 2.721 2203821 True
Malala Poland 614.190 38433600 False

In the previous tutorials, we checked values or lists of values manually. With the skills we’ll develop in this tutorial, we will automate processing items in the table to eliminate missing elements and summarize the given information.


Introduction to Logicals, Conditionals & Loops

This introduction will walk through the basics of Python conditionals and logical expressions, including if statements and examples of their use with various data types. The section on loops will cover the basics of looping operations using Python’s while and for loops, and the simpler comprehensions. We will walk through the basics of Python flow control, specifically covering the following:

Want us to make more free Python tutorials? Share this article on Facebook and Twitter! When you spread the word on social media, you’re helping us grow so we can continue to provide free tutorials like this one for years to come.

Can't get enough Python?

Enter your email address for more free Python tutorials and tips.

Python is powerful! Show me more free Python tips

Python Logicals and Conditionals

This section will focus on the way Python processes logical through the use of if statements, Boolean operators, and other logical tests.

Boolean Operations & Value Comparisons

Operations on Python’s data types (Boolean, numeric, string, etc.) can be used to compare object values and perform logical operations. The following table contains Python’s logical operators:

Operator Operation
Equivalence (Equals) ==
Not Equal !=
Greater Than >
Less Than <
Greater Than or Equal To >=
Less Than or Equal To <=
And and
Or or
not not

Note that equivalence is defined as two equals signs ==, whereas assignment uses a single equals sign =. In other words, you use two equal signs to compare values and you use one equal sign to set a value equal to something.

Python Order of Operations

The following list is the order of operations from greatest precedence to lowest. Precedence just means the order in which the operations are processed. Items in the same group are evaluated in-line left to right.

  1. Parenthetical partitions: (), [], and {}
  2. in, not in, is, is not, <, <=, >, >=, !=, and ==
  3. not
  4. and
  5. or

Python evaluates the and statement using the shortcut technique of evaluating the statement on its left and determining if the output should be False prior to evaluating the right side. If the left side is False, then the right side is not evaluated and False is returned. For example:

print(None and False)
> None
print(False and None)
> False

Notice in the above statement that when a None object is evaluated with an and or or statement, the result will be a None. This is because Python will return the final evaluated argument for and or or:

print(True and "best")
> 'best'
print(False or "best")
> 'best'

Compound Comparisons

Python allows the use of compound value comparisons such as a < x < b which is equivalent to (a < x) and (x < b). For example:

x = 5
1 <= x < 10
> True
x = 10
1 <= x < 10
> False

Identity Comparisons: is Operator

One point of confusion to beginners of Python is the difference between the equivalence operator == and the object comparison operator is. If used to compare values, the two will behave identically:

15 == 15
> True
15 is 15
> True

However, this property can break down when comparing variables:

a = [1, 2, 3]
b = [1, 2, 3]
a == b
> True
a is b
> False

The reason is that == compares the value of the two given objects, and is compares the two objects themselves. Each object possesses its own unique identifier, which may be thought of as the object’s location in memory. Using the id(object) function we can determine the id’s of a and b:

id(a) # Note these values may be different on your device
> 1393032855176
id(b)
> 1393032854856

The object id’s of a and b are different, therefore a is b returned false. The values of the two objects are the same; they contain the same lists, therefore a == b returns true.

Membership Tests: in Operator

The a in b operator tests the membership of a within a given set b. The given set can be any sequence (list, tuple, string, etc.). If b is a string, then the expression will determine if a is a substring of b.

a = [1, 2, 3]
b = "The best of times."
1 in a
> True
4 in a
> False
"best" in b
True

Conditional Expressions: if Statements

If statements follow the format: if [condition]: [action]. If the condition evaluates to True, the the action is performed. If statements are standard in all programming languages, therefore this introduction will focus on Python’s implementation.

If statements can be either in-line for short tests, or can be extended over multiple lines.

if (1 < 2): print("That's true!")
> That's true!

If extended over multiple lines, Python uses tabs (or 4 spaces) to determine what lines are to be included in the [action] execution. If a Python terminal is used, then any line following a line ending with a colon : will start an additional line beginning with ... and a tab to indicate that a further lines are included in [action].

if (1 < 2): # Script style
    a = 15
    print(a)
> 15
>>> if (1 < 2): # Terminal style
...     a = 15
...     print(a)
...     # Extra line for additional input. If left blank, the entire block is run
> 15

Additional nested if statements use additional tabs (or spaces):

if (1 < 2): # Script style
    a = 15
    if (a == 15):
        b = 42
        print(b)
    print(a)
> 42
> 15

To evaluate multiple exclusive [condition] statements, the elif and else statements can be used. These statements have the following form:

if [condition 1]:
    [action 1]
elif [condition 2]:
    [action 2]
... # Additional elif statements can be inserted
else: 
    [Else action] # Else action is performed if none of the previous statements are true

If any previous previous if or elif [condition] does not evaluate to True, the the else [action] will be performed. Python does not include a native case statement, as multiple elif statements is equivalent to a case statement.

Suppose for the following example the following if block is constructed:

if x == 1:
    print("a")
elif x == 2:
    print("b")
elif x == 3:
    print("c")
else: 
    print("None of the above.")

If the x variable has an assignment prior to the above if statement block, then the following output will occur:

x = 1
... # Above if block
> 'a'
x = 2
... # Above if block
> 'b'
x = 5
... # Above if block
> 'None of the above.'

If any one of the if or elif conditions does evaluate to true, then the remaining elif of else statements in the block will be ignored. For example:

x = 12
if [x == 12]:
    print("a")
elif [x > 10]:
    print("b")
> 'a'

Notice in the above code that the elif statement was ignored, despite its condition evaluating to true. If multiple condition evaluations need to occur, then multiple if statements should be used:

x = 12
if x == 12:
    print("a")
if x > 10:
    print("b")
> 'a'
> 'b'
Can't get enough Python?

Enter your email address for more free Python tutorials and tips.

Python is powerful! Show me more free Python tips

Python Loops

Python’s loop control flows allow for the performance of a given action while a conditional expression holds true. In general loops follow the ` [loop] [condition]: [action] format, where the [loop] type performs a calculation for the [condition] expression that, while true, will perform the [action]`.

while Loops

The simplest application of the [loop] [condition]: [action] format is the while loop, which will continue to perform the [action] while the [condition] holds at the start of the loop. Like if statements, the [action] statement can be extended over multiple lines using tabs (or 4 spaces). For example:

x = True
while x:
    a = 15
    print(a)
    x = False # Setting x to false will cause the [condition] to fail
> 15

while can be extended over multiple iterations using counters:

x = 1
while (x <= 15):
    x += x
    print(x)
> 2
> 4
> 8
> 16

In the above example, the x variable is initially set to 1, and for each iteration of the while loop x is doubled and printed. At the end of the loop where x is 16, the condition (x <= 15) fails and the loop is exited.

Caution: If variables used within condition statement are not modified in the body of the loop, then an infinite loop can occur.

for Loops

for loops behave similar to while loops, however they have the form for [variable] in [sequence]: [action]. The for loop initializes the [variable] to be the first element of the given ordered [sequence], and will update the [variable] to be the next value of the sequence after the loop has completed an iteration. When all elements in the sequence have been exhausted, the loop will complete. For example:

for i in [0, 1, 2, 3, 4]:
    print(i)
> 0
> 1
> 2
> 3
> 4

As you can see from the above code, the i variable takes on a different value within the given list at each iteration of the print statement. Any of the ordered data structures we discussed previously can be used as a sequence, and sequences do not have to contain only numbers:

for i in ("The", "best", "of", "times."): # Tuple of strings
    print(i)
> The
> best
> of
> times.

The [variable] statement can also be used to “catch” tuples:

for (i, j) in [("The", "best"), ("of", "times.")]: # List of string tuples
    print(i + " " + j)  # + will concatenate strings
> The best
> of times.

A string is also an acceptable sequence:

for i in "abcd":
    print(i)
> a
> b
> c
> d

The most common form of for loops are those in which an integer is increased or decreased over a given range, like in our first example. Rather than preparing a list containing each of the integers, the range(a, b, k) function can be used to iterate over the range [a,b) in steps of k. If b is not included, the default will be 0, and if k is not included, the default will be 1.

for i in range(5): # Note that 5 will not be included
    print(i)
> 0
> 1
> 2
> 3
> 4
for i in range(0, 20, 5):
    print(i)
> 0
> 5
> 10
> 15

range will also accept negative ranges and steps for counting down. In this case, the range (b,a] in reverse order will be output.

for i in range(5, 0, -1):
    print(i)
> 5
> 4
> 3
> 2
> 1

Implicit Loops: Comprehensions

Suppose there is a sequence of objects in variable x, which need to be mapped to another sequence of objects in variable y. Rather than writing an entire for loop to perform this mapping, a comprehension can be used to quickly map elements in one line. This is performed by including the for statement in some sequence structure. The general format of these comprehensions are [open set] [output element] for [variable] in [input sequence] [close set] For example, suppose we have a list x of numbers and we want to create a new list y wherein each element is the square of each element in x:

x = [1, 2, 3, 4, 5, 6]
y = [i**2 for i in x]
print(y)
> [1, 4, 9, 16, 25, 36]

y is defined as a list using [open set] = [ and [close set] = ], sets the iterating [variable] as i, which iterates over the [input sequence] = x. Each element in the list will be [output element] = i**2, or the square of the values of the input. The comprehension doesn’t have to be for just lists. For example:

x = [1, 2, 3, 4, 5, 6]
y = {i**2 for i in x} # Outputs  a set
print(y)
> {1, 4, 36, 9, 16, 25}

Note: Suppose you want to generate a list of numbers in the range [1,11) with step size 1. You may think that this can be done using the following code1:

x = range(0, 11)
print(x)
> range(0, 11)

We see that the output is not a list, but unhelpfully, the range object itself. This is because the range function outputs a generator object rather than a list. The reason for this becomes clear if you consider wanting a loop to iterate over 1,000,000,000 elements. If range(1, 1000000000) created a list, then a 1,000,000,000 number list would need to be stored, taking up an enormous amount of memory. The generator object rather generates each number in range on-the-fly, and calculates a new value each time the object is iterated over. To generate the [1,11), you can use a list comprehension:

x = [i for i in range(0, 11)]
print(x)
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Loop Operations: break Statement

The break statement will cause the loop to be exited when executed. break statements are valuable in search-type loops, where once a value is found, no further values in the loop need to be executed. For example:

for i in range(5):
    if i == 3:
        break
    print(i)
> 0
> 1
> 2

When variable i is updated to the value of 3, the if statement within the for loop is satisfied, and the break statement is executed. Because the loop is broken, no additional numbers are printed.

Loop Operations: continue Statement

The continue statement tells Python to start back at the top of a loop and update the variable if it is a for loop. For example:

for i in range(5):
    if i == 2 or i == 3:
        continue
    print(i)
> 0
> 1
> 4

When variable i is updated to the value of 3 or 2, the if statement within the for loop is satisfied, and the continue statement is executed. The loop is restarted with a new index and continued, eventually reaching the end of the given range.

Can't get enough Python?

Enter your email address for more free Python tutorials and tips.

Python is powerful! Show me more free Python tips

Python Conditionals Examples

Suppose we want to apply the skills we’re learned to the motivating example at top. We can store the table above as a list of lists using the following definition:

table = [["Mary", "Luxembourg", 64.2, 602005, False],
         ["Matthew", "Eritrea", 6.856, 4954645, True],
         ["Marie", None, None, None, None],
         ["Manuel", "Lesotho", 2.721, 2203821, True],
         ["Malala", "Poland", 614.190, 38433600, False],
        ]

Now we can use loops and logicals to determine properties of the given information. First we will want to screen out any spurious entries that may cause errors in analysis down the line. Knowing that missing data was represented as None, we can easily determine if any of the reports is missing by summing the number of None cases.

missing_count = 0
for row in table:
    if row[4] is None:  
        missing_count += 1
print(missing_count)
> 1

Now suppose we wanted to check the total number of None objects within the table. We can use a nested set of for loops:

none_count = 0
for row in table:  
    for item in row:  
        if item is None:  
            none_count += 1
print(none_count)
> 4

Now that we’ve determined that the table has missing data, we can use a loop to create a new cleaned data set:

clean_table = []  #Creating an empty list
for row in table:
    if None not in row:  
        clean_table.append(row)
print(clean_table)
> [['Mary', 'Luxembourg', 64.2, 602005, False],
>  ['Matthew', 'Eritrea', 6.856, 4954645, True],
>  ['Manuel', 'Lesotho', 2.721, 2203821, True],
>  ['Malala', 'Poland', 614.19, 38433600, False]]

Note that in the above example, we had to create an empty list [] before we can append an element to it. If we did not first define the table, then the program would have raised an error that the clean_table variable was undefined.

We can count the number of countries within the continent of Africa using the following:

country_count = 0
for entry in clean_table:
    if entry[4]:  #Checks if the "In Africa?" Boolean is True:
        country_count += 1
print(country_count)
> 2

We can now quickly determine the mean population and GDP of the cleaned table using list comprehensions:

GDP = [row[2] for row in clean_table]
population = [row[3] for row in clean_table]
mean_GDP = sum(GDP)/len(GDP)
mean_pop = sum(population)/len(population)
print([mean_GDP, mean_pop])
> [171.99175000000002, 11548517.75]

Remember that the trailing 2 in mean_GDP is a result of binary to decimal conversion, and should be disregarded. The round function can be used to display only the significant figures of the output.


Python Logicals & Loops Exercises

  1. What is the output of the following code?
x = range(5)
y = [2*i for i in x]
z = []
for i in x:
    for j in y:
        if i > j:
            z.append(i)
print(z)

    Solution
2. Are the following two strings x and y anagrams? (Hint: use dictionaries)

x = "iddujossuupoofapfdaposffoisiuijjdoaasopfhlpfiiuspffoddaufdau"
y = "ojdflsahdfiujofasdjfupofaupoidusfpaoisudfposaidufpoipoasdifu"

    Solution
3. In our second example on the geography class, we used the following conditional statement to determine if there were any None objects within the table:

if entry[4] is None:

Could we have used an == operator instead of a is operator? Why or why not? What is the difference between them?     Solution
4. Use a loop to calculate the sum of all numbers from 1 to 100.     Solution
5. What is the output of the following expression? x is an unknown Boolean.

(True and ((not True or ("True" in "False")) and x)) and x

    Solution


Solutions

1.

x = range(5)  # Create a generator for a range [0,4]
y = [2*i for i in x] # double the elements in x: [0, 2, 6, 8]
z = []  # Create an empty list z
for i in x:  #iterate through [0,4]
    for j in y: #iterate through [0, 2, 6, 8]
        if i > j: # If an element in x is greater than a doubled value in y
            z.append(i)  # Add that element to z
print(z)
> [1, 2, 3, 3, 4, 4]

2. Dictionaries can be used to tally the number of each unique letter. Comparing the final dictionaries will determine if the strings are anagrams.

x = "iddujossuupoofapfdaposffoisiuijjdoaasopfhlpfiiuspffoddaufdau"
y = "ojdflsahdfiujofasdjfupofaupoidusfpaoisudfposaidufpoipoasdifu"
dx = dict()  # Make empty dictionaries
dy = dict()  
for c in x:
    if c in list(dx):
        dx[c] += 1
    else:
        dx[c] = 1
for c in y:
    if c in list(dy):
        dy[c] += 1
    else:
        dy[c] = 1
dx == dy  # Compare dictionaries
> True

The two strings are anagrams.

3. In this situation, the functionality of is is the same as ==, as the value of a None object will be the same as any None object, and the id of a None object will be the same as any other pointer to the None object. The is statement compares object id’s, whereas == compares object values.

4.

s = 0
for i in range(1, 101):
    s += i
print(s)
> 5050

5. False. Despite not knowing the value of x, the and shortcut functionality will not evaluate any of the x variables.


Did you find this free tutorial helpful? Share this article with your friends, classmates, and coworkers on Facebook and Twitter! When you spread the word on social media, you’re helping us grow so we can continue to provide free tutorials like this one for years to come.

  1. And in Python Version 2 you would be correct. In Python Ver. 2, the range function does output a list, while the xrange function outputs a generator. In Python Ver. 3, which this tutorial assumes, the range function replicates the functionality of the xrange function.