All in One View

Content from Executing Python Code


Last updated on 2026-06-27 | Edit this page

Overview

Questions

  • What is the difference between executing code in an interactive environment vs. a script?
  • What is the Python REPL and how do you start it?
  • How do you execute Python code in the REPL?
  • How do you write and run Python scripts from the command line?
  • How do you comment out code in Python?

Objectives

  • Understand the differences between Python REPL and Python scripts
  • Execute Python code in an interactive environment (e.g., Python REPL)
  • Create and run Python scripts from the command line
  • Comment out code in Python

Shell vs. Script


When you execute Python code, you can do so in two main ways: through an interactive shell (sometimes called a “REPL”) or by writing and running a Python script.

Callout

“REPL” stands for “Read-Eval-Print Loop”.

It is an interactive environment where you can type Python code and see the results immediately.

Remember that a “shell” is an interface that allows you to interact with your operating system, while a “script” is a file containing a sequence of Python commands that can be executed as a program.

In practice, you will often use both methods. The interactive shell is great for testing small snippets of code, debugging, and exploring Python features. On the other hand, writing Python scripts is essential for creating larger programs, automating tasks, and sharing your code with others.

Entering the Python REPL


Before you start writing your own Python scripts, it is recommended to first test things in an interactive REPL session. This will allow you to see output in real-time and let you fix things dynamically if error messages arise.

To start a Python REPL session, open your terminal and type python or python3 (depending on your system configuration). You should see something that looks like this:

BASH

>>> python
Python 3.12.8 (main, Dec  5 2024, 14:06:27) [MSC v.1942 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

The >>> symbol is the prompt of the interactive Python interpreter, meaning that the interpreter is ready for Python code to be typed in. Anything you type in, until you exit your interactive shell, will be executed with Python. The code will be executed on a line-by-line basis, and a line will be executed after pressing Enter / Return. To end a statement in Python, you do not have to type in a semicolon or other special character, you just need to press Enter / Return.

Challenge

Quiting the REPL

Now that you can start a REPL session, how do you exit it?

After entering the REPL, execute the following command to exit:

BASH

>>> quit()

Alternative Solution

You can also use exit() or press Ctrl + D on Unix/Linux/Mac or Ctrl + Z followed by Enter on Windows to exit the REPL.

REPL Line Syntax


First, let’s test things out by making Python say “Hello!” to us using the print function

BASH

>>> print("Hello!")
'Hello!'
>>>

In this example, we typed print("Hello!") at the prompt and pressed Enter. The print function is a built-in function in Python that outputs the specified message to the console.

Congratulations, you just used Python for the first time in this walkthrough! As it has finished printing out “Hello!”, the interactive prompt is now displaying >>> again and waiting for you to tell it what to do next. Let’s use the print function again to print out multiple things at once that are side-by-side

BASH

>>> print("I am on the left!", "I am on the right!")
'I am on the left! I am on the right!'
>>>

Under certain circumstances, your lines may begin with ... (called “continuation lines”), indicating that the interpreter has not run anything yet and is waiting for you to input something else or “finish” the line. To see this, we can explicitly span a single Python statement across multiple lines by using the \ symbol at the end of a line. Let’s do this by modifying our above print statement example,

BASH

>>> print("I am on the left!", \
... "I am on the right!")
'I am on the left! I am on the right!'
>>>

Even though we split the single statement across multiple lines, Python still ran the code as if it were all on the same line. Therefore, you can think of the \ symbol as just extending any given line. Using \ can be helpful if you are typing a lot of code on a single line and would like to make it more “human-readable” in a text editor for example. The reason why you see ... is because the interpreter waited for you to tell it what to do next. In this case, it was waiting for you to “finish” the print function by submitting the final closing ).

Now that you’ve seen how to split a single Python statement across multiple lines, let’s try to combine multiple statements into a single line. We can combine both statements into a single line using the ; symbol. Consider the following code,

BASH

>>> print("I have the high ground") ; print("You underestimate my power!") 
I have the high ground
You underestimate my power!
>>>

The ; symbol is a shortcut for executing multiple statements on a single line, rather than having to code two lines separately. This can be useful for consecutive lines that are short and succinct, or for consecutive lines that may be related to each other. To the Python interpreter, the above example would just look like

>>> print("I have the high ground")
>>> print("You underestimate my power!")

as two separate lines of code.

Writing and Running Python Scripts


