Programming Workshop for Beginners

Day 1: Laying the foundation

Saturday, June 23, 2018

University of Waterloo

Review from yesterday

  1. Data Types (string, int, float)

  2. Putting data into variables

  3. Simple data operations and manipulation

Schedule

10:00 - 11:00: Work
11:00 - 11:10: Break
11:10 - 12:30: Work

12:30 - 13:30: Lunch
13:30 - 17:00: Work & Project

Welcome to Day 1

Here's what we're going to cover today:

  1. Lists
  2. Conditions
  3. Talking to the user using input()
  4. Repeating steps with for loops

Slides available online at:

  • http://uwpyb.github.io/materials/lectures/day_1.slides.html#/

Or if you want a shorter URL:

  • http://goo.gl/7GtZqx

Lists: shelves full of items

Building a list

In [1]:
groceries = ["apples", "blueberries", "chocolate"]
print(groceries)
type(groceries)
['apples', 'blueberries', 'chocolate']
Out[1]:
list

Getting a single thing from lists using an index

In [2]:
# 0 is the index
print(groceries[0])
apples
In [3]:
print(groceries[2])
chocolate
In [4]:
print(groceries[-1])
chocolate

What is the result of running the code print(groceries[3])?

a) Error
b) Chocolate
c) Apples

In [5]:
groceries[3]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-5-87080ad480f6> in <module>()
----> 1 groceries[3]

IndexError: list index out of range

Getting multiple things from a list

In [6]:
groceries
Out[6]:
['apples', 'blueberries', 'chocolate']
In [7]:
# go from 1 and stop before 3
print(groceries[1:3])
print(groceries[0:2])
['blueberries', 'chocolate']
['apples', 'blueberries']

Given the following list:

In [8]:
groceries
Out[8]:
['apples', 'blueberries', 'chocolate']

What is the result of groceries[0:3]:

a) IndexError

b) ['blueberries', 'chocolate']

c) ['apples', 'blueberries', 'chocolate']

In [9]:
groceries[0:3]
Out[9]:
['apples', 'blueberries', 'chocolate']

We can change elements of a list:

In [10]:
groceries
Out[10]:
['apples', 'blueberries', 'chocolate']
In [11]:
groceries[2] = "cranberries"
print(groceries)
['apples', 'blueberries', 'cranberries']

len() is a function so you can put stuff into it (in between the parentheses) to get some useful information out. In this case, the total amount of items in the list (also called length of a list):

In [12]:
len(groceries)
Out[12]:
3

As you saw yesterday, we can do similar things with strings!

In [13]:
major = "biochem"
print(major[0])
b
In [14]:
print(major[-1])
m
In [15]:
len(major)
Out[15]:
7

But with strings, you can't change parts of them afterwards:

In [16]:
major[3] = "t"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-16-3191c5776024> in <module>()
----> 1 major[3] = "t"

TypeError: 'str' object does not support item assignment

List Operations

Things we can do with two or more lists:

In [17]:
drinks = ["pop", "water", "juice"]
food = ["apple", "pear", "bread"]
In [18]:
drinks = ["pop", "water", "juice"]
food = ["apple", "pear", "bread"]

Since "apple" + "water" gives "applewater" what will drinks+food do?

a) Give an error

b) ["pop", "water", "juice", "apple", "pear", "bread"]

c) ["popapple", "waterpear", "juicebread"]

In [19]:
drinks = ["pop", "water", "juice"]
food = ["apple", "pear", "bread"]

Since "apple" * 3 gives "appleappleapple" what will drinks * 2 do?

a) Give an error

b) ["poppop", "waterwater", "juicejuice"]

c) ["pop", "water", "juice", "pop", "water", "juice"]

Note: we can't subtract lists or strings (we get a TypeError)

In [20]:
drinks - food
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-20-d36cb77699c5> in <module>()
----> 1 drinks - food

TypeError: unsupported operand type(s) for -: 'list' and 'list'

Python finds out the truth: comparisons

In [21]:
5 > 3
Out[21]:
True
In [22]:
5 != 2
Out[22]:
True
In [23]:
5 == 5
Out[23]:
True
In [24]:
"pants" == "face"
Out[24]:
False
In [25]:
(5 == 5)
Out[25]:
True
In [26]:
res = 5 == 5
print(res)
res = (5 == 5)
print(res)
type(res)
True
True
Out[26]:
bool

What will be the result of:

participants = 33
print(participants >= 33)

a) True
b) False
c) Error

In [27]:
participants = 33
print(participants >= 33)
True

Combining comparisons

What if we want to find a number in a range?

In [28]:
num = 5

