Lecture 2: Introduction to Python Programming, Part 1#

Learning objectives#

Last lecture we learned how to:

  • Identify and describe values of different types in Python code (int, float, bool, and str)

  • Perform simple computations on these values

  • Store values and the results of computations in variables

  • Run Python code and display results in a Jupyter notebook (like this one!)

We learned about:

  • Operations we can perform on different data types

    • Arithmetic: +, -, *, /

    • Comparison: ==, !=, <, <=, >, >=

    • Boolean (logic): and, or, not

  • Functions

    • len

    • type

    • abs

In this lecture, we will learn about:

  • String methods

    • str.upper()

    • str.lower()

    • str.replace(old, new)

    • str.split()

  • The difference between a function and a method

  • The list type

  • Conditional statements (if statements) to control how Python is executed

  • Loops, specifically for loops to repeat operations multiple times.

You will also learn to:

  • “Reset” Python in your notebook

  • Read in data from files

Review: data types#

We talked about four different data types last week: int, float, bool, and str. We also introduced the notion that we can perform different kinds of operations on data with these types, such as arithmetic operations on ints and floats and comparison operations using bools.

# Try out a few different types and operations on the types
3
# We talked about how strings could be concatenated together using the + operator
new_word = 'suit' + 'case'
print(new_word)
# But what about other operators using strings?

Review: functions#

Functions in Python have some similarity to functions in math. We introduced a few different useful functions, and some terminology. For example, below we are calling the function round with the arguments 3.6789 and 2, and storing or assigning the return value of the function to the variable result.

result = round(3.6789, 2) 

Text data or “Strings”#

We introduced strings last week and will add on this week.

str, short for string, is a type of data for representing text. A string is a sequence of characters, where each character could be:

  • English letters (a, b, c)

  • numeric digits (0, 1, 2, etc.)

  • letters and glyphs from languages other than English (e.g., ي, Ο, 䜠)

  • punctuation marks and symbols (such as the period (.) and at symbol @)

  • spaces

  • emojis (e.g., 😉, 🐧, đŸ«)

In Python, we write strings by writing text surrounded by either single-quotes or double-quotes.

'Hello, world!'
"Dark chocolate is the best."

This comparison is case-sensitive:

# Remember that the double equals (==) is used to test for equality
# The single equals is used for assignment statements
"Hello" == "hello"

We can use a new operator, in, to check whether one string is contained inside another:

# What type is this expression?
"cat" in "education"

We can access a specific character in the string by its position (or “index”) using square bracket notation.

Note: in Python, positions/indexes start at 0, not 1!

"Hello World!"[0]

We do this indexing more often on string variables. For example:

greeting = "Hello World!"
greeting[0]

Finally, we can use the len function to compute the number of characters of a string:

len("Hello World!")

The print function#

Normally when we execute a notebook cell with multiple expressions/statements, only the value of the last one is displayed.

3 + 4
5 + 6
7 + 8

We can use the built-in Python function print to display multiple values in the cell output.

print(3 + 4)
print(5 + 6)
print(7 + 8)

Jupyter Notebook Tips#

Before we start adding to our Python vocabularly, here are a couple of tips for working with Jupyter Notebooks.

If Python seems to be behaving strangely or you’ve run a bunch of cells and lost track of what you’re doing, don’t panic!

Reset Python your notebook by doing the following:

  1. Go to Kernel -> Restart & Clear Output.

  2. Python will restart, and all cell outputs will be removed, leaving only your code.

  3. Then, select the cell you’re currently working on, and go to Cell -> Run All Above.

    Or, if you want to re-run all cells, select Cell -> Run All instead.

Common pitfall: changing variables and running cells out of order#

Demo!

my_number = 10
my_number
my_number = 20
my_number = my_number + 100

my_number

Avoiding this pitfall:

  1. Prefer making cells “self-contained”: define and use variables in the same cell.

  2. If you’re using a variable, make sure it’s been defined in an earlier cell.

  3. After defining a variable, avoid changing the variable’s value in a different cell. Treat the variable as “read-only” after the cell it’s been defined in.

String Methods#

Strings are the most complex form of data we’ve studied so far, and there are a lot more operations we can perform on them beyond ==, in, and len.