All of what we covered previously still applies when running Python scripts, but there are a few changes of note. First, since everything in a .py file is assumed to be run with Python, there is no need for the >>> symbol to be at the beginning of your lines of code. Similarly, you will no longer need ... at the beginning of your lines to indicate continuation lines. We also gain the ability to comment out multiple lines at once using ''' or """, which is a nice bonus.

We will be covering Python syntax for writing Python scripts in more detail in the next episode, but for now, you can just write the same code that you would write in the REPL into a .py file and run it with Python. For example, if you have a file called hello.py with the following content,

PYTHON

print("I have the high ground")
print("You underestimate my power!")

you can run it with Python by executing the following command in your terminal,

This will execute the code in hello.py and print the following output to the console,

OUTPUT

I have the high ground
You underestimate my power!

A blank template file called first_script.py is included in the data you downloaded for this lesson. Use your favorite text editor to open the file, first_script.py.

Once you have opened this file, it’s time to fill it with some code. Entering code into a Python file works just like entering it into the interactive shell, just without the >>>. And, just like before, it is executed line-by-line, so to enter a new Python statement or piece of code, just move on to the next line. A blank line in your file will cause no harm, as it just means you are not trying to execute code on that line. For testing purposes, let’s fill out first_script.py with the following code

PYTHON

# top of the file
'''
Showing off commenting out multiple lines.
Sometimes comments of this nature are used
to provide a description of the file at
the top of the file.
They can span multiple lines when enclosed
by a pair of three single quotes.
'''

print("Hello from your first script!")

# Add some numbers
x = 8.675
y = 3.09
z = x + y

# Print some output
print("Jenny has ", z, " gallons of water in her pool.")

After you have filled in your file with code (and saved), you can run it by executing the following in your terminal

You should then see the following output displayed in your terminal

OUTPUT

Hello from your first script!
Jenny has  11.765  gallons of water in her pool.
Challenge

Too many spaces

There appears to be too many spaces around the number 11.765 in the output. How can you fix this?

There are extra spaces in the output because we used commas to separate the different items in our print statement. When you use commas in a print statement, Python automatically adds a space between each item.

PYTHON

# Print without extra spaces
print("Jenny has", z, "gallons of water in her pool.")

Alternative Solution

The more “Pythonic” solution is to use an f-string to format the output. There are many reasons why f-strings are generally preferred over using commas in print statements including improved control and readability.

PYTHON

# Print using an f-string
print(f"Jenny has {z} gallons of water in her pool.")

The Main Event


__main__ is the standard Python pattern for code that should run only when a file is executed directly, not when it is imported as a module. The usual form is if __name__ == "__main__":, and it is often used to call a main() function or launch command-line behavior.

PYTHON

def main():
    # Your main code here
    print("This code runs when the script is executed directly.")

if __name__ == "__main__":
    main()

When Python runs a file directly, it sets that file’s __name__ to "__main__"; when the same file is imported, __name__ is set to the module name instead. This lets you keep reusable functions and classes in the same file without automatically executing the script entry logic during imports.

The Comments Section


Some final syntax that we need to cover before moving on is Python “comments”. After you have filled in your file with code, you can run it by executing the following in your terminalComments are not interpreted by Python and are used to clarify code — usually they act as notes to yourself or others to explain what a piece of code may be doing (they are otherwise hidden). Comments in Python start with the hash character # (also known as “pound” or “hashtag” or “octothorpe”), which affects all the text you type in afterward. A comment may appear at the start of a brand new line or following pieces of code. However, the # symbol enclosed by a pair of " or ' is just a hash character and has no effect. For example, consider the following code,

BASH

>>> # this is a comment
>>> print("Comments are hidden") # this is also a comment
'Comments are hidden'
>>> print(" # this is not a comment because enclosed in quotes")
 # this is not a comment because enclosed in quotes

Comments are used heavily throughout this lesson and, other than the above example, you do not have to type in the comments yourself while you go through the examples — they are mainly there for you to read.

You can enclose multiple lines in a pair of ''' (three single quotes) or """ (three double quotes) to comment out entire blocks of lines.

Callout

Technically, you are able to do ''' (and """) in the REPL, but it is much more cumbersome, so we did not cover it.