print(num < 10)
print(1 < num)
print(1 < num and num < 10)
True
True
True

What will the statment below return:

name = "Ivana"
print(name == "Ivana" or name == "Sean")

a) False

b) True

Given not flips/invert the result, what will the statment below return:

num = 5
print(num > 1 and not num == 5)

a) False

b) True

Python finds out the truth: membership

In [29]:
"a" in "face"
Out[29]:
True
In [30]:
"b" in "pants"
Out[30]:
False
In [31]:
"ice" in ["I", "scream", "for", "ice", "cream"] 
Out[31]:
True

What will be the result of:

"put" in "computer"

a) True
b) False
c) Error

In [32]:
"put" in "computer"
Out[32]:
True

Conditions

Using comparisons to do one thing or another, depending on some condition

In [33]:
weather = "sunny"
# the colon: important!
# the indentation: also important!
if weather == "sunny":
    print("Go for a walk!")
else:
    print("Do your work!")
Go for a walk!

You can add more code inside the weather == "sunny" block and the else block, as long as it's indented in the same way.

In [34]:
weather = "sunny"

if weather == "sunny":
    print("Go for a walk!")
    print("Eat ice cream!")
    print("Fix the air conditioner!")
else:
    print("Do your work!")
Go for a walk!
Eat ice cream!
Fix the air conditioner!

What will happen if we move print("Eat ice cream!") to the end and remove the indentation?

weather = "sunny"

if weather == "sunny":
    print("Go for a walk!")
    print("Fix the air conditioner!")
else:
    print("Do your work!")
print("Eat ice cream!")

a) Print out just Go for a walk! and Fix the air conditioner!
b) Print out Go for a walk!, Fix the air conditioner! and Eat ice cream!
c) Error

In [35]:
weather = "sunny"

if weather == "sunny":
    print("Go for a walk!")
    print("Fix the air conditioner!")
else:
    print("Do your work!")
print("Eat ice cream!")
Go for a walk!
Fix the air conditioner!
Eat ice cream!

And now we always get the message about ice cream, whether the weather is sunny or rainy.

It turns out that the else block is optional.

In [36]:
weather = "rainy"

if weather == "sunny":
    print("Go for a walk!")
    print("Fix the air conditioner!")
    
print("Eat ice cream!")
Eat ice cream!

What if you want to go for a walk when it is either sunny or cloudy?

In [37]:
weather = "sunny"
if weather == "sunny" or weather == "cloudy":
    print("Go for a walk!")
else:
    print("Do your work!")
Go for a walk!

Trick question: what will the statement below print:

weather = "rainy"
if weather == "sunny" or "cloudy":
    print("Go for a walk!")
else:
    print("Do your work!")

a) Go for a walk!

b) Do your work!

c) Error

In [62]:
weather = "rainy"
if weather == "sunny" or "cloudy":
    print("Go for a walk!")
else:
    print("Do your work!")
Go for a walk!

Why?

As far as Python is concerned, the left side of the or and the right side are completely unconnected, so it forgets about the weather variable.

"cloudy" by itself is not a bool. But if it's inside an if statement, Python will convert it.

In [38]:
bool("cloudy")
Out[38]:
True
In [39]:
if "waefuibwehp":
    print("Computers are dumb.")
else:
    print("Computers are smart.")
Computers are dumb.

What if your only day off is Saturday?

In [40]:
weather = "sunny"
today = "Saturday"
if weather == "sunny" and today == "Saturday":
    print("Go for a walk!")
else:
    print("Do your work!")
Go for a walk!

Mini-exercise: What if there are a few kinds of weather where you can take a walk? Fill in the blank:

weather = "snowy"
decent_weather = ["sunny", "cloudy", "snowy"]
if BLANK:
    print("Go for a walk!")
else:
    print("Do your work!")

You may have done something like this:

weather = "snowy"
decent_weather = ["sunny", "cloudy", "snowy"]
if weather == decent_weather[0] or weather == decent_weather[1] or weather == decent_weather[2]:
    print("Go for a walk!")
else:
    print("Do your work!")

But you should also keep this option in mind:

weather = "snowy"
decent_weather = ["sunny", "cloudy", "snowy"]
if weather in decent_weather:
    print("Go for a walk!")
else:
    print("Do your work!")

Talking to People

In [41]:
name = input("What's your name? ")
print("Hello " + name)
What's your name? Ryan
Hello Ryan

How would you find what kind of data type is returned by input?

In [42]:
type(name)
Out[42]:
str

What will the following code do, if the user enters 2 when prompted?

age = input("How old are you? ")
print(age + 7)

