Laboratory 1b: Python Review#
Programming skills
Iteration
Functions
Conditional statements
Required hardware: None
Total: 100 points
Student information#
Write your name and email below.
Name:
Email:
Importing required libraries#
import numpy as np # Numpy will assist in manipulating datastructures like arrays.
import matplotlib.pyplot as plt # Matplotlib is MATLAB implementation in python for the purpose of plotting and visualising data.
from matplotlib import rcParams # rcParams
rcParams.update({'font.size': 20}) # for setting text size in plots
Variables and data types#
# --- INTEGER DEFINITION ---
# If no decimal place is provided, Python considers it an integer
a = 9
# --- FLOAT DEFINITION ---
# Specifying a decimal point creates a float
b = 6.05
# --- STRING DEFINITION ---
# Strings are collections of characters, defined with '' or ""
c = 'for'
d = "good"
# --- LIST DEFINITION ---
# Lists are flexible containers that can hold multiple data types
e = [a, b, c]
print("Datatype of variable a = ", type(a))
print("Datatype of variable b = ", type(b))
print("Datatype of variable c = ", type(c))
print("Datatype of variable d = ", type(d))
print("Datatype of variable e = ", type(e))
Datatype of variable a = <class 'int'>
Datatype of variable b = <class 'float'>
Datatype of variable c = <class 'str'>
Datatype of variable d = <class 'str'>
Datatype of variable e = <class 'list'>
# Type conversion from foat to int and int to float
print(int(9.08))
print(float(98))
9
98.0
Common operations on variables#
Addition/Subtraction:
+,-— for numeric variables these perform arithmetic (e.g., \(3 + 2 = 5\)). For sequences like lists or strings,+performs concatenation.Multiplication/Division:
*,/—*multiplies numbers and can repeat sequences;/performs floating-point division (e.g., \(5 / 2 = 2.5\)).Exponentiation:
**— raises a number to a power (e.g., \(2^3\) is written as2 ** 3).Root: Use
np.sqrt()for square roots or fractional powers for \(n^{th}\) roots (e.g.,8 ** (1/3)for \(\sqrt[3]{8}\)).
Data structures#
In computer languages, data structures are systematic ways to represent collections of data. This allows us to manipulate, transform, or search through an entire dataset efficiently.
The most common structures in Python are lists and arrays. Both are sequential, meaning elements are arranged linearly and can be accessed by their position (index).
Lists and arrays#
Python lists#
A general-purpose container that can hold a mixture of different types (integers, strings, or even other lists).
Pros: Flexible and built into Python.
Cons: Slower for mathematical operations and uses more memory.
NumPy arrays#
Specialized for numerical data. All elements are normally of the same type (for example, all floats).
Pros: Extremely fast and supports vectorization (applying mathematics to an entire array at once).
Cons: Less flexible with mixed data types.
Common list commands#
Append:
list.append(x)adds elementxto the end.Delete:
del list[i]removes the element at indexi.Insert:
list.insert(i, x)adds elementxat index positioni.
# Example for working with list
list1 = [3, 14.98, 'cab', np.sqrt(2)]
print(list1)
list1.append(np.sqrt(9))
print(list1)
list1.insert(2, -20) # Adds -20 at index 2 (the 3rd position)
print(list1)
Iteration and indexing#
Both lists and arrays are ordered sequences. Imagine them as a row of boxes, where each box has a specific address called an index.
Zero-based indexing: In Python, we start counting from 0, not 1.
Index |
0 |
1 |
2 |
3 |
4 |
|---|---|---|---|---|---|
Content |
10 |
20 |
30 |
40 |
50 |
my_list[0]would give you 10.my_list[4]would give you 50.
We use iterators (such as a for loop) to visit each box in sequence and perform an action.
# example for using for-loop
for i in range(1, 10):
print("iterating variable value = ", i)
print("Square of the iterating variable = ", i*i)
# example for summing elements using an index-based loop
array1 = np.array([1, -1, 9, -4, 5])
sum_val = 0
for i in range(0, 5):
sum_val = sum_val + array1[i] # the '[i]' keyword after the 'array1' allows one to access the 'ith' element of the array.
print("Total sum of all the elemets =", sum_val)
Problem 1 (5 points). Compute
Start with the code below and fill in the missing pieces.
total = 0
for i in range(____, ____):
total = total + ____
print(total)
Conditional statements#
An if-else statement is a conditional branch. It allows the program to make decisions based on whether a specific condition is True or False.
if: The computer checks the condition. If it is true, the code block directly under it runs.elif(optional): Short for “else if.” It is checked only if the firstifcondition was false.else: The catch-all case. It runs only if none of the preceding conditions were met.
Syntax:
if condition == True:
# run this block
else:
# run this block instead
# Determine whether a number is positive, negative, or zero
num = 10
if num > 0:
print("number is positive")
elif num < 0:
print("number is negative")
else:
print("number is zero")
number is positive
# Example for if-else
number_range_lower_bound = 1
number_range_upper_bound = 11
for i in range(number_range_lower_bound, number_range_upper_bound):
if i % 2 == 0: # Here the '%' operator checks for remainder. If a number is divisible it return 0, else it gives out the remainder.
print("iterator ", i, " is even")
else: # whenever the remainder is non-zero the if-block fails and the else-block is executed.
print("iterator ", i, " is odd")
# Note: The computer will execute any one of the condition blocks. When if-block is satisfied, the else-block won't be executed and vice-versa.
Problem 2 (10 points). Iterate through the integers from 1 through 50 and find all the numbers divisible by 3.
Store the divisible numbers in a new list and print the list.
# Write code here
Built-in functions#
Python provides many ready-to-use functions:
np.array(my_list): Converts a Python list into a NumPy array.len(object): Returns the number of items in a list, array, or string.
# Example of list to array conversion and their dimensions.
list1 = [3, 14.98, 'cab', np.sqrt(2)]
array3 = np.array(list1)
print(array3, array3[2])
print(len(array3[2]), len(list1))
Problem 3 (15 points). Define a list named x containing the integers from \(-10\) through \(10\). Then define a new list y using
Plot y versus x. The graph should resemble a parabola.
# Write your code here
User-defined functions#
A user-defined function is a reusable block of code that performs a specific task. We define functions using the def keyword.
How to define a function:
defkeyword: Tells Python you are creating a function.Function name: A descriptive name (for example,
calculate_area).Arguments (inputs): Variables passed inside the parentheses
().Colon
:: Ends the function header.Indented body: Contains the function’s logic.
returnstatement: Sends the result back to the caller.
Example:
def greet_user(name):
message = "Hello " + name
return message
# Example function for adding
def add_nos(a, b):
c = a + b
return c
# Example for calling the function defined above
x, y = 9, 6
z = add_nos(x, y)
print("Result obtained from the function above = ", z)
Problem 4 (15 points). Define a function that finds both roots of a quadratic polynomial:
You may use the quadratic formula:
# define function
# call function
NumPy array functions#
np.linspace(start, stop, N): Generates \(N\) equally spaced elements.Example:
x = np.linspace(0, 10, 5)creates[0, 2.5, 5, 7.5, 10].
np.asarray(list): Converts a Python list to a NumPy array.Example:
arr = np.asarray([1, 2, 3])converts the list to an array.
np.size(array): Returns the total number of elements in the array.Example:
np.size(np.array([10, 20]))returns2.
Problem 5 (20 points). Approximate the integral
using a left Riemann sum.
A Riemann sum approximates the area under \(f(x)\) by summing rectangle areas. The figure below illustrates this idea (source).
Let \(L_N\) denote the left Riemann sum when \([0,1]\) is divided into \(N\) equal subintervals:
where \(\Delta x = 1/N\) and \(x_i=i\Delta x\).
(a) 5 points: Write code that computes \(L_N\) for \(N=10\).
(b) 5 points: Convert the code from part (a) into a function that computes \(L_N\) for any positive integer \(N\).
(c) 10 points: For Nvals = [10, 100, 1000], compute \(L_N\) for each value and plot \(N\) versus \(L_N\). Explain whether \(L_N\) approaches the exact value of \(I\).
# Write your code here
Problem 6 (20 points). Find where consecutive values in a list change sign. Let x contain 100 equally spaced values from \(-2\) to \(2\), and let y store the corresponding values of
(a) 5 points: Write a function that calculates y.
(b) 5 points: Given two numbers \(a\) and \(b\), explain what the sign of their product \(ab\) tells you about the signs of \(a\) and \(b\).
(c) 5 points: Write code that identifies where consecutive values in y change sign.
(d) 5 points: Write code that counts how many times y changes sign.
# Write your code here
Boolean indexing#
Boolean indexing lets you select data from an array using a corresponding array of True and False values.
x = np.array([-3, -1, 2, 5, -4])
x>0
array([False, False, True, True, False])
Problem 7: Boolean-indexing check (5 points total). Run the code above and answer the following short questions:
(a) What type of object is the output?
(b) How long is it?
(c) Which entries are True?
(d) What happens when you change the last line to x < 0?
x = np.array([-3, -1, 2, 5, -4])
mask = x > 0
x[mask]
array([2, 5])
Continue Problem 7 using the second code example:
(e) What does x[x > 0] return?
(f) What does x[x > 2] return?
This technique is called Boolean indexing: selecting elements from an array with a Boolean (True/False) array of the same length.
# Example for boolean indexing
x = np.array([1, 3, 5, 7, 6, 4, 2])
y = np.array([True, True, True, False, False, True, False])
print("Filtered x: ", x[y])
Filtered x: [1 3 5 4]
# Another example for boolean indexing for fiteration
# A list of temperature readings in Celsius
temps = np.array([-5.2, 12.5, 0.4, -1.8, 25.0, 3.2, -10.5])
# 1. Create a Boolean mask
# This checks which elements are greater than 0
mask = temps > 0
print("Boolean Mask:", mask)
# Output: [False True True False True True False]
# 2. Use the mask to index the array
# This returns only the values where the mask is True
above_freezing = temps[mask]
print("Values above freezing:", above_freezing)
# Output: [12.5 0.4 25. 3.2]
Boolean Mask: [False True True False True True False]
Values above freezing: [12.5 0.4 25. 3.2]
Slicing#
We can also take slices of an array.
arr[a:b]
This selects elements starting at index a
This stops selecting elements before index b
Index b is not included
arr[1:]
This selects elements starting at index 1
Recall, in python, arrays start at index 0
The : with nothing after it means go to the end
It returns all elements except the first one
arr[:-1]
The : with nothing before it means start at index 0
The -1 refers to the last index
It returns all elements except the last one
# --- Example of [:-1] and [1:] Indexing ---
arr = np.array([10, 20, 30, 40, 50])
print(arr)
# arr[:-1] gets all elements EXCEPT the last one: [10, 20, 30, 40]
current_elements = arr[:-1]
print(current_elements)
# arr[1:] gets all elements EXCEPT the first one: [20, 30, 40, 50]
next_elements = arr[1:]
print(next_elements)
# By comparing them, we can find the difference or sign change between neighbors
diff = next_elements - current_elements
print("Difference between neighbors:", diff)
[10 20 30 40 50]
[10 20 30 40]
[20 30 40 50]
Difference between neighbors: [10 10 10 10]
Problem 8 (10 points). Redo Problem 6 using NumPy tools such as np.array(), np.sign(), and Boolean indexing.
Hint: To compare adjacent elements efficiently, use slices such as array[:-1] and array[1:], as shown above.
# Write your code here