Key Points
  • Python code can be executed in an interactive environment (e.g., Python REPL).
  • Python code can be executed by writing and running Python scripts (ex., python script.py).
  • The Python REPL allows you to type Python code and see the results immediately.
  • Python scripts are files containing Python code that can be executed as a program.
  • Comments in Python start with the # symbol.
  • You can use ''' or """ to comment out multiple lines of code.

Content from Types and Operators


Last updated on 2026-06-27 | Edit this page

Overview

Questions

  • “Python has types?”
  • “How do you check the type of a variable?”
  • “What are the basic data types in Python?”
  • “How do you convert between different data types?”
  • “What are the rules for naming variables in Python?”

Objectives

  • Understand the concept of a type system in programming languages
  • Identify and use basic data types in Python
  • Learn how to check the type of a variable in Python
  • Convert between different data types in Python
  • Use string slicing and indexing to manipulate strings in Python
  • Use lists to group data in Python
  • Understand the rules and conventions for naming variables in Python

In Python, almost everything is an object, and every object has a type. In the context of Python, a type can be thought of as a description of what a value is and what you can do with it. That is, the type of an Python object determines what operations can be performed on it and how it behaves. Python has a rich set of built-in data types, and understanding these types is fundamental to programming in Python.

In contrast with a strongly typed language that assures type safety (e.g., 🦀Rust), Python is dynamically typed, meaning that the type of a variable is determined at runtime and can change as the program executes. In practice, this makes Python easier to write and run, but it also means that type-related errors (and many other runtime errors) may only be discovered during execution.

Basically, Python does not care about your types, but your types help Python understand how to interpret your code.

Types in Python


Python has several built-in data types, including but not limited to:

  • int: Integer numbers (e.g., 1, 42, -5)
  • float: Floating-point numbers (e.g., 3.14, -0.001)
  • str: Strings, which are sequences of characters (e.g., "Hello, World!")
  • bool: Boolean values, which can be either True or False
  • list: Lists, ordered, mutable collections of items (e.g., [1, 2, 3])
  • tuple: Tuples, ordered, immutable collections of items (e.g., (1, 2, 3))
  • dict: Dictionaries, unordered collections of key-value pairs (e.g., {"name": "Alice", "age": 30})
  • set: Sets, unordered collections of unique items (e.g., {1, 2, 3})

Python provides the built-in function type() that can be used to check the type of a variable or value,

>>> type(42)
<class 'int'>

>>> type(3.14)
<class 'float'>

>>> type("Hello, World!")
<class 'str'>

>>> type(True)
<class 'bool'>

>>> type([1, 2, 3])
<class 'list'>

>>> type((1, 2, 3))
<class 'tuple'>

>>> type({"name": "Alice", "age": 30})
<class 'dict'>

>>> type({1, 2, 3})
<class 'set'>

As is the case with most coding languages, integers (-2, -1, 0, 1, etc.) are of the type int and rational numbers (-2.0, -1.3, 0.2, 1.4, etc.) are of the type float. Mixing float and int numbers typically results in converting everything to a float. Using the / division operator to divide integers also results in a float, unless you use the // “floor” division operator

BASH

>>> type(1.0)
<class 'float'>
>>> type(1)
<class 'int'>
>>> 4.2 * 2
8.4
>>> 17 / 3
5.666666666666667
>>> 17 // 3
5

A string in Python is a sequence of characters that usually represent a form of text. In other coding languages, such as Fortran and C, text is usually stored in some form of “character” or “char” datatype. Python, however, does not have a character datatype. Instead, a single character in Python is simply a “string” datatype called str with length 1 (a string with two characters would be of length 2, etc.). Like with numbers, Python also has the ability to manipulate strings.

We have already used a few strings in this lesson when we used the print function, but you can also assign strings to variables using =. To create a string in Python, all you have to do is enclose it in a pair of quotation marks, either a pair of single quotes '...' or double quotes "...". The choice between the two is usually personal preference; however, " is helpful when the string you are dealing with already has a ' in it, and vice versa. For example, consider the following code,

BASH

>>> x = "Hello"
>>> y = 'Hello'
>>> x==y
True
>>> no_error_1 = "You're cool"
>>> error_1 = 'You're cool'

  File "<stdin>", line 1
    error_1 = 'You're cool'
                    ^
SyntaxError: invalid syntax
>>> no_error_2 = ' No "i" in "Team" '
>>> error_2 = " No "i" in "Team" "

  File "<stdin>", line 1
    error_2 = " No "i" in "Team" "
                    ^
SyntaxError: invalid syntax

For a more advanced approach, you can explicitly “escape” the error messages seen above by using either \' or \" in problematic areas, as in

BASH

>>> error_1 = 'You\'re cool'
>>> error_2 = " No \"i\" in \"Team\" "

Similar to numbers, strings also can be manipulated using the + and * operators. More specifically, the + operator combines two strings, while the * operator can be used to repeat a string if used with a number, as in

BASH

>>> "gg" + "ez"
'ggez'
>>> 3 * "yes"
'yesyesyes'
>>> ( 3 * "yes" ) + "no"
'yesyesyesno'

You may recall from the first episode that Python is dynamically typed, which means that the type of a variable is determined at runtime. This allows for flexibility in how you use variables, but it also means that you need to be careful when performing operations on variables of different types, as it may lead to unexpected results and/or errors.

BASH

>>> 42 + 3
45
>>> "foo" + "bar"
'foobar'
>>> "foo" + 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

Type Conversion


Python provides built-in functions for converting between different data types. For example, you can convert a string to an integer using the int() function, and you can convert an integer to a string using the str() function.

BASH

>>> int("42")
42
>>> str(42)
'42'
Challenge

The Cast Awakens

What does str(True) evaluate to?

PYTHON

'True'
Challenge

The Matrix: Re-casted

What does int(True) evaluate to?

Boolean values can be converted to integers, where True is converted to 1 and False is converted to 0. We call values such as 1 and True “truthy” values, while values such as 0 and False are called “falsy” values.

PYTHON

1
Challenge

The Return of the String

What does int("Gandalf") evaluate to?

PYTHON

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'Gandalf'

Operators in Python


One of the most common things Python is used for is being a fancy numerical calculator.

Python behaves similarly to other languages when performing arithmetic, using the operators +, -, *, / for addition, subtraction, multiplication, and division, respectively.

BASH

>>> 2 + 3
5
>>> 5 - 2
3
>>> 4 * 3
12
>>> 10 / 2
5.0
Callout

Python also supports exponentiation with the ** operator, modular division with the % operator, and “floor” division with the // operator.

BASH

>>> 2 ** 3
8
>>> 7 % 3
1
>>> 7 // 3
2

In Python (and many other programming languages), = is called the “assignment operator” and is used to assign a value to a variable. The == operator is called the “equality operator” and is used to compare two values for equality, returning True if they are equal and False otherwise. Here are some examples of how = and == are used in Python,

BASH

>>> x = 5
>>> y = 10
>>> x == y
False
>>> x == 5
True

The equality operator, ==, will be covered in the next episode, but it is important to understand that = and == are not interchangeable. Using = when you meant to use == can lead to unexpected results and/or errors.

Variables


Variables are used in every aspect of modern life, from the nickname you have for your cat to how we store and analyze data in science and engineering. As it is in real life, variable names in Python can be almost anything, but there are rules and conventions to follow. Rules impose restrictions on how you can name your variables, while conventions are more like guidelines that help make your code more readable and maintainable (e.g., “Pythonic”).

✅ Allowed

  1. Variable names must start with a letter (a-z, A-Z) or an underscore (_)
  2. Variable names can only contain letters, numbers, and underscores

Examples

PYTHON

cake = "chocolate"
_cake = "vanilla"
i_love_cake = True

❌ Not Allowed

  1. Variable names cannot be a reserved keyword in Python (e.g., if, else, for, while, etc.)
  2. Variable names cannot start with a number
  3. Variable names cannot contain spaces (use underscores instead)

Examples

PYTHON

c@ke = "carrot"
0cake = "bettercream"
i love cake = False
Caution

Python variable names are case-sensitive, meaning that cake, Cake, and CAKE are all different variables.

String Slicing and Indexing


One cool thing about strings is that you can “slice” them to extract specific portions of the string. Slicing is very useful in Python programming, especially when analyzing data, plotting, and sorting. “Indexing” is a subset of slicing that only extracts one character from a string, while “slicing” can extract multiple characters at once (i.e., multiple indices).

Python is “zero-indexed”, meaning indexing starts at 0 instead of 1. The first character in a string has index 0, the second character has index 1, and so on and so forth. To find the full length of a string you can use the len() function. To start, you must put these indices in square brackets [ ], as in

BASH

>>> alphabet = "abcdefghijklmnopqrstuvwxyz"
>>> len(alphabet)
26
>>> alphabet[0]
'a'
>>> alphabet[1]
'b'
>>> alphabet[25]
'z'

Note that in our example we had 26 letters (a to z), but since indexing starts from 0, the final letter in the string is index 25. You can also use negative indices to start at the end of the string. Therefore, you can think of using negative indices as reading from “right to left” instead of “left to right”, as in

BASH

>>> alphabet[-1]
'z'
>>> alphabet[-2]
'y'

Negative indices can be helpful when you don’t know how long a string is, but you know that you want specific characters located at the end of the string, however long the string may be.

you can use the : operator inside of [ ] to pick a range of indices (inserted on either side of the :). Note that when using :, the left side is inclusive while the right side is exclusive. Therefore, for a desired range, this results in a syntax of [desired start index : desired end index + 1 ]. For example, using our alphabet string variable of length 26, we have

BASH

>>> alphabet[0:10]
'abcdefghij'
>>> alphabet[0:5]
'abcde'
>>> alphabet[1:5]
'bcde'
>>> alphabet[1 : (4+1)]  # slices indices 1-4 (same as above, but with math)
'bcde'

Remember that when performing math inside of [ ] on indices, the numbers must be integers (i.e., int type objects) and/or the math that should result in an integer.

Instead of explicitly indicating the start/end of a slice with indices, you can choose to leave a side of the : blank. Leaving the left side blank means that you want the slice to begin at the start of the string, while leaving the right side blank means you want the slice to stop at the end of the string. Therefore, leaving both sides blank (i.e., [ : ]) indicates that you just want the entire string returned. Using our alphabet string variable again, we have

BASH

>>> alphabet[:]
'abcdefghijklmnopqrstuvwxyz'
>>> alphabet[2:]
'cdefghijklmnopqrstuvwxyz'
>>> alphabet[:8]
'abcdefgh'
>>> alphabet[:-1]
'abcdefghijklmnopqrstuvwxy'
>>> alphabet[:-2]
'abcdefghijklmnopqrstuvwx'

Because of the left side of : being included and the right side being excluded, this makes sure that alphabet[ : index ] + alphabet[ index : ] is always equal to alphabet

BASH

>>> alphabet[:2]
'ab'
>>> alphabet[2:]
'cdefghijklmnopqrstuvwxyz'
>>> alphabet[:2] + alphabet[2:]
'abcdefghijklmnopqrstuvwxyz'
>>> alphabet[:4] + alphabet[4:]
'abcdefghijklmnopqrstuvwxyz'

The List Frontier


The next thing to cover is how to group data – specifically by using something in Python called a “list”. Lists are defined as a “compound” datatype and are able to group together both numbers and strings, either individually or in a mix. The data contained in a list are comma separated and enclosed by square brackets.

Here is a short lists of examples of lists in Python,

PYTHON

# empty list
blank_list = []

# list of length 1
some_list = ["hola"]

# list of numbers of length 5
numbers = [1, 2, 3, 4, 5]

# list of mixed types
mixed = ["foo", 3.14, "bar", True]

Unlike with strings, you can modify a specific entry in a list with slicing/indexing, as in

PYTHON

squares = [0, 1, 4, 9, 16, 25, 'temp'] 
print(squares[6])
# 'temp'

squares[6] = 36
print(squares)
# [0, 1, 4, 9, 16, 25, 36]

This slicing ability can also be used to modify sections of lists, or be used to completely remove sections, as in

PYTHON

letters = ['a', 'b', 'c', 'd', 'e']
print(letters[2:4])
# ['c', 'd']

letters[2:4] = ['C', 'D']
print(letters)
# ['a', 'b', 'C', 'D', 'e']

letters[2:4] = []
print(letters)
# ['a', 'b', 'e']

letters[:] = []
print(letters)
# []

Lists are a powerful data structure in Python (and almost every other programming language) and are used extensively in data analysis, machine learning, and many other applications.

Challenge

Knowledge Check

What does (alphabet[13] + alphabet[:1]) * int("8") evaluate to?

PYTHON

'nananananananana'

We can break this down step by step.

  1. alphabet[13] gives us the character at index 13, which is 'n'.
  2. alphabet[:1] gives us the slice of the string from the start up to (but not including) index 1, which is 'a'.
  3. Adding these together with + gives us 'n' + 'a', which results in the string 'na'.
  4. int("8") converts the string "8" to the integer 8.
  5. Finally, multiplying the string 'na' by 8 with * gives us 'na' * 8, which results in the string 'nananananananana'.

Adict-ed to Python


We cannot cover every data type in Python in this lesson, but we will briefly mention one more important data type — the “dictionary” (or dict for short). A dictionary is a collection of key-value pairs, where each key is unique and maps to a specific value. Dictionaries are defined using curly braces {} and the key-value pairs are separated by colons, as in

PYTHON

lookup = {'name': 'Batman', 'city': 'Gotham'}

Values in a dictionary can be accessed using their corresponding keys, as in

PYTHON

name = lookup['name']
print(name)

OUTPUT

'Batman'

Values can also be modified or added to a dictionary using their keys, as in

PYTHON

lookup['name'] = 'Superman'
lookup['city'] = 'Metropolis'
print(lookup['name'])

OUTPUT

'Superman'
Key Points
  • Python has built-in types that describe the nature of values and how they can be manipulated.
  • The type() function can be used to check the type of a variable or value.
  • Python is dynamically typed, meaning that the type of a variable can change at runtime.
  • Python provides built-in functions for converting between different data types.
  • Python supports various operators for performing arithmetic and other operations on values.
  • String slicing and indexing allow you to extract specific portions of a string based on their position.
  • Lists are a compound data type that can hold multiple values of different types and can be modified using slicing and indexing.

Content from Loops and Logic


Last updated on 2026-06-27 | Edit this page

Overview

Questions

  • How do I use loops to repeat code in Python?
  • What are the different types of loops in Python and when should I use each one?
  • What are the main logical operators in Python and how do they work?

Objectives

  • Learn the different types of loops in Python and when to use each one
  • Understand and use the main logical operators in Python

Scaling Up with Loops


One of the most common and fun things to do in Python is to write loops of code. Loops make Python iterate over a certain section of code (usually over a list or a set of numbers). There are two main types of loops, the for loop and the while loop.

for the Record

The for statement in Python iterates over the items of a sequence (e.g., a list, a string, or range of values) in the order that the items appear in the sequence. The syntax of a for loop is

PYTHON

letters = ["a", "b", "c"]
for letter in letters:
    # Code to execute for each item in the sequence
    print(letter)
Discussion

The body of a “for” loop is separated from the rest of the code using indentation. Indentation is Python’s way of grouping statements. The official coding conventions for Python dictate using 4 spaces for indentation.

In general follow two rules when using indentation in Python: 1. Use 4 spaces per indentation level. 2. Never mix tabs and spaces.

In actual English, you can think of the line for letter in letters: as meaning

“For every letter in letters, print the letter”.

You should have a file called loops_01.py in the scripts directory that contains the code,

PYTHON

# loops_01.py

# create a list to loop over
loop_list = ['cat', 'dog', 'hamster', 'bird']

# use a "for" loop to loop over our list
# print out each entry "i" in "loop_list"
for i in loop_list:
    print(i)

Try running the code in loops_01.py and see what happens.

OUTPUT

cat
dog
hamster
bird

This type of loop can also be used to iterate over a range of values, which is extremely helpful for indexing and slicing in a loop. To iterate over a range of values, you can use the range function, which takes a start value, a stop value, and an optional step value,

PYTHON

range(start, stop, step)

Just like with indexing, the start value is inclusive while the stop value is exclusive.

To see how this works in practice, open the file loops_02.py in the scripts directory and take a look at the code.

Run the code in loops_02.py and see what happens.

OUTPUT

Example 2.1: range(0, 10, 1)
0
1
2
3
4
5
6
7
8
9

Example 2.2: range(0, 10, 2)
0
2
4
6
8

Example 2.3: range(4)
0
1
2
3

Example 2.4: range(length of x)
O
L
C
F

Example 2.5: enumerate(x)
0 O
1 L
2 C
3 F

while We’re Here…

In contrast with for loops, while loops keep iterating until a certain condition is no longer true. The syntax of a while loop is

PYTHON

while some_condition:
    # Code to execute while the condition is true
    print("This code will keep running until some_condition is no longer true.")

In natural English, you can think of the line while some_condition: as meaning

While some condition is true, Python will execute the code in the “while” block.

Because the while loop constantly checks to see if a certain statement is “true”, the loop is often used with comparison operators. The standard comparison operators are: < (less than), > (greater than), == (equal to), <= (less than or equal to), >= (greater than or equal to) and != (not equal to).

This means

PYTHON

# will never stop
while True:
    print("This loop will run forever!")

and

PYTHON

# will never start
while False:
    print("This loop will never run!")

To see how this works in practice, open the file loops_03.py in the scripts directory and take a look at the code.

Run the code in loops_03.py and see what happens.

OUTPUT

Example 6.5: while x < y
x equals 0
x equals 1
x equals 2
x equals 3
x equals 4

Example 6.6: while z != 6
Am I 6 yet? Nope, I am 0
Am I 6 yet? Nope, I am 1
Am I 6 yet? Nope, I am 2
Am I 6 yet? Nope, I am 3
Am I 6 yet? Nope, I am 4
Am I 6 yet? Nope, I am 5

while loops can be dangerous at times, as it is very easy to accidentally get stuck in an infinite loop if it is not coded properly. In the above examples, if we did not modify either x or z in our loops, their value never would have changed and we would have gotten stuck in the loop (as both conditions would always remain True). In general, if you can convert a while loop into a for loop, it is recommended to use the for loop version instead.

Discussion

The preference for for over while goes beyond just avoiding infinite loops. while loops almost always require mutation of a variable (e.g., x or z in the above examples), which is a common source of bugs in code. for loops, on the other hand, can often be written without mutation, which makes them easier to reason about and less prone to bugs. Finally, for loops without mutation are immediately equivalent to functional programming constructs like map and filter, which are often objectively better in almost every aspect.

Caution

If you do get stuck in a loop, either close the the terminal window, or press CTRL + C to interrupt the execution.

Now that we’ve introduced conditions being either “True” or “False” in the context of loops, the natural next step is to introduce how to control the flow of your code based on “True” or “False” conditions.

Fork in the Code


If you want to execute a piece of code only if a specific condition is met, the if statement comes in handy. For example, maybe you only want to print something out if a specific variable is “True”, or when a math expression yields a specific value. No matter the reason, the syntax of the if statement is

PYTHON

if condition:
    print("Execute this block if condition is True")
flowchart LR
    accTitle: {if control flow}
    A{"Condition"}
    B("Code")
    C([Continue])
    A -- True --> B
    A -- False --> C
    B --> C

Like with loops, the body of an if statement is indented. In the example above, Python first evaluates condition to determine whether it is “True” or “False”. Next, Python executes the body of the statement only if condition is “True”. In natural English, you can think of the line if condition: as meaning

If this line is True, Python will do the following: …“.

To see this in practice, open the file logic_01.py in the scripts directory and take a look at the code.

Run the code in logic_01.py and see what happens.

OUTPUT

'x is 1'

Recall from the Types and Operators episode that the == operator checks if two things are equal. In Example 1.1, x did indeed equal 1, so the condition was “True” and Python executed the print function in the first if statement. In Example 1.2, x did NOT equal 2, so the condition was “False” and Python did not execute the if statement. Because we did not tell Python what to do if the condition was “False”, Python did nothing and skipped over it.

To explicitly tell Python what to do in the event that the condition is “False”, you need to add an else statement, as in

PYTHON

if condition:
    print("Execute this block if condition is True")
else:
    print("Execute this block if condition is False")
flowchart LR
    accTitle: {if-else control flow}
    A{"Condition"}
    B("Code")
    C("Code")
    D([Continue])
    A -- True --> B
    A -- False --> C
    B --> D
    C --> D

First, Python checks to see if the condition is “True”. If the condition is “True”, then Python executes the body of the if statement and ignores the body of the else statement. However, if Python found that the condition was “False”, it would execute the body of the else statement instead.

To see this in practice, open the file logic_02.py in the scripts directory and take a look at the code.

Run the code in logic_02.py and see what happens.

OUTPUT

'x is not 1'

We see that Python only executed one of the print statements because of our if and else statements. The x variable was equal to 2, so the if block x == 1 condition was “False” and Python executed the else statement instead.

Extending things further, perhaps you want to tell Python to check for multiple conditions, instead of just one. In that case, you need to add an elif statement (short for “else-if”), as in

PYTHON

if condition:
    # A
    print("Execute this block if condition is True")
elif another_condition:
    # B
    print("Execute this block if another_condition is True")
else:
    # C
    print("Execute this block if condition is False")
flowchart LR
    accTitle: {if-elif-else control flow}
    X{"Condition"}
    Y{"Another<br/>Condition"}
    B1("A")
    D1("B")
    E1("C")
    F([Continue])
    X -- True --> B1
    X -- False --> Y
    Y -- True --> D1
    Y -- False --> E1
    B1 --> F
    D1 --> F
    E1 --> F

First, Python checks to see if condition is “True”. If it finds that condition is “True”, then Python will execute the body of the if statement and skip the rest (regardless of the remaining conditions). However, if it finds that condition is “False”, then Python then checks to see if another_condition is “True”. If it finds that another_condition is “True”, then Python will execute the body of the elif statement and skip the rest. And, if all conditions are “False”, then Python will execute the else statement as a last resort.

Because Python skips the remaining if-elif-else code once it finds a “True” condition, only ONE of the statements will be executed across an entire if-elif-else section of code. Even if multiple statements are “True”, it will only execute whichever one it finds first, starting from the top.

We only used one elif line in the above syntax example, but you can include as many elif statements as you like. However, note that you can only ever have one if and else line in a given if-elif-else block of code.

To see this in practice, open the file logic_03.py in the scripts directory and take a look at the code.

Run the code in logic_03.py and see what happens.

OUTPUT

'x is less than 2'
Key Points
  • for loops are used to iterate over a sequence of items, while while loops are used to repeat code until a certain condition is no longer true.
  • The main logical operators in Python are == (equal to), != (not equal to), < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to).
  • The if statement allows you to execute a block of code only if a specific condition is met, while the else statement allows you to execute a block of code if the condition is not met.
  • The elif statement allows you to check for multiple conditions in an if-else block, and only the first “True” condition will be executed.
  • Logical operators can be combined to create more complex conditions in if and elif statements.

Content from Functions, Functions, Functions


Last updated on 2026-06-27 | Edit this page

Overview

Questions

  • Why are functions useful in programming?
  • How are functions defined in Python?
  • What is the difference between a function definition and a function call?
  • How do you pass arguments to a function in Python?

Objectives

  • Understand the concept of functions and their importance in programming
  • Understand how to use functions
  • Distinguish between function definitions, function application, and function arguments
Discussion

Functions enable the re-use of code without copy-pasting or typing it over and over and duplicating code. Functions are delayed computations that can be called at any time. They are a fundamental building block of programming and are used to break down complex problems into smaller, more manageable pieces.

Function Junction


A function is a block of code that only runs when it is called, but is designed to be reusable. This is a major convenience when trying to repeat a specific action within your code. We already used a couple pre-defined functions in this lesson, mainly print and len, but you can also create your own functions, which are called “user-defined functions”.

We can represent the idea of a function mathematically1 as

\(f(x) = y\)

Where f is the name of the function, x is the argument, and y is the return value.

The same idea can be represented in Python as

PYTHON

def f(x):
    """Function description"""
    y = x + 1
    return y

The function block begins with the def keyword followed by the desired name of the function with a set of parentheses ( ). Input parameters for the function are placed inside the parentheses next to the function name.

In other words, the function above says

I want to define a function called f that depends on these (x)

Just like with loops and if-statements, everything within a function block is indented, and the function block ends when the indentation ends. A description of the function enclosed by a set of triple-quotes ''' can be included at the top. This is optional but a good habit. The “body” of the function is the code you want the function to perform when called, similar to the body of a loop or if-statement. The return statement exits the function, and can pass back a specific variable or expression, usually the results of the body.

