Welcome back!
In the last workshop we have covered basics of Python. In this workshop, we will continue introducing more about Python and data structure.
If you didn't attend the last workshop, don't worry. This notebook will include Recaps from the first workshop to refresh your memory about related concept.
In computer science, a data structure is a data organization, management, and storage format that enables efficient access and modification. More precisely, a data structure is a collection of data values, the relationships among them, and the functions or operations that can be applied to the data.
Workshop Best Practices
There are four collection data types in the Python programming language:
When choosing a collection type, it is useful to understand the properties of that type. Choosing the right type for a particular data set could mean retention of meaning, and, it could mean an increase in efficiency or security.
Recap: About Data Types
x = 5
y = "John"
z = 5.55
i = 15j #appending j to an int yields an imaginary number
boo = False
print(x, y, z, i, boo)
5 John 5.55 15j False
# use type() to see the data type of each variable
print(type(x), type(y), type(z), type(i), type(boo))
<class 'int'> <class 'str'> <class 'float'> <class 'complex'> <class 'bool'>
Lists are created using square brackets:
# Create a List with the fruit names: 'apple', 'banana', and 'cherry'
# What are the datatype(s)?
fruits = ['apple', 'banana', 'cherry']
print(fruits)
['apple', 'banana', 'cherry']
List items are ordered, changeable, and allow duplicate values.
Ordered: When we say that lists are ordered, it means that the items have a defined order, and that order will not change. If you add new items to a list, the new items will be placed at the end of the list.
Changeable: The list is changeable, meaning that we can change, add, and remove items in a list after it has been created.
Allow Duplicates: Since lists are indexed, lists can have items with the same value.
Recap: About Indexing
We can access characters in a string by indexing. Square brackets can be used to access elements of the string. The first character has the position 0.
# Get the character at position 1 (remember that the first character has the position 0):
a = "wonderland"
print(a[5])
r
List items are indexed in a similar way to string. The first item has index [0], the second item has index [1] etc.
# index fruits = ['apple', 'banana', 'cherry'] to get 'apple'
fruits = ['apple', 'banana', 'cherry']
print(fruits)
fruits[0]
['apple', 'banana', 'cherry']
'apple'
# Add 'grapes' to the list using .append()
# .append() function is specific to the data type of lists
# i.e. you can't use it on a string value
fruits.append('grapes')
print(fruits)
['apple', 'banana', 'cherry', 'grapes']
# Remove 'grapes' from list using .remove(value)
fruits.remove('grapes')
print(fruits)
['apple', 'banana', 'cherry']
# Pop (store & remove) 'banana' from list using .pop(index)
# Store: The popped value can be stored as a variable
banana = fruits.pop(1)
print(banana)
banana
# Remove: After popping, we'll see that 'banana' got removed
print(fruits)
['apple', 'cherry']
# Lists allow duplicate values:
fruits = ['apple', 'apple', 'cherry']
print(fruits)
['apple', 'apple', 'cherry']
List Length
To determine how many items a list has, use the len() function:
# Print the number of items in the list using len():
len(fruits)
3
List Items - Data Types
List items can be of any data type:
# String, int and boolean data types:
list1 = ['apple', 'banana', 'cherry']
list2 = [1, 5, 7, 9, 3]
list3 = [True, False, False]
print('List 1 is all strings:', list1)
print('List 2 is all integers:', list2)
print('List 3 is all booleans:', list3)
List 1 is all strings: ['apple', 'banana', 'cherry'] List 2 is all integers: [1, 5, 7, 9, 3] List 3 is all booleans: [True, False, False]
A list can contain different data types:
# A list with strings, integers and boolean values:
list4 = ['abc', 34, True, 40, 'male']
print("List 4 is a mixture of data types:", list4)
List 4 is a mixture of data types: ['abc', 34, True, 40, 'male']
Assigning Values to Multiple Variables using Lists
If you have a collection of values in a list, tuple etc. Python allows you extract the values into variables. This is called unpacking.
# Previously, we assigned multiple values like this:
x, y, z = 'apple', 'banana', 'cherry'
print(x, y, z)
apple banana cherry
# define a list named "fruits" containing "apple", "banana", "cherry"
# assign x, y, z to each fruit in the "fruits" list
fruits = ['apple', 'banana', 'cherry']
x, y, z = fruits
print(x, y, z)
apple banana cherry
Tuples are written with round brackets.
# Create a Tuple with the values ('red', 'yellow', 'blue')
colors = ('red', 'yellow', 'blue')
print(colors)
type(colors)
('red', 'yellow', 'blue')
tuple
Like lists, tuples are:
Unlike lists, tuples are:
# duplicate items can be contained in a tuple -- similar to lists
colors = ('red', 'red', 'yellow', 'blue')
print(colors)
('red', 'red', 'yellow', 'blue')
# get "yellow" by index
colors[2]
'yellow'
Tuple Length
To determine how many items a tuple has, use the len() function:
# Print the number of items in the tuple:
colors = ('red', 'yellow', 'blue')
len(colors)
3
Tuple Items - Data Types
Tuple items can be of any data type:
# String, int and boolean data types:
tuple1 = ("apple", "banana", "cherry")
tuple2 = (1, 5, 7, 9, 3)
tuple3 = (True, False, False)
# A tuple can contain different data types:
# A tuple with strings, integers and boolean values
tuple1 = ("abc", 34, True, 40, "male")
Create Tuple With One Item
To create a tuple with only one item, you have to add a comma after the item, otherwise Python will not recognize it as a tuple.
# You can add round brackets to any value without changing its data type
a = ([1, 1])
b = ('apple')
c = (2)
print(type(a), type(b), type(c))
# 1 common use case of round brackets: writing logical statements
if (3 > 2) and (a != b):
print('Random statement holds.')
<class 'list'> <class 'str'> <class 'int'> Random statement holds.
# Try creating a tuple with only one item:
tuple1 = ('red',)
print(type(tuple1))
print(len(tuple1))
<class 'tuple'> 1
Sets are written with curly brackets.
# Create a Set:
set1 = {'cherry', 'apple', 'banana'}
print(set1)
print(type(set1))
{'apple', 'banana', 'cherry'} <class 'set'>
Set items are unordered, unchangeable, and do not allow duplicate values.
# Duplicate values will be ignored:
set1 = {'cherry', 'apple', 'banana', 'banana'}
print(set1)
{'apple', 'banana', 'cherry'}
Get the Length of a Set
To determine how many items a set has, use the len() method.
# Get the number of items in a set:
set1 = {'cherry', 'apple', 'banana'}
len(set1)
3
Set Items - Data Types
Set items can be of any data type:
# String, int and boolean data types:
set1 = {"apple", "banana", "cherry"}
set2 = {1, 5, 7, 9, 3}
set3 = {True, False, False}
# A set with strings, integers and boolean values:
set1 = {"abc", 34, True, 40, "male"}
Different from lists, tuples, and sets, dictionaries are used to store data values in key: value pairs.
Dictionaries are written with curly brackets, and have keys and values:
# Create and print a dictionary:
car_info = {'brand': 'Ford', 'model': 'Mustang', 'year': 1964}
# Adding an key: value pair to the dictionary
# Directly attach the name of the new key in square brackets to your dictionary,
# Assign it to the value you wish to add
car_info = {'brand': 'Ford',
'model': 'Mustang',
'year': 1964}
car_info['color'] = 'red'
print(car_info)
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964, 'color': 'red'}
# Dictionaries don't have the .remove() method
# We use .pop() method to remove 'model' information
# In dictionaries, the pop method takes the key as the argument
car_info.pop('model')
print(car_info)
{'brand': 'Ford', 'year': 1964, 'color': 'red'}
# .pop() in dictionaries store the popped value in a similar way to lists
year_info = car_info.pop('year')
print(year_info)
print(car_info)
1964 {'brand': 'Ford', 'color': 'red'}
# Does not allow duplicate values will overwrite existing values:
car_info = {
"brand": "Ford",
"model": "Mustang",
"year": 1964,
"year": 2020 # only the latter year information is stored
}
print(car_info)
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}
# get value of a certain key using .get()
# let's try to get the "brand" information
car_info.get('brand')
'Ford'
# get keys (no argument is taken)
car_info = {
"brand": "Ford",
"model": "Mustang",
"year": 1964,
"year": 2020 # only the latter year information is stored
}
car_info.keys()
dict_keys(['brand', 'model', 'year'])
Dictionary Length
To determine how many items a dictionary has, use the len() function.
# Find the number of items in the dictionary:
print(car_info)
len(car_info)
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}
3
Dictionary Items - Data Types
The values in dictionary items can be of any data type.
# String, int, boolean, and list, dictionary data types:
car_info = {
"brand": "Ford",
"electric": False,
"year": 1964,
"colors": {"red": 1, "white": 2, "blue": 3}
}
car_info
{'brand': 'Ford', 'colors': {'blue': 3, 'red': 1, 'white': 2}, 'electric': False, 'year': 1964}
# change brand to BMW
# car_info["brand"] = "BMW"
{'brand': 'BMW', 'colors': {'blue': 3, 'red': 1, 'white': 2}, 'electric': False, 'year': 1964}
When to use a dictionary:
When to use the other types:
Python has two primitive loop commands:
These loops are frequently used with If - Elif - Else conditional statements
Recap: If - Elif - Else Statements
a = 2
b = 33
if b > a: #if condition (b > a) is fulfilled
print("b is greater than a")
elif a > b: #else if condition (a > ba) is fulfilled
print("a is greater than b")
else: #else/ in all other cases
print("a is equal to b")
b is greater than a
# a while loop can be combined with else statements
# Print a message once the condition is false:
i = 1
while i < 6:
print(i)
i += 1
1 2 3 4 5
With the while loop we can execute a set of statements as long as a condition is true.
# Print i as long as i is less than 6:
i = 1
Note: remember to increment i by adding 1, or else the loop will continue forever.
The break Statement
With the break statement we can stop the loop even if the while condition is true:
# Exit the loop when i is 3:
# print i in every iteration,
# increment i by 1 at the end of every iteration
i = 1
while i < 6:
print(i)
if i == 3:
break
i += 1
1 2 3
The continue Statement
With the continue statement we can stop the current iteration, and continue with the next:
# Continue to the next iteration if i is 3:
# start from 0 this time
# since the continue statement prevents the code after from running,
# we should increment i by 1 at the beginning
# print i at the end
i = 0
while i < 6:
i += 1
if i == 3:
continue
print(i)
1 2 4 5 6
The else Statement
With the else statement we can run a block of code once when the condition no longer is true:
A for loop is used for iterating over a sequence (that is either a list, a tuple, a dictionary, a set, or a string).
This is less like the for keyword in other programming languages, and works more like an iterator method as found in other object-orientated programming languages.
With the for loop we can execute a set of statements, once for each item in that sequence (e.g. a list, tuple, set etc.)
Recap: Looping Through a String
Even strings are iterable objects, they contain a sequence of characters, i.e. arrays.
Since strings are arrays, we can loop through the characters in a string, with a for loop.
# Loop through the character in the string "apple":
word = 'apple'
for i in word:
print(i)
a p p l e
# Try this: Print each fruit in a fruit list:
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
apple banana cherry
The for loop does not require an indexing variable to set beforehand.
The break Statement
With the break statement we can stop the loop before it has looped through all the items:
# Print the element at the start of each iteration
# Exit the loop when fruit is "banana"
# Hint: use the 'break' statement
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
if fruit == 'banana':
break
apple banana
# Exit the loop when x is "banana",
# but this time the break comes before the print (i.e. 'banana' doesn't need to be printed)
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
if fruit == 'banana':
break
print(fruit)
apple
The continue Statement
With the continue statement we can stop the current iteration of the loop, and continue with the next:
# Do not print 'banana', but print the other elements
# Print the element at the end of each iteration
# hint: use the continue statement
fruits = ["apple", "banana", "cherry"]
apple cherry
The pass Statement in For Loops
for loops cannot be empty, but if you for some reason have a for loop with no content, put in the pass or continue statement to avoid getting an error.
list1 = [1, 2, 3]
# this is a legit for loop with no content
for num in list1:
pass
The difference between Pass and Continue is shown below:
a = [0, 1, 2]
for element in a:
if element == 0:
print('The element is 0')
pass # condition is fulfilled, continues to the rest of loop
print(element)
The element is 0 0 1 2
for element in a:
if element == 0:
print("The element is 0")
continue # makes the statement AND the rest of loop not executable, i.e. continues to the next loop
print(element)
The element is 0 1 2
The range() Function
To loop through a set of code a specified number of times, we can use the range() function,
The range() function returns a sequence of numbers, starting from 0 by default, and increments by 1 (by default), and ends at a specified number.
# Using the range() function, we can specify the number of iterations
for x in range(10):
print(x)
print('This line of code is executed in loop', x)
0 This line of code is executed in loop 0 1 This line of code is executed in loop 1 2 This line of code is executed in loop 2 3 This line of code is executed in loop 3 4 This line of code is executed in loop 4 5 This line of code is executed in loop 5 6 This line of code is executed in loop 6 7 This line of code is executed in loop 7 8 This line of code is executed in loop 8 9 This line of code is executed in loop 9
# print "hello world" 6 times using for loop with range()
for x in range(6):
print("hello, world!")
hello, world! hello, world! hello, world! hello, world! hello, world! hello, world!
Note that range(6) is not the values of 0 to 6, but the values 0 to 5.
The range() function defaults to 0 as a starting value, however it is possible to specify the starting value by adding a parameter: range(2, 6), which means values from 2 to 6 (but not including 6)
Recap: Slicing strings with indices
You can return a range of characters by using the slice syntax.
Specify the start index and the end index, separated by a colon, to return a part of the string.
# Get the characters from position 0 to position 5 (not included):
b = "Hello, World!"
print(b[0:5])
Hello
Indexing a range is very similar to slicing a string
for x in range(1,10):
print(x)
1 2 3 4 5 6 7 8 9
The range() function defaults to increment the sequence by 1, however it is possible to specify the increment value by adding a third parameter: range(2, 30, 3)
Recap: Stepping strings with indices
# [start_index:end_index:step_size]
b = "Hello, World!"
step_b = b[1:8:2]
print(step_b)
el,W
Incrementing a range is very similar to stepping strings with indices
# Increment the sequence with 3 (default is 1):
for x in range(1, 10, 3):
print(x)
1 4 7
Else in For Loop
The else keyword in a for loop specifies a block of code to be executed when the loop is finished:
# Print all numbers from 0 to 5, and print a message when the loop has ended:
for x in range(6):
print(x)
else:
print("Finally finished!")
0 1 2 3 4 5 Finally finished!
Note: The else block will NOT be executed if the loop is stopped by a break statement.
# Break the loop when x is 3, and see what happens with the else block:
for x in range(6):
if x == 3:
break
print(x)
else:
print("Finally finished!")
0 1 2
Nested Loops
A nested loop is a loop inside a loop.
The "inner loop" will be executed one time for each iteration of the "outer loop":
# Print each adjective for every fruit:
adj = ["red", "big", "tasty"]
fruits = ["apple", "banana", "cherry"]
for x in adj:
for y in fruits:
print(x, y)
red apple red banana red cherry big apple big banana big cherry tasty apple tasty banana tasty cherry
A function is a block of code which only runs when it is called.
You can pass data, known as parameters, into a function.
A function can return data as a result.
In Python a function is defined using the def keyword:
def my_function():
print("Hello from a function")
To call a function, use the function name followed by parenthesis:
my_function()
Hello from a function
Information can be passed into functions as arguments.
Arguments are specified after the function name, inside the parentheses. You can add as many arguments as you want, just separate them with a comma.
The following example has a function with one argument (fname). When the function is called, we pass along a first name, which is used inside the function to print the full name:
def add_first_name(fname):
print(fname + " Lee")
# Let's say we want to print out the name "Stan Lee" using this function
add_first_name("Stan")
Stan Lee
Arguments are often shortened to args in Python documentations.
The terms parameter and argument can be used for the same thing: information that are passed into a function.
From a function's perspective:
An argument is the value that is sent to the function when it is called.
A parameter is the variable listed inside the parentheses in the function definition.
Number of Arguments
By default, a function must be called with the correct number of arguments. Meaning that if your function expects 2 arguments, you have to call the function with 2 arguments, not more, and not less.
# This function expects 2 arguments, and gets 2 arguments:
def full_name(fname, lname):
print(fname + " " + lname)
full_name('Peter','Parker')
Peter Parker
Keyword Arguments
You can also send arguments with the key = value syntax.
This way the order of the arguments does not matter.
def youngest(child3, child2, child1):
print("The youngest child is " + child3)
youngest("Peter", "Loki", "Thor")
# alternatively, we can manually reset the argument order and use the 'key=value' syntax,
youngest(child1 = "Thor", child2 = "Loki", child3 = "Peter")
The youngest child is Peter The youngest child is Peter
youngest() # error message will be returned
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-61-9b299445d4db> in <module>() ----> 1 youngest() # error message will be returned TypeError: youngest() missing 3 required positional arguments: 'child3', 'child2', and 'child1'
Default Parameter Value
The following example shows how to use a default parameter value.
If we call the function without argument, it uses the default value:
def my_country(country = "Norway"):
print("I am from " + country)
# if there is a default parameter,
# we can directly call on the function by my_function()
my_country()
# we can also change the argument, try China
my_country('China')
I am from Norway I am from China
Return Values
To let a function return a value, use the return statement:
def multiply_five(x):
return 5 * x
# the returned value can be stored as a variable
result = multiply_five(10)
print(result)
type(result)
50
int
# try to return the following values:
multiply_five(3)
15
A lambda function is a small anonymous function.
A lambda function can take any number of arguments, but can only have one expression.
Syntax
lambda arguments : expression
The expression is executed and the result is returned:
# Add 10 to argument a, and return the result:
x = lambda a : a + 10
print(x(5))
15
def add_10(a):
print(a + 10)
add_10(5)
15
Lambda functions can take any number of arguments:
# Multiply argument a with argument b and return the result:
x = lambda a, b : a * b
print(x(10, 10))
100
print(x(2, 3))
6
# Challenge: How to get 8 using the above lambda fuction?
print(x(2,4))
8
# Summarize argument a, b, and c and return the result:
y = lambda a, b, c : a + b + c
print(y(1, 2, 3))
6
# Rewrite y by defining a normal function
# called on the function with arguments: a=1, b=2, c=3
6
Why Use Lambda Functions?
They are useful when you want a function that you will use just one time.
They contain simple logical operations that are easy to read and understand.
The power of lambda is better shown when you use them as an anonymous function inside another function.
Say you have a function definition that takes one argument, and that argument will be multiplied with an unknown number:
def my_func(n):
return lambda a : a * n
Use that function definition to make a function that always doubles the number you send in:
def my_func(n):
return lambda a : a * n
# By implementing a lambda function within my_func()
# you can make another function with my_func() by assigning it to a variable,
# (i.e. without necessarily defining it the normal way)
# Let's decalre my_doubler, which is a function that doubles up the input argument
# it can take an argument and pass into the lambda function declared within my_func()
my_doubler = my_func(2)
print(my_doubler(11)) # this argument is the argument a in the lambda function
# in other words, it passes a = 11 into my_func(2), where n = 2
# therefore, my_doubler(11) will return 11 * 2 = 22,
# which corresponds to the lambda a : a * n
22
# if you try to input 2 arguments, you'll see an wrror
# because the lambda function inside my_func() only takes 1 argument
print(my_doubler(11, 10))
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-82-93ad7f27537c> in <module>() ----> 1 print(my_doubler(11, 10)) TypeError: <lambda>() takes 1 positional argument but 2 were given
# Exercise I: Write a for loop to sum up all the items in the following list
# Hint: initialize a variable first to store the sum (e.g. sum = 0)
num_list = [8, 9, 2, 65, 39, 1, 4, 32, 100]
# Exercise II:
# Previously in the Nested Loop exercise, we print each adjective for every fruit:
adj = ["red", "big", "tasty"]
fruits = ["apple", "banana", "cherry"]
for x in adj:
for y in fruits:
print(x, y)
red apple red banana red cherry big apple big banana big cherry tasty apple tasty banana tasty cherry
# What if we want to get the following output (i.e. matching each element in order)?
# Hint: think about indexing in lists, and making logical comparisons
red apple big banana tasty cherry
# Exercise III: Change the 'city' information to 'New York'
iron_man = {"name": "Tony Stark",
"city": "Los Angeles",
"age": 51,
"profession": "Industrialist"}
#Type your answer below.
# Exercise IV: Define a function that returns the age of super heroes using the following dictionary
# Hint: Use 2 arguments -- 1 for the dictionary name, 1 for the key name
# Think about how to get values by key using .get()
# Lastly, try to get the age of Black Widow by calling on this function
super_hero_age = {'Iron Man': 51,
'Spider Man': 28,
'Hulk': 49,
'Black Widow': 37,
'Captain America': 99,
'Thor': 1500}
Solutions are in the Workshop Drive.
If you want more assistance/ explanations, kindly contact shanghai.library@nyu.edu
Ending credits
Tutorial framework: https://www.w3schools.com/python/default.asp
Modified and organized by: Pamela Pan, Jie Chen