Most of these operations are implemented as string methods.

A method is a function that is defined as part of a data type.

We refer to methods using “dot notation”: <type>.<method name>.

For example, str.upper is a string method that converts a string to ALL CAPS.

We can call the method by putting a string value to the left of the dot in Python code:

name = "Karen"

name.upper()

Here are some common string methods you may find useful:

String method

Description

str.upper()

Convert the string to uppercase.

str.lower()

Convert the string to lowercase.

str.count(other)

Return the number of times other appears in the string.

str.replace(old, new)

Replace all occurrences of old with new in the string.

str.split()

Return a list of the words in the string, separating by spaces.

my_string = "Karen likes chocolate."

my_string = my_string.replace("Karen", "Alex")

print(my_string)

This brings us to an interesting conundrum. How do we know whether a method changes the object we are using to call the method, or when we have to save the return value in another (or the same) variable.

The most common behaviour is not to change the original object, so we mostly have to save the return value of the method.

str.split and the Python list data type#

my_string = "Karen likes chocolate."

my_string.split()

What exactly is ['Karen', 'likes', 'chocolate']?

It contains strings, but is not one big string itself.

Let’s use the type() function to see what kind of value it is according to Python:

mystery_value = my_string.split()

type(mystery_value)

Okay! ['Karen', 'likes', 'chocolate'] is a list.

In Python, list are used to store multiple values in a sequence (i.e., with a defined order).

List examples#

Python lists are very versatile, and can be used to store different kinds of values. We write lists by using square brackets: [...].

# A list of strings:
["Karen", "likes", "chocolate"]
# A list of ints
[3, 5, 10000]
# An *empty* list
[]

List operations#

Lists support many of the same operations as strings, since both are “sequences”.

Lists can be compared using ==. Note: order matters!

[1, 2, 3] == [1, 2, 3]
[1, 2, 3] == [3, 2, 1]

We can compute the length of a list using the len function:

len(["Karen", "likes", "chocolate"])

We can calculate the sum of a list of numbers using the sum function:

sum([10, 20, 30])

We can index into lists and also get a subset of a list using the slicing that we saw with strings. Can you explain in English what each one does?

my_string = "Karen likes chocolate."
my_list = my_string.split()
my_list[0]
my_list[-1]
my_list[:1]
my_list[1:2]

Exercise: Putting it all together#

Given the list of numbers defined in the variable my_numbers, do the following:

  1. Calculate the length of the list (i.e., number of numbers in the list). Call this number my_len.

  2. Calculate the sum of the numbers in the list. Call this number my_sum.

  3. Calculate the average of the numbers in the list. Call this number my_avg.

  4. Print out a message of the form "The average of my_numbers is {my_avg}", where {my_avg} is replaced by the average of the numbers.

my_numbers = [1, -4.5, 333, 274, -1000, 0]

# Write your code in the space below

If statements#

So far, all of our code has been executed one line at a time, in top-down order:

name = "Karen"
age = 18

print(f"Hello {name}! How old are you?")
print(f"Wow {name}, you're only {age} years old? Why do they let you teach?")
print(f"Goodbye {name}, nice to meet you. :)")

Sometimes, we want to run different code depending on the values of our variables.

An if statement is a kind of Python code that lets us only execute some code if a specific condition is met.

name = "Karen"
age = 18

print(f"Hello {name}! How old are you?")

# NEW
if age < 20:
    print(f"Wow {name}, you're only {age} years old? Why do they let you teach?")

print(f"Goodbye {name}, nice to meet you. :)")

If statement terminology#

if <condition>:
    <statement1>
    <statement2>
    ...

We call the expression between the if and the colon the if condition.

We call the statements indented on the line(s) after the colon the if branch.

Warning: indentation matters! Python uses indentation to determine what code is part of an if statement vs. what’s after the if statement.

if 3 > 5:
    print("Line 1")

print("Line 2")

vs.

if 3 > 5:
    print("Line 1")
    print("Line 2")

if, elif, else#

We can use an optional else block after the if block to execute code only when the if condition is False.

name = "Karen"
age = 18

print(f"Hello {name}! How old are you?")

if age < 20:
    print(f"Wow {name}, you're only {age} years old? Why do they let you teach?")