Once a function is defined, you are then able to “call” it (execute it).

To see this in practice, open the file functions_01.py in the scripts directory and take a look at the code.

Run the code in functions_01.py and see what happens.

OUTPUT

8

It is good practice to define your functions at the top of the script, so they are more findable. Doing so also makes your code flow better and makes it more readable than placing a function block in the middle of your script, for example.

Because we told the function to return print(z) when the function call completed, we were actually able to see the output, 8. Instead, we could have told the function to return z when it finished, which would return the variable, z, rather than printing the actual value of z.

To see this in practice, open the file functions_02.py in the scripts directory and take a look at the code.

Run the code in functions_02.py and see what happens.

OUTPUT

8

Same as in scripts/functions_01.py

The function add was written exactly like the previously discussed print_add function, but with the key difference being return z instead of return print(z). Because of this, calling the function add by itself doesn’t automatically print out the value of z – as seen in “Example 2.1” in the above script. This is because the function was told only to return a variable upon exit, not actually use the variable in a specific way.

In “Example 2.2”, we save the resulting variable of the function to a new variable called result. This allows Python to access the z result of the function through result, which, upon printing, we see that the result of the function is 8, just like before.

Challenge

Let’s Get Functional

How might we combine (or “compose”) the code from functions_01.py and functions_02.py to create a new function that both computes the sum of two numbers and prints the result?

