Python Fundamentals#
This notebook contains material from the Pyomo Summer Workshop 2018 by the Pyomo Developement Team and the notebook is developed by David Bernal (dbernaln@purdue.edu), Zedong Peng (peng372@purdue.edu), and Albert Lee (lee4382@purdue.edu); the content is available on Github. The original sources of this material are available on Pyomo.
1. Lists#
Lists are mutable sequences, typically used to store collections of homogeneous items (where the precise degree of similarity will vary by application).
Lists are enclosed by brackets ([ ]
) and their elements and size can be changed.
In this section, we will learn how to replace the elements of a list, and index a number specifying the position of an item in a sequence
s[i]
return the item at index i
.
The list is given as follows:
a = [1, 2, 3, 4, 5]
Inline Exercise 1.1: Replace the '1' in the list with the string 'foo'.
# TODO: INSERT CODE HERE TO REPLACE THE '1' IN a WITH THE STRING "foo"
# TODO: INSERT CODE HERE TO REPLACE THE '1' IN a WITH THE STRING "foo"
a = [1, 2, 3, 4, 5]
a[0] = "foo"
print("CHECK a is:", a) # check your work
CHECK a is: ['foo', 2, 3, 4, 5]
Inline Exercise 1.2: Replace the `4` in the list `a` with the string `bar`.
# TODO: INSERT CODE HERE TO REPLACE THE '4' IN a WITH THE STRING "bar"
# TODO: INSERT CODE HERE TO REPLACE THE '4' IN a WITH THE STRING "bar"
a = [1, 2, 3, 4, 5]
a[3] = "bar"
print("CHECK a is:", a) # check your work
CHECK a is: [1, 2, 3, 'bar', 5]
In Python, all sequences, be they lists, strings, or tuples, support indexing, which allows for the direct access of individual items within the sequence.
The numbering of these indices starts from zero (0
); hence, the initial item in any sequence is found at the zeroth index.
This implies that for a sequence of n
elements, the last item would be positioned at an index of n-1
.
Inline Exercise 1.3: Given the list `a`, guess what the output of `print(a[-1])` will print.
# TODO: INSERT CODE HERE TO PRINT WHAT YOU THINK 'print(a[-1])' WILL PRINT
# TODO: INSERT CODE HERE TO PRINT WHAT YOU THINK 'print(a[-1])' WILL PRINT
print(5)
print("CHECK a[-1] is:", a[-1]) # check your work (don't just write this for your answer!)
5
CHECK a[-1] is: 5
Another unique feature of sequence indexing in Python is the support for negative indices, which provide a means to count from the end of the sequence towards the beginning.
Utilizing this approach, the last item of any given sequence can be accessed using an index of -1
.
Progressively, moving further towards the start of the sequence, the indices decrease, meaning the penultimate item would be at index -2
, and so forth.
Remarkably, the first item in a sequence can also be accessed using negative indexing by specifying the negative of the sequence’s length, denoted as -length
.
Inline Exercise 1.4: Given the list `a`, modify `a` so that the output is `[1, 2, "hello", "world", 4, 5]`.
# TODO: INSERT CODE HERE TO MODIFY a SO IT IS [1, 2, "hello", "world", 4, 5]
# TODO: INSERT CODE HERE TO MODIFY a SO IT IS [1, 2, "hello", "world", 4, 5]
a = [1, 2, 3, 4, 5]
a[2:3] = ["hello", "world"]
print("CHECK a is:", a) # check your work
CHECK a is: [1, 2, 'hello', 'world', 4, 5]
In Python, slicing allows you to access a subset or a range of elements from a sequence-like object such as a list, string, or tuple.
This can be accomplished by specifying two indices in the format s[i:j]
, where s
is the sequence.
This expression denotes a slice starting at index i
and ending just before index j
.
Inline Exercise 1.5: After setting list `b`, what do you expect `print(a[2])` to output?
b = a
b[2] = "small"
# TODO: INSERT CODE HERE TO PRINT WHAT YOU THINK 'print(a[2])' WILL PRINT
b = a
b[2] = "small"
# TODO: INSERT CODE HERE TO PRINT WHAT YOU THINK 'print(a[2])' WILL PRINT
print("small")
print("CHECK a[2] is:", a[2]) # check your work (don't just write this for your answer!)
small
CHECK a[2] is: small
In Python, using the assignment operator as in b = a
for lists doesn’t create a new copy.
Instead, a
and b
point to the same list in memory.
Therefore, changes made using one variable (like b[2] = "small"
) also appear when accessed through the other (a
), demonstrating Python’s handling of object references.
List comprehensions provide a concise way to create lists. Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable, or to create a subsequence of those elements that satisfy a certain condition.
Inline Exercise 1.6: `c` is given as a list comprehension. Find what you think `print(c[3])` will output.
c = [x for x in range(2, 10)] # this is a list comprehension!
# TODO: INSERT CODE HERE TO PRINT WHAT YOU THINK 'print(c[3])' WILL PRINT
c = [x for x in range(2, 10)] # this is a list comprehension!
# TODO: INSERT CODE HERE TO PRINT WHAT YOU THINK 'print(c[3])' WILL PRINT
print(5)
print("CHECK c[3] is:", c[3]) # check your work (don't just write this for your answer!)
5
CHECK c[3] is: 5
A list comprehension consists of brackets containing an expression followed by a for
clause, then zero or more for
or if
clauses.
The result will be a new list resulting from evaluating the expression in the context of the for
and if
clauses which follow it.
Inline Exercise 1.7: Using the list comprehensions in Python, write code that transforms the given list `d = [6, 5, 4, 3, 2]` into `[7, 6, 5, 4, 3]`` by adding 1 to each element.
# TODO: INSERT CODE HERE TO USE LIST COMPREHENSION TO CREATE THE FOLLOWING LIST:
# [7, 6, 5, 4, 3]
# USING THE LIST d GIVEN ABOVE. THEN PRINT IT.
# TODO: INSERT CODE HERE TO USE LIST COMPREHENSION TO CREATE THE FOLLOWING LIST:
# [7, 6, 5, 4, 3]
# USING THE LIST d GIVEN ABOVE. THEN PRINT IT.
d = [6, 5, 4, 3, 2]
d = [x+1 for x in d]
print(d)
[7, 6, 5, 4, 3]
2. Dictionaries#
A dictionary in Python is a mutable and dynamic data structure that maps unique keys to corresponding values, akin to a table. Keys, which are immutable, can be integers, strings, floats, tuples, booleans, or the NoneType, but not mutable types like lists or dictionaries. Values, however, can be any Python object, mutable or immutable. This structure makes dictionaries a versatile tool in Python for storing and manipulating diverse data types in an intuitive key-value format.
We will conduct some exercise problems with the following dictionary
d = {"tree": "wood", "flower": "petal", "earth": "water", 101: [4, 6, 8]}
d = {"tree": "wood", "flower": "petal", "earth": "water", 101: [4, 6, 8]}
In Python, dictionaries are mutable, which means we can change their content without changing their identity.
Inline Exercise 2.1: Given the dictionary `d`, change the value of the key `tree` into `leaves`.
# TODO: INSERT CODE HERE TO REPLACE "wood" WITH "leaves"
# TODO: INSERT CODE HERE TO REPLACE "wood" WITH "leaves"
d["tree"] = "leaves"
In Python, dictionaries are not fixed in size. This means that new key-value pairs can be added to the dictionary at any time.
Inline Exercies 2.2: Given the dictionary `d`, add a new key-value pair `monty: python` to the dictionary.
# TODO: INSERT CODE HERE TO ADD THE PAIR "monty": "python"
# TODO: INSERT CODE HERE TO ADD THE PAIR "monty": "python"
d["monty"] = "python"
d[key]
returns the value for key in the dictionary. If key is not available, then a KeyError will be raised.
Inline Exercise 2.3: Given the dictionary `d`, what do you think `print(d["earth"])` will output?
# TODO: INSERT CODE HERE TO FIRST CHECK IF "earth" IS A KEY,
# AND IF IT IS THEN PRINT THE VALUE IT MAPS TO
# TODO: INSERT CODE HERE TO FIRST CHECK IF "earth" IS A KEY,
# AND IF IT IS THEN PRINT THE VALUE IT MAPS TO
if "earth" in d:
print("The value of 'earth' is:", d["earth"])
else:
print("'earth' is not found in the dictionary.")
The value of 'earth' is: water
Inline Exercise 2.4: Print all the pairs in the dictionary `d`.
# TODO: INSERT CODE HERE TO PRINT ALL THE PAIRS IN d
# TODO: INSERT CODE HERE TO PRINT ALL THE PAIRS IN d
print("All key-value pairs:")
print(list(d.items()))
All key-value pairs:
[('tree', 'leaves'), ('flower', 'petal'), ('earth', 'water'), (101, [4, 6, 8]), ('monty', 'python')]
3. Functions#
A function in Python is a reusable block of code designed to perform a specific task. They play a pivotal role in structuring programs by enabling a divide-and-conquer approach, where a large task is broken down into several smaller, more manageable tasks.
When a function is defined, its code isn’t executed immediately. Instead, the function’s code is run whenever the function is called.
This call can come from various control structures within the program, including sequential code flow and within conditional (like if
statements) or repetition structures (like for
and while
loops).
By encapsulating specific tasks in functions, we can create more organized, readable, and efficient programs.
There are several Exercise Problems for you to practice.
Exercise 3.1#
Write a function that takes in a list of numbers and prints the value of the largest number. Be sure to test your function. Start with the following code:
def print_max_value(nums):
##TODO
def print_max_value(nums):
print("The max value is: ")
print(max(nums))
test = [1, 2, 3, 4, 5]
print_max_value(test)
The max value is:
5
Exercise 3.2#
Write a function that takes a list of numbers and returns the largest number. Start with the following code:
def max_value(nums):
##TODO
def max_value(nums):
return max(nums)
test = [1, 2, 3, 4, 5]
print(max_value(test))
5
Exercise 3.3#
Do so without using any built-in functions. Start with the following code:
def my_max_value(nums):
##TODO
def my_max_value(nums):
tmp = nums[0]
for i in range(1, len(nums)):
if nums[i] > tmp:
tmp = nums[i]
return tmp
test = [1, 2, 3, 4, 5]
print(my_max_value(test))
5
Exercise 3.4#
Call both functions on a couple different lists of numbers to verify they return the same value.
l1 = [1, 3, 0, 5, -2]
ans1 = max_value(l1)
print(ans1)
ans2 = my_max_value(l1)
print(ans2)
l2 = [12, 0, 11.9]
print(max_value(l2))
print(my_max_value(l2))
The max value of l1 is 5, and the max value of l2 is 12.
max_value()
and my_max_value()
returneed the same values for both lists.
l1 = [1, 3, 0, 5, -2]
ans1 = max_value(l1)
print('Max value using the built-in functions :', ans1)
ans2 = my_max_value(l1)
print('Max value without using the built-in functions :', ans2)
l2 = [12, 0, 11.9]
print('Max value using the built-in functions :', max_value(l2))
print('Max value without using the built-in functions :', my_max_value(l2))
Max value using the built-in functions : 5
Max value without using the built-in functions : 5
Max value using the built-in functions : 12
Max value without using the built-in functions : 12
Exercise 3.5#
Write a function that takes a list of numbers and returns a dict consisting of the smallest and largest number (use keys ‘smallest’ and ‘largest’). Be sure to test your function. Start with the following code:
def max_and_min(nums):
##TODO
def max_and_min(nums):
return {'smallest': min(nums), 'largest': max(nums)}
test = [1, 2, 3, 4, 5]
print(max_and_min(test))
{'smallest': 1, 'largest': 5}
Exercise 3.6#
Write a function that takes in two lists and prints any common elements between them hint: check if an item is in a list using: if item in list
def get_common(l1, l2):
##TODO
def get_common(l1, l2):
for i in l1:
if i in l2:
print(i)
get_common(l1, l2)
0
4. For Loops#
A for loop in Python is a control flow structure that allows for a fixed number of iterations, determined by the size of the iterable it traverses. An iterable, in this context, is any object capable of returning its elements one at a time, examples of which include strings, lists, and ranges, among others. With each iteration of the for loop, the variable (often referred to as the loop variable or item) is set to a different value from the iterable. This process continues until all values in the iterable have been assigned to the variable, marking the completion of the loop’s iterations. There are several Exercise Problems for you to practice.
Exercise 4.1#
Inline Exercise 4.1: Write a for loop that prints the entries of the following list, one at a time:
words = ["Wow,", "python", "is", "really", "cool."]
##TODO
words = ["Wow,", "python", "is", "really", "cool."]
##TODO
for i in words:
print(i)
Wow,
python
is
really
cool.
Exercise 4.2#
Inline Exercise 4.2: Write a for loop that computes 2^n only using multiplication by 2.
n = 5
##TODO
n = 5
##TODO
val = 2
for i in range(0,n-1):
val = val*2
print(val)
32
Exercise 4.3#
Inline Exercise 4.3: Write a for loop that adds 1 to elements in a list and prints their squared value.
nums = [0, 3, -2, -1]
##TODO
nums = [0, 3, -2, -1]
##TODO
for i in nums:
print((i+1)**2)
1
16
1
0
5. Pandas#
Exercise 5.1#
Your colleague wants to build a classifier that will identify types of bears, but is having trouble importing data for her project. Lucikly, you know about pandas. No, not the fluffy black and white things, the python data manipulation package.
The file bears-are-bears.csv contains a human-generated categorization of several bear specimens obtained by underpaying undergraduate students to collect data. Please import the file and display it to the console to verify that it matches your expectations.
import pandas as pd
# df = pandas.read_csv(--CODE TO IMPORT HERE--)
# print(df)
df = pd.read_csv('bears-are-bears.csv', index_col=0)
print(df)
Bear Type Weight (kg) Color Endangered Bear Necessities \
Tag #
1 Black bear 280 Black You Charmin Ultra
2 Brown bear 700 Brown No NaN
3 Polar bear 80 White Yes NaN
4 Andean bear 200 Black Vulnerable NaN
5 Panda bear 113 Black and white NaN Bamboo
6 Sloth bear 100 Black Yes NaN
7 Sun bear 50 Black Yes NaN
8 Panda bear 123 Black and white Yes Bamboo
9 Black bear 287 Brown No NaN
10 Black bear 276 Black No NaN
Speed Eats
Tag #
1 Fast Everything
2 NaN Salmon
3 Faster in water Not enough
4 NaN bromeliads
5 NaN Bamboo
6 Slow Insects
7 NaN Insects
8 NaN Bamboo
9 Fast Everything
10 Fast Everything
Exercise 5.2#
Your colleague wants to have an alphabetically sorted unique list of all the bear types. Generate this from the pandas DataFrame.
# sorted_bears = --CODE HERE TO CREATE UNIQUE SORTED LIST--
# print("Sorted bears list:")
# print(sorted_bears)
sorted_bears = sorted(df['Bear Type'].unique().tolist())
print("Sorted bears list:")
print(sorted_bears)
Sorted bears list:
['Andean bear', 'Black bear', 'Brown bear', 'Panda bear', 'Polar bear', 'Sloth bear', 'Sun bear']