a) Print 9

b) Print 27

c) Error

In [43]:
age = input("How old are you? ")
print(age + 7)
How old are you? 2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-43-e3b7d5a83e38> in <module>()
      1 age = input("How old are you? ")
----> 2 print(age + 7)

TypeError: must be str, not int

Mini-exercise: middle letter

Ask the user for a word, then print out the middle letter from that word.

For instance,

Enter a word: racecar
The middle letter is e

For a word with an even number of letters, either of the middle 2 is fine.

Hint: to round down from a float like 1.4 to an int like 1, we can do int(1.4).

Solution

In [45]:
word = input("Enter a word: ")
middle_index = int(len(word) / 2)
print("The middle letter is", word[middle_index])
Enter a word: racecar
The middle letter is e

Example: Online shopping cart

In online stores, there is always a "shopping cart" that shows the subtotal of the items being purchased.

The total cost is the subtotal + any shipping costs and other fees.

Let's examine a program that asks a person what their subtotal is, and gives them free shipping if they order more than $50.

In [46]:
user_input = input("Enter your subtotal: $")
subtotal = float(user_input)

if subtotal >= 50:
    shipping = 0
else:
    shipping = 15
    
print("Shipping cost: $" + str(shipping))    

total = subtotal + shipping

print("Your total comes to: $" + str(total))
Enter your subtotal: $56
Shipping cost: $0
Your total comes to: $56.0

Mini-exercise: Coupon codes

Modify the shopping cart so that it asks the user if they have a coupon.

If they enter SAVE10, it should take 10% off of their subtotal.

Enter your subtotal: $60
Enter a coupon code (or leave blank to skip): SAVE10
Coupon discount: $6.0
Shipping cost: $0
Your total comes to: $54.0

If they don't, the program works like before.

Enter your subtotal: $60
Enter a coupon code (or leave blank to skip): 
Shipping cost: $0
Your total comes to: $60.0

Exercise: Pizzeria

A person puts in the number of slices they want, and how much money they have. A slice of pizza costs $1.50, and the program calculates the total cost of the slices. If the person doesn't have enough money, they must try again. If they do have enough money, their change is calculated.

Here are the lines of code you'll need. Put them in the right order and with the right indentation!

slices = int(slices_input)

print("Here is your change:", change)

slices_input = input("Enter how many slices of pizza you want:")

if total_cost > money:

else:

print("You do not have enough money to buy this much pizza!")

total_cost = slices * 1.5

money_input = input("Enter how many dollars you have: ")

money = int(money_input)

change = money - total_cost

In [47]:
slices_input = input("Enter how many slices of pizza you want: ")
money_input = input("Enter how many dollars you have: ")
slices = int(slices_input)
money = int(money_input)
total_cost = slices * 1.5
if total_cost > money:
    print("You do not have enough money to buy this much pizza!")
else:
    change = money - total_cost
    print("Here is your change:", change)
Enter how many slices of pizza you want: 12
Enter how many dollars you have: 30
Here is your change: 12.0

Repeating actions

Problem: we want to do something a certain number of times or we want to do something to each element of a list

In [48]:
names = ["Sean", "Mariah", "Jasmine", "Sajed", "Ivana"]
In [49]:
print("Hi five " + names[0])
print("Hi five " + names[1])
print("Hi five " + names[2])
print("Hi five " + names[3])
print("Hi five " + names[4])
Hi five Sean
Hi five Mariah
Hi five Jasmine
Hi five Sajed
Hi five Ivana

But this is very repetitive and boring. Is there a more efficient way to do this?

There is! We can use a for loop:

In [50]:
names
Out[50]:
['Sean', 'Mariah', 'Jasmine', 'Sajed', 'Ivana']
In [51]:
for name in names:
    print("Hi five " + name)
Hi five Sean
Hi five Mariah
Hi five Jasmine
Hi five Sajed
Hi five Ivana

Let's take a closer look at how for loops work.

for loop

So we just saw that we have these two programs that do the same thing, with and without a loop. We converted from a long form into a short, loopy form:

print("Hi five " + names[0])
print("Hi five " + names[1])
...

to

for name in names:
    print("Hi five " + name)

As a little exercise, let's look at a different program and try going backwards, starting in loop form and going to long form.

In [52]:
# let's convert this from loopy form to long form
numbers = [1, 2, 3, 4]
for x in numbers:
    print(x + 10)
11
12
13
14

In long form, this might look something like...

In [53]:
numbers = [1, 2, 3, 4]
print(numbers[0] + 10)
print(numbers[1] + 10)
print(numbers[2] + 10)
print(numbers[3] + 10)
11
12
13
14