PYTHON

def add(x, y):
    """This function will sum x and y into a variable z and print the variable z when the function exits"""
    return x + y


def print_add(x, y):
    """This function will sum x and y into a variable z and print the variable z when the function exits"""
    print(add(x, y))


print_add(3, 5)

This code hints at the idea of “function composition”, which is the process of combining two or more functions to create a new function.

Pass It On


Functions can take arguments, which are values that are passed to the function when it is called, and they can return values, which are the results of the function’s computations.

Argument order, naming, and default values are defined by the function definition.

During function application (“execution”) arguments can be “positional”, meaning they are passed in a specific order, or “keyword”, meaning they are passed with a specific name.

PYTHON

def add(x, y):
    return x + y

# Positional arguments
add(3, 5)

# Keyword arguments only
add(x=3, y=5)


# Positional and keyword arguments
add(3, y=5)

Default values are optional and defined in a similar way to how keyword arguments are passed, as in

PYTHON

# The default value of y is 5
def add(x, y=5):
    return x + y


add(3) # returns 8
add(x=3) # returns 8
add(3, 4) # returns 7

Finally, we can refer to functions based on how many arguments they take. For example, a function that takes one argument is called a “unary function”, a function that takes two arguments is called a “binary function”, and so on.

Challenge

What’s in a Name?

What would you call a function that takes N arguments?

“N-ary” or “variadic” function, where N is a variable that can take on any value.

One Line to Rule Them All


Functions can be defined in-line with their application by using a special syntax called “lambda functions” or “anonymous functions”.

They are called “anonymous” because they do not have a name, and are often used for short, simple functions that are not intended to be reused. They are more accurately called “lambda functions” as they use the lambda keyword in reference to the mathematical notation of lambda calculus2. Lambda functions are very useful when using higher-order functions, which are functions that take other functions as arguments or return functions as their output.

PYTHON

# A lambda function that adds two numbers
add = lambda x, y: x + y

# Using the lambda function
result = add(3, 5)
print(result) # Output: 8

Functions All the Way Down


Functions that accept functions as arguments or return functions as their output are called “higher-order functions”. They are a powerful tool for creating abstractions and can be used to create more complex functions from simpler ones, through a process called” function composition”. We cannot go too deep into higher-order functions in this lesson, but they are an important concept to understand as you continue to learn about functions and their applications in programming. For now, here are some examples of higher-order functions in Python:

PYTHON

# A higher-order function that takes a function as an argument
def apply(func, x, y):
    return func(x, y)


result = apply(lambda x, y: x + y, 3, 5)
print(result) # Output: 8

add = lambda x, y: x + y
result = apply(add, 3, 5)
print(result) # Output: 8

In practice, higher-order functions like map and filter are commonly used in Python for applying a function to a list of values or filtering a list of values based on a condition, respectively.

Challenge

Functional Finale

Can you use map and filter to create a new list that contains the squares of all the even numbers from a given list of integers without hard-coding any values? Can you do it without using any variables?

PYTHON

is_even = lambda x: x % 2 == 0
square = lambda x: x ** 2
numbers = range(1, 10)

squares = list(map(square, filter(is_even, numbers)))
print(squares) # Output: [4, 16, 36, 64, 100]

Variables are not strictly necessary in this case, as we can directly pass the lambda functions to map and filter without assigning them to a variable.

PYTHON

squares = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, range(1, 10))))
print(squares) # Output: [4, 16, 36, 64, 100]

“…variables are a logically unnecessary but practically very useful device.”

–Haskell Curry, Combinatory Logic, 1968, p. 154

See the reference for more information on higher-order functions and list comprehensions.

Key Points
  • Functions are reusable blocks of code that perform a specific task and can be called at any time.
  • Functions are defined using the def keyword followed by the function name and parentheses containing any parameters.
  • Lambda functions are another way to define functions and are escpecially useful when using higher-order functions.
  • Higher-order functions are functions that take other functions as arguments or return functions as their output, and are a powerful tool for creating abstractions and composing functions.

  1. This is not the only way to represent functions mathematically, but it is a common notation.↩︎

  2. Lambda calculus is a formal system in mathematical logic and computer science for expressing computation based on function abstraction and application. Some historical accounts say Alphonso Church originally used \(\hat{y}\) to represent functions, which became \(\land y\) in his typed manuscripts, and took its final form of \(\lambda y\) by the decision of a typesetter.↩︎

Content from Bonus Challenges


Last updated on 2026-06-27 | Edit this page

Challenge Level File
Slicing the Cake Easy scripts/challenges/cake.py
Calculating the Box Easy scripts/challenges/box.py
Playing the Banjo Medium scripts/challenges/banjo.py
Counting the Sheep Medium scripts/challenges/sheep.py
Finding the Needle Hard scripts/challenges/needle.py
Challenge

Slicing the Cake

Who doesn’t love slicing some cake? The objective of this challenge is to match two lists (test_cake and fake_cake) by slicing real_cake. Your mission is to edit the line labeled as “TO-DO” to get the script to work properly. After editing the script, run it to see if you correctly fixed things. If you are successful, you will see 'Success!' printed out.

PYTHON

