Week 00
Workload expectation
In general, each credit hour in a 100-200 level course will require an average of 3 hours per week spent on work for that course, outside of the synchronous meeting time.
Homework
Homework is due 7 days after assigned. No extensions.
Learning to program takes time. Sometimes you read a problem, write some code, and try to figure out why the code doesn’t work. You struggle with it, and go to the next problem, you sleep on it, you wrestle with it again, you go to tutoring or office hours, and you finally figure it out. To some, the process of debugging code comes naturally, for other you will need to build up a new set of skills.
Beginning to Program in Python
1def our_first_program():
2 print("hello world!")
3
4our_first_program()
Dissecting a simple program
def
: a reserved string.hour_first_program
a function name.()
an empty list of parameters.print
another reserved string."hello world"
: a string.our_first_program()
: invocation of a function.
Known words above: a, an, empty, of, another.
Syntax rules and good practices for function names
Start with a Letter or Underscore: A function name must start with a letter (uppercase or lowercase) or an underscore (_). It cannot start with a number or special character.
Alphanumeric and Underscore: After the first character, a function name can contain letters, numbers, and underscores. No spaces or special characters are allowed.
Case-Sensitive: Function names in Python are case-sensitive, so
myfunction
,myFunction
, andMYFUNCTION
are all different functions.No Reserved Words: You cannot use Python’s reserved words as function names. These include words like
if
,else
,while
,for
,return
, etc.Snake Case: By convention, function names in Python are usually written in snake_case, where all letters are lowercase, and words are separated by underscores. For example,
my_function_name
.Avoid Leading Underscores Unless Necessary: A leading underscore in a function name (e.g.,
_my_function
) typically indicates that the function is intended for internal use within a module or class and should not be accessed from outside. It’s a convention, not a strict rule, so it won’t prevent access, but it signals to other developers that the function is considered “private” or “protected.”Descriptive Names: It’s good practice to choose function names that clearly describe what the function does. This makes the code more readable and maintainable.
Examples of valid function names
def my_function():
def _internal_use_only():
def calculate_sum(x, y):
Examples of invalid function names
def 123_function(): # Starts with a number
def my-function(): # Contains a special character
def for(): # Uses a reserved word
Knowledge test
Basic Understanding
What does the
def
keyword do in Python?What is the purpose of the
print
statement in the code?How would you describe the function’s name and its naming convention?
Function Concepts
What does the
our_first_program
function do when it is called?How many parameters does the
our_first_program
function take? Can you explain what a parameter is?
Code Execution
What will be the output of the code when it is run?
In what order are the lines of code executed?
Indentation and Structure * Why is indentation important in defining the body of a function? * What is the significance of the colon
:
at the end of the function definition?Application and Extension
Can you write a similar function that prints a different message?
How would you modify the
our_first_program
function to take a name as a parameter and print “Hello, [name]!”?
Understanding Errors (Advanced)
What would happen if you removed the indentation from line 2? Why?
What would happen if you tried to call the
our_first_program
function before defining it?
(Answers)
f-strings
An f-string is created by placing an f
before the opening quotation mark of a string and including expressions inside curly braces {}
within the string. For example:
name = "John"
age = 25
greeting = f"Hello, {name}! You are {age} years old."
Here, the variables name
and age
are directly embedded within the string, resulting in the greeting: Hello, John! You are 25 years old.
f-strings provide a concise way to include variables or expressions inside strings.By embedding values directly in the string, the code remains clean and easy to read. The expressions inside the curly braces are evaluated at runtime, allowing for dynamic string creation.
f-strings are an essential tool in Python programming, and you’ll often find them used to create clear and efficient string representations.
Variables and Boolean logic
This next example will introduce variables, boolean values, boolean logic, and function parameters.
1def check_age(age):
2 is_adult = age >= 18
3 is_teenager = 13 <= age < 18
4 print(f"Age provided: {age}")
5 if is_adult:
6 print("You are an adult.")
7 elif is_teenager:
8 print("You are a teenager.")
9 else:
10 print("You are a child.")
11 print(f"Is adult? {is_adult}")
12 print(f"Is teenager? {is_teenager}")
13
14 check_age(20)
The function takes an input parameter, “age”, and then produces text output that changes depending on the value used. Let’s go through this example line by line.
Dissecting the code
Line 1:
def check_age(age):
- Defines a function namedcheck_age
that takes one parameter,age
.Line 2:
is_adult = age >= 18
- Declares a boolean variableis_adult
, which isTrue
ifage
is 18 or older.Line 3:
is_teenager = 13 <= age < 18
- Declares a boolean variableis_teenager
, which isTrue
ifage
is between 13 and 17 (inclusive).Line 4:
print(f"Age provided: {age}")
- Prints the provided age using an f-string.Line 5:
if is_adult:
- Begins anif
statement that checks ifis_adult
isTrue
.Line 6:
print("You are an adult.")
- Prints a message ifis_adult
isTrue
.Line 7:
elif is_teenager:
- Begins anelif
statement that checks ifis_teenager
isTrue
.Line 8:
print("You are a teenager.")
- Prints a message ifis_teenager
isTrue
.Line 9-10:
else:
/print("You are a child.")
- If neitheris_adult
noris_teenager
isTrue
, this message is printed.Line 11-12:
print(f"Is adult? {is_adult}")
/print(f"Is teenager? {is_teenager}")
- Prints the values of the boolean variables.Line 14:
check_age(20)
- Calls thecheck_age
function with an argument of 20.
Knowledge test
What is the output of the code when
check_age(20)
is called?How would the output change if the age provided was 15?
What are the boolean variables
is_adult
andis_teenager
, and how are they used in the code?Can you write a similar function that checks and prints whether a number is positive, negative, or zero?
(Answers)
Working with numbers
1def calculate_statistics(number1: int, number2: float) -> str:
2 """Calculates and returns a summary of statistics.
3
4 Args:
5 number1 (int): An integer input.
6 number2 (float): A decimal input.
7
8 Returns:
9 str: A string summary of the statistics.
10 """
11 sum_result = number1 + number2 # Addition
12 product = number1 * number2 # Multiplication
13 is_odd = number1 % 2 == 1 # Modulo operation to check odd
14
15 summary = (f"Sum of {number1} and {number2}: {sum_result}\n"
16 f"Product of {number1} and {number2}: {product}\n"
17 f"{number1} is {'odd' if is_odd else 'even'}")
18
19 return summary
20
21print(calculate_statistics(3, 4.5))
Dissecting the code
Line 1:
def calculate_statistics(number1: int, number2: float) -> str:
- Defines a function with type annotations for the parameters and return type. This improves code readability and helps tools provide better analysis.Line 2-10: These lines form the docstring, which provides a detailed explanation of the function, its parameters, and its return value. This is essential for understanding the function’s purpose and usage.
Line 11:
sum_result = number1 + number2 # Addition
- Calculates the sum ofnumber1
andnumber2
and stores it insum_result
. The inline comment explains the operation.Line 12:
product = number1 * number2 # Multiplication
- Calculates the product of the numbers.Line 13:
is_odd = number1 % 2 == 1 # Modulo operation to check odd
- Uses the modulo operator%
to check ifnumber1
is odd. Ifnumber1
divided by 2 has a remainder of 1, it’s odd.Line 15-17: Constructs a summary string that includes the results of the previous calculations and whether
number1
is odd or even.Line 19:
return summary
- Returns the summary string.Line 21:
print(calculate_statistics(3, 4.5))
- Calls the function with an integer and a float, and prints the result.
Knowledge test
What is the purpose of the type annotations in the function definition, and how are they used?
What is a docstring, and why is it included in the code?
How does the code determine if
number1
is odd or even?What will be the output of the code when
calculate_statistics(3, 4.5)
is called?
(Answers)
Booleans and truth tables
Booleans are a fundamental data type in programming that represents one of two values: True
or False
. They are named after George Boole, who first defined an algebraic system of logic in the mid-1800s.
In Python, booleans are often used to represent the results of logical comparisons, such as equality or inequality tests.
x = 10
y = 5
is_greater = x > y # Evaluates to True
is_equal = x == y # Evaluates to False
Truth Tables
A truth table is a mathematical table used to represent the values of logical expressions based on their possible inputs. It’s a systematic way to list every possible combination of truth values for a given logical operation, such as AND, OR, and NOT.
Here are the truth tables for the three basic logical operations:
A |
B |
A AND B |
---|---|---|
True |
True |
True |
True |
False |
False |
False |
True |
False |
False |
False |
False |
A |
B |
A OR B |
---|---|---|
True |
True |
True |
True |
False |
True |
False |
True |
True |
False |
False |
False |
A |
NOT A |
---|---|
True |
False |
False |
True |
Booleans and truth tables are fundamental to understanding logic in programming. They form the basis of conditional statements and control flow, allowing programs to make decisions and perform different actions depending on certain conditions. Understanding these concepts will enable you to write more complex and dynamic code. ### What does it mean for something to be evaluated in a boolean context: Truthiness and Falsiness
In programming, the concepts of truthiness and falsiness refer to how non-boolean values are treated when evaluated in a boolean context. Essentially, truthiness and falsiness determine how values are interpreted as True
or False
when used in conditions, such as in an if
statement.
Truthiness and Falsiness in General
Truthiness: A value is considered “truthy” if it evaluates to
True
in a boolean context, even if it is not explicitly the boolean valueTrue
.Falsiness: Conversely, a value is considered “falsy” if it evaluates to
False
in a boolean context, even if it is not explicitly the boolean valueFalse
.
Different programming languages have different rules for what values are considered truthy or falsy.
Truthiness and Falsiness in Python
In Python, the following values are considered falsy:
None
False
Zero of any numeric type, such as
0
,0.0
,0j
Any empty sequence, such as
''`, ``[]
,()
Any empty mapping, such as
{}
Custom objects that implement a
__bool__()
or__len__()
method that returnsFalse
or0
All other values are considered truthy.
if 'hello': # Truthy, because the string is not empty
print('True')
if []: # Falsy, because the list is empty
print('True')
else:
print('False')
if 42: # Truthy, because the number is not zero
print('True')
if 0.0: # Falsy, because the number is zero
print('True')
else:
print('False')
Understanding truthiness and falsiness is vital for writing conditional statements and working with logical operations. It allows you to leverage non-boolean values in conditions and can lead to more concise and expressive code. However, it’s essential to be aware of these rules, as unexpected truthiness or falsiness can lead to subtle bugs in a program.
Variable Naming Rules in Python
Variables are used to store data in a program, and their names should be chosen to convey meaning. In Python, the rules for naming variables are:
Start with a Letter or Underscore: Variable names must start with a letter (either uppercase or lowercase) or an underscore.
Contain Only Alphanumeric Characters and Underscores: The rest of the name can consist of letters, numbers, and underscores.
Cannot Be a Reserved Word: Python’s reserved words, such as
if
,for
,while
, cannot be used as variable names.Case-Sensitive: Variable names are case-sensitive, so
myVariable
andmyvariable
are different.Conventions: By convention, variable names are written in snake_case (e.g.,
my_variable
), and constants are written in UPPERCASE.
Common Data Types in Python
Python has several built-in data types that can be grouped into the following categories:
Numeric Types: Integers (int), Floating-Point Numbers (float), Complex Numbers (complex).
Sequence Types: Lists (list), Tuples (tuple), Ranges (range).
Text Type: Strings (str).
Mapping Type: Dictionaries (dict).
Set Types: Sets (set), Frozen Sets (frozenset).
Boolean Type: Boolean (bool), with values
True
orFalse
.Binary Types: Bytes (bytes), Byte Arrays (bytearray).
Type Annotations in Python
Type annotations are used to indicate the expected type of a variable, parameter, or return value. They enhance code readability and can help with error checking.
Here’s how you can use type annotations for different types:
Integers:
x: int = 10
Floats:
y: float = 5.5
Strings:
name: str = "Alice"
Lists:
numbers: list[int] = [1, 2, 3]
Dictionaries:
mapping: dict[str, int] = {'a': 1}
Booleans:
is_active: bool = True
Function Parameters and Return Types:
def add(x: int, y: int) -> int:
return x + y
Understanding the rules for naming variables, the common types in Python, and how to use type annotations will enable you to write clear, expressive, and maintainable code. It’s an essential foundation for programming in Python.
Introduction to Data Structures
Data structures are a way of organizing and storing data in a computer. They provide a means to manage large amounts of data efficiently for uses such as large databases and internet indexing services. In Python, two fundamental data structures are lists and dictionaries.
Lists
Lists are ordered collections of items and are one of the most versatile data structures in Python. They can contain items of different types, but usually, all the items in a list are of the same type.
Dictionaries
Dictionaries are unordered collections where data is stored in key-value pairs. Keys must be unique and immutable, while values can be of any type.
def add_to_list(lst: list, item: int) -> None:
"""Add an item to the list."""
lst.append(item)
def read_from_list(lst: list, index: int) -> int:
"""Read an item from the list by index."""
return lst[index]
def update_list(lst: list, index: int, item: int) -> None:
"""Update an item in the list by index."""
lst[index] = item
def delete_from_list(lst: list, index: int) -> None:
"""Delete an item from the list by index."""
lst.pop(index)
def create_dict() -> dict:
"""Create a new dictionary."""
return {}
def add_to_dict(dct: dict, key: str, value: int) -> None:
"""Add a key-value pair to the dictionary."""
dct[key] = value
def read_from_dict(dct: dict, key: str) -> int:
"""Read a value from the dictionary by key."""
return dct[key]
def update_dict(dct: dict, key: str, value: int) -> None:
"""Update a value in the dictionary by key."""
dct[key] = value
def delete_from_dict(dct: dict, key: str) -> None:
"""Delete a key-value pair from the dictionary by key."""
del dct[key]
Knowledge test
What are lists and dictionaries, and how are they used in Python?
Explain the CRUD operations performed on lists and dictionaries in the code.
How can you handle situations where you attempt to read from or delete a non-existing index or key?
What are some use cases for using lists and dictionaries in programming?
(Answers)
Lists and Dictionary: Example Usage
Here’s a code example for a function that takes two lists as input and creates a dictionary where the keys are from the first list and the values are from the second list. The function ensures that the lists are of the same length.
1def create_dict_from_lists(keys: list[str], values: list[int]) -> dict[str, int]:
2 """Create a dictionary from two lists of equal length.
3
4 Args:
5 keys (list[str]): A list of keys.
6 values (list[int]): A list of values.
7
8 Returns:
9 dict[str, int]: A dictionary with keys from the first list and values from the second list.
10 """
11 if len(keys) != len(values): # Check if lists are of the same length
12 raise ValueError("Keys and values must be of the same length.")
13
14 result_dict = {}
15 for i in range(len(keys)): # Iterate through indices of both lists
16 key = keys[i]
17 value = values[i]
18 result_dict[key] = value
19
20 return result_dict
Dissecting the code
Line 1: Function definition with type annotations for parameters and return type.
Lines 2-10: Docstring explaining the purpose, parameters, and return value of the function.
Line 11: An inline comment mentioning the purpose of the upcoming condition.
Line 12: Checks if the lengths of the keys and values lists are the same; if not, raises a
ValueError
.Line 14: Initializes an empty dictionary to store the result.
Line 15: Uses a for loop to iterate through the indices of the keys list (and implicitly, the values list since they have the same length).
Line 16: Retrieves the key from the keys list using the current index.
Line 17: Retrieves the value from the values list using the current index.
Line 18: Assigns the value to the corresponding key in the result dictionary.
Line 20: Returns the created dictionary.
Knowledge test
What is the purpose of the
create_dict_from_lists
function, and how does it ensure that the input lists are of the same length?How does the
for
loop work in this code, and how are the keys and values retrieved using the index?What error will be raised if the input lists have different lengths, and how can it be handled?
How would you write a test case to verify that the function works correctly with valid input lists?
(Answers)
Unit tests and loops
Advanced topic – mentioned here just as an fyi
In this final section we’ll introduce loops (although you got a sneak peak last section to the _for_ loop) and unit tests. We’ll also showcase the test() function you’ll use in future homework and lab assignments.
import sys
def test(did_pass):
"""Print the result of a test."""
linenum = sys._getframe(1).f_lineno
msg = "Test at line {0} {1}.".format(linenum, "ok" if did_pass else "FAILED")
print(msg)
def factorial(n: int) -> int:
"""Calculate the factorial of a non-negative integer.
Args:
n (int): A non-negative integer.
Returns:
int: The factorial of n.
"""
result = 1
for i in range(1, n + 1): # For loop to iterate through the range
result *= i
return result
def count_odds(numbers: list[int]) -> int:
"""Count the number of odd numbers in a list.
Args:
numbers (list[int]): A list of integers.
Returns:
int: The count of odd numbers in the list.
"""
count = 0
i = 0
while i < len(numbers): # While loop to iterate through the list
if numbers[i] % 2 == 1:
count += 1
i += 1
return count
def test_suite():
"""Run the suite of tests for code in this module (this file)."""
test(factorial(5) == 120)
test(factorial(0) == 1)
test(count_odds([1, 2, 3, 4, 5]) == 3)
test(count_odds([2, 4, 6]) == 0)
test_suite() # Here is the call to run the tests
Dissecting the code
Line 1: Imports the
sys
module, needed to obtain the line number of the calling code in the test function.Lines 3-7: Defines the
test
function, which takes a boolean and prints a success or failure message, including the line number of the test.Lines 9-21: Defines the
factorial
function, which calculates the factorial of a non-negative integer using afor
loop. The docstring and type annotations provide details about the function.Lines 23-38: Defines the
count_odds
function, which counts the number of odd numbers in a list using awhile
loop.Lines 40-46: Defines the
test_suite
function, which runs a series of tests to verify the functionality of thefactorial
andcount_odds
functions.Line 48: Calls the
test_suite
function to run the tests.
Knowledge test
What is the purpose of the
test
function, and how does it obtain the line number of the calling code?Explain the use of the
for
loop in thefactorial
function.Describe how the
count_odds
function uses awhile
loop to achieve its goal.What are the benefits of including docstrings and type annotations in the functions?
How can you write a test to verify that the
factorial
function returns an error for negative input?
(Answers)