Which form is "better": long form, or loopy form?

The result is the same either way, so maybe they're equivalent.

But you might find that loops are a bit more flexible.

What if we wanted to change the number of things in the collection numbers?

numbers = [1, 2, 3]

print(numbers[0] + 10)
print(numbers[1] + 10)
print(numbers[2] + 10)
print(numbers[3] + 10) # error

vs.

numbers = [1, 2, 3]
for x in numbers:
    print(x + 10)

Long form errors out, but loop form works fine. The loop knows how many times it needs to run.

What about setting numbers = [1, 2, 3, 4, 5]?

Long form is a tool for understanding.

But in practice, loop form is almost always better.

What would happen if we tried to loop over a single string instead of a list?

pet1 = "kitty"
for char in pet1:
    print(char)

a) Print out the letters k, i, t, t, y, one per line
b) Print out just kitty
c) Error

Strings are kinda like a list of characters, so the for loop takes them one at a time.

In [54]:
pet1 = "kitty"
for char in pet1:
    print(char)
k
i
t
t
y

Check out this similar word.

In [55]:
pet2 = "doggy"
for char in pet2:
    print(char)
d
o
g
g
y

It kind of prints the word in a column. What if we wanted to print the two words together, in columns side-by-side?


k d
i o
t g
t g
y y

Let's start by writing the program in long form:

In [56]:
pet1 = "kitty"
pet2 = "doggy"

print(pet1[0], pet2[0])
print(pet1[1], pet2[1])
print(pet1[2], pet2[2])
print(pet1[3], pet2[3])
print(pet1[4], pet2[4])
k d
i o
t g
t g
y y

Tough Exercise:

Convert the above into loop form.

Here's a start:

pet1 = "kitty"
pet2 = "doggy"

for x in BLANKBLANKBLANK:
    print(BLANKETYBLANK)

There is a hint on the subslide if you have trouble starting.

Hint:

If you wanted to make a loop that prints off

0
1
2
3
4

how would you do that?

Instead of printing the number itself, is there something more useful we could do with it?

Solution

You may have come up with this solution:

In [57]:
pet1 = "kitty"
pet2 = "doggy"

for x in [0, 1, 2, 3, 4]:
    print(pet1[x], pet2[x])
k d
i o
t g
t g
y y

It might look a bit abstract, but it works!

But if we change the words to something longer or shorter, [0, 1, 2, 3, 4] might not cut it.

Luckily, Python has a built-in function to make this list of numbers: range(). Let's try it out:

In [58]:
for x in range(3):
    print(x)
0
1
2

So, for kitty/doggy, we'd use range(5).

Mini-Exercise

Fill in the BLANK so that this works for any pair of words of the same length:

pet1 = "cat"
pet2 = "dog"

# or
# pet1 = "kitty"
# pet2 = "doggy"

num_letters = BLANK
for x in range(num_letters):
    print(pet1[x], pet2[x])

We use the len function to do this, since it counts the number of letters in a word.

In [59]:
pet1 = "cat"
pet2 = "dog"

# or
# pet1 = "kitty"
# pet2 = "doggy"

num_letters = len(pet1)
for x in range(num_letters):
    print(pet1[x], pet2[x])
c d
a o
t g

Exercise: counting vowels

A person enters a word. The program checks each letter and tallies up the number of vowels it sees, printing out the final count.

Here are the lines of code you'll need. Put them in the right order and with the right indentation!

if character in vowels:

print(word, "has", total, "vowels.")

vowels = "aeiou"

total = total + 1

word = input("Enter a word: ")

for character in word:

total = 0

In [60]:
word = input("Enter a word: ")

vowels = "aeiou"

total = 0
for character in word:
    if character in vowels:
        total = total + 1
        
print(word, "has", total, "vowels.")
Enter a word: telepathy
telepathy has 3 vowels.

Exercise: Average grade

Given a list of grades, grades = [81, 70, 60, 91], print the average and the number of grades above 80. In this case:

Average 75.5
Number of good grades 2

Hint: Start by thinking about how to calculate the average grade.

Get this working first!

Hint: Then think about how to count the number of grades above 80

In [61]:
# Python is great for data processing
grades = [81, 70, 60, 91]
good_grades = 0
avg = 0
for grade in grades:
    if grade >= 80:
        print("WOW! " + str(grade))
        good_grades = good_grades + 1
    avg = avg + grade
avg = avg/len(grades)
print("Average " + str(avg))
print("Number of good grades " + str(good_grades))
WOW! 81
WOW! 91
Average 75.5
Number of good grades 2