# Set up lists
real_cake = ["portal", "the cake", "is", "not", "a lie", "!", "hl3"]
fake_cake = ["the cake", "is", "a lie", "!"]
# Manipulate real_cake to match fake_cake
test_cake = real_cake[1:3] + real_cake[4:6]
# Check to see if you are correct
print("real cake:", real_cake)
print("fake cake:", fake_cake)
print("test cake:", test_cake)
if test_cake == fake_cake:
    print("Success!")
else:
    print("Try again!")
    print("Fake cake should equal test cake")
Challenge

Calculating the Box

Who doesn’t love math and boxes? The objective of this challenge is to fill in the missing information of the get_size function to calculate the area and volume of a box and then return the results in the form of a list [area, volume]. You will need to edit both the body of the function and the return line of the function, which are both marked by “TO-DO” comments. After editing the script, run it to see if you correctly fixed things. If you are successful, you will see 'Success!' printed out.

PYTHON

def get_size(w, h, d):
    """This function calculates the
    surface area and volume of any
    given box of width "w", height
    "h", and depth "d"."""
    area = (2 * d * w) + (2 * d * h) + (2 * w * h)
    vol = w * h * d
    box_list = [area, vol]
    return box_list


# Test the get_size function for a couple box sizes
box_1 = get_size(w=1, h=1, d=1)
box_2 = get_size(w=4, h=2, d=6)
# Check to see if you are correct
print("Area and volume of 1x1x1 box: ", box_1)
print("Area and volume of 4x2x6 box: ", box_2)

if (box_1 == [6, 1]) and (box_2 == [88, 48]):
    print("Success!")
else:
    print("Try again!")
    print("You should get [6,1] and [88,48]")
Challenge

Playing the Banjo

Who doesn’t love the banjo? The objective of this challenge is to fill in the missing information of the playing_banjo function to figure out if someone knows how to play the banjo or not. More specifically, you want the function to print either NAME plays the banjo or NAME does not play the banjo based on a person’s name. In this code-world, only names that begin with the letter “R” (lower case or upper case) know how to play the banjo. You will need to edit the if and elif statements in the body of the function to make sure things print out correctly (marked by the “TO-DO” comments). Note that the else statement is already correctly filled in. After editing the script, run it to see if you correctly fixed things.

If you are successful, you will see this output:

OUTPUT

Leah does not play the banjo
michael does not play the banjo
brian does not play the banjo
Ryan plays the banjo
rolf plays the banjo

PYTHON

def playing_banjo(name):
    """This function checks to see if someone plays
    the banjo based on their name. Names beginning
    with "R" or "r" play the banjo, while others do not."""
    if name[0] == "r":
        banjo = name + " plays the banjo"
    elif name[0] == "R":
        banjo = name + " plays the banjo"
    else:
        banjo = name + " does not play the banjo"
    return print(banjo)


# Test cases to see if you are correct
playing_banjo("Leah")
playing_banjo("michael")
playing_banjo("brian")
playing_banjo("Ryan")
playing_banjo("rolf")
Challenge

Counting the Sheep

Who doesn’t love sheep? The objective of this challenge is to fill in the missing information of the count_sheeps function to count the number of “True” entries in a list. Each “True” entry in the list represents one single sheep in this universe. You will only need to edit one line of the body of the function, marked by the “TO-DO” comment. After editing the script, run it to see if you correctly fixed things (the function should be able to detect 17 sheep). If you are successful, you will see 'Success!' printed out.

PYTHON

def count_sheeps(sheep):
    """This function loops over the entire sheep
    array and adds up all the values"""
    size_sheep = len(sheep)
    count = 0
    for i in range(0, size_sheep):
        count = count + sheep[i]

    return count


# Our flock of "sheep" list
flock = [
    True,
    True,
    True,
    False,
    True,
    True,
    True,
    True,
    True,
    False,
    True,
    False,
    True,
    False,
    False,
    True,
    True,
    True,
    True,
    True,
    False,
    False,
    True,
    True,
]
# Call the count_sheeps function
flock_count = count_sheeps(flock)
# Check to see if you are correct
print("You counted this many sheep: ", flock_count)
if flock_count == 17:
    print("There are 17 sheep! Success!")
else:
    print("Try again!")
    print("The sheep count should be 17")
Challenge

Finding the Needle

Who doesn’t love needles in haystacks? The objective of this challenge is to fill in the missing information of the find_needle function so that it returns the position of “needle” in a given list. You will need to edit the body of the loop in the function and the return line of the function (both marked by “TO-DO” comments). Note that you will need to add more than one line in the body of the loop even though it’s only marked by one “TO-DO” comment. After editing the script, run it to see if you correctly fixed things. If you are successful, you will see 'Success!' printed out.

PYTHON

def find_needle(haystack):
    """This function iterates through a list
    to find the "needle" string. The function
    then returns the index (position) in the
    list where it found "needle"."""
    dummy_index = 0
    for entry in haystack:
        if entry == "needle":
            index = dummy_index
        else:
            dummy_index = dummy_index + 1

    return index


# Create a couple "haystack" lists to be searched through and tested
hay_list_1 = [
    "283497238987234",
    "a dog",
    "a cat",
    "some random junk",
    "a piece of hay",
    "needle",
    "something somebody lost a while ago",
]
hay_list_2 = [
    "Python is cooler than C++",
    "needle",
    "Fortran is also cool",
    "blah",
    "summit",
    "rhea",
    "andes",
    "titan",
]
# Call the find_needle function, set result to a variable
needle_pos_1 = find_needle(hay_list_1)
needle_pos_2 = find_needle(hay_list_2)
# Check to see if you are correct
print("Found the needle in the 1st haystack at position", needle_pos_1)
print("Found the needle in the 2nd haystack at position", needle_pos_2)
if (needle_pos_1 == 5) and (needle_pos_2 == 1):
    print("Success!")
else:
    print("Try again!")
    print("You should find them at position 5 and position 1")