else:
    print(f"Ah yes {name}, {age} is indeed a reasonable age to be teaching.")

print(f"Goodbye {name}, nice to meet you. :)")

Finally, we can include zero or more elif blocks between the if and else to express more than two cases.

name = "Karen"
age = 18

print(f"Hello {name}! How old are you?")

if age < 20:
    print(f"Wow {name}, you're only {age} years old? Why do they let you teach?")
elif age > 100:
    print(f"Wow {name}, you're already {age} years old? Why do they let you teach?")
elif age == 58:
    print(f"Ah {name}, you are the perfect age and they should let you do whatever you want. 😎")
else:
    print(f"Ah yes {name}, {age} is indeed a reasonable age to be teaching.")

print(f"Goodbye {name}, nice to meet you. :)")

Exercise Break#

When is a year a leap year? A leap year is a year that has 366 days by adding February 29 to the calendar. Leap years occur on years that are evenly divisible by 4, except years that are evenly divisible by 100 but not by 400.

Write conditional statements so that the statement f"{year} is a leap year" will be printed if year is a leap year and f"{year} is not a leap year" will be printed if year is not a leap year.

This question uses the modulus operator, %, which finds the integer remainder of the division between two integers. For example, x % 4 == 0 if x is evenly divisible by 4. In other words x % 4 == 0 is true if x / 4 has no remainder.

Test your statements on the following years:

  • 2025 is not a leap year

  • 2024 is a leap year

  • 2000 is a leap year

  • 2100 is not a leap year

year = 2024 

# write your code here   

For loops#

Recall that we can represent and operate on a collection of data using the list data type:

numbers = [10, 20, 30, 40, 50]

sum(numbers)

Sometimes we want to execute a piece of code once per element in a collection.

We can do this using a for loop.

numbers = [10, 20, 30, 40, 50]

for number in numbers:
    print(number)

For loop terminology#

for <variable> in <collection>:
    <statement1>
    <statement2>
    ...
  • We call <variable> the (for) loop variable. It refers to each element of the <collection>, one at a time.

  • We say that the for loop iterates over the <collection>.

  • We call the statements indented after the colon the (for) loop body.

  • We call each repetition of the loop body an iteration of the loop.

Using loops: compute and print#

Problem: Given a list of names, compute the length of each name and display each result.

names = ["Karen Reid", "Alex Ramiller", "Michael Moon"]

for name in names:
    name_length = len(name)
    print(f"The length of '{name}' is {name_length}.")

Using loops: compute and save#

Problem: Given a list of names, compute the length of each name and store each result (so that we can use these values later).

names = ["Karen Reid", "Alex Ramiller", "Michael Moon"]

for name in names:
    name_length = len(name)
    # How do we "save" the length of the name?

To accomplish this, we will:

  1. Create a new list variable to store the results.

  2. In the loop body, use the (new!) list.append method to add each length to the new list.

names = ["Karen Reid", "Alex Ramiller", "Michael Moon"]
lengths = []

for name in names:
    name_length = len(name)
    lengths.append(name_length)
    
lengths

Using loops: filtering#

We can combine a for loop and an if statement to iterate over a collection, decide what to do based on whether the current value satisifies a condition.

Problem: Given a list of names, compute the length of each name that contains an "l", and store each result.

names = ["Karen Reid", "Alex Ramiller", "Michael Moon"]
lengths = []

for name in names:
    if "l" in name:
        name_length = len(name)
        lengths.append(name_length)
    
lengths

Exercise Break#

  1. Given a list of names, compute the length of each name that contains an "a" and a "c", and store each result.

  2. Given a list of names, compute the length of each name and store each result that is \(\geq 11\).

names = ["Karen Reid", "Alex Ramiller", "Michael Moon"]

# Write your code for Question 1 here.


# Write your code for Question 2 here.

len(names[0])

Learning objectives#

In this lecture, you learned to:

  • Identify and describe values of different types in Python code

    • int, float, bool, str, list

  • Perform simple computations on these values

    • arithmetic, comparisons, functions (e.g. round, abs), string methods (e.g. str.upper, str.split)

  • Store values and the results of computations in variables

    • e.g. name = "Karen"

  • Run Python code and display results in a Jupyter notebook (like this one!)