IT 117: Intermediate Scripting
Class 8
General Advice
Review
New Material
Microphone
Questions
Are there any questions before I begin?
Readings
If you have the textbook read Chapter 9, Dictionaries and Sets
section 9.2, Sets.
Homework 4
I have posted homework 4
here.
It is due this coming Sunday at 11:59 PM.
Quiz 2
I have posted the answers to Quiz 2
here.
Let's review the answers.
Today's Class
Today I will discuss Python sets.
General Advice
Keep Each Study Period Short
- Do not spend more than 1 hour on a study session
- Otherwise you may find that your attention wanders ...
- as your brain gets tired
- If you spread out your study session over the week ...
- you will learn more
- The first time you read something new you might miss important details
- Your brain needs time to absorb the material you have just studied
- Each time you look at new material it will become more familiar
- Things that you did not understand at first become clearer with time
- It's also a great way to break up a big task ...
- into smaller chunks
- A few summers ago I needed to spread mulch over my yard
- My house is on a corner so it's a big yard
- It took 170 bags of mulch to cover the area
- I no longer have the stamina that I had when I was your age
- I could not spread 170 bags in one, two or even three sessions
- But I learned that I could spread 6 bags without to much trouble
- Every day when the weather permitted I spread 6 bags
- By the end of the summer the job was done
Review
Values in a Boolean Context
- If you use an expression whose value is a number or a string ...
- in a place where Python expects a boolean expression ...
- the interpreter will automatically apply the
bool conversion function ...
- to turn the string or number into a boolean value ...
- which can be used in
if statements and while loops
- If the string expression is the
empty string ...
- Python will treat it as false
>>> value = ""
>>> if value:
... print("True")
... else:
... print("False")
...
False
- If the string expression is not the empty string ...
- Python will treat it as true
>>> value = "x"
>>> if value:
... print("True")
... else:
... print("False")
...
True
- Python will so something similar with numbers
- To show how this works, let's create a test function
>>> def true_or_false(value):
... if value:
... print("True")
... else:
... print("False")
...
- Any expression whose value is zero will be treated as false
>>> true_or_false(0)
False
>>> true_or_false(0.0)
False
- Any expression whose value is not zero will be treated as true
>>> true_or_false(1)
True
>>> true_or_false(4)
True
- This even works for negative values
>>> true_or_false(-1)
True
>>> true_or_false(-100)
True
- This even works with objects
- Any variable that points to an object will be treated as true
>>> file = open("students.txt", "r")
>>> file
<_io.TextIOWrapper name='students.txt' mode='r' encoding='UTF-8'>
>>> true_or_false(file)
True
- Can an object variable ever be false?
- Python has a special value called
None
- An object variable whose value is
None points to nothing
- It's like zero for objects
- So an expression whose value is
None is false
>>> true_or_false(None)
False
Keys Are Immutable
- There is only one constraint on dictionaries
- The keys of a dictionary must be
immutable
- In other words they must be things that cannot be changed
- The following data types can be used as keys
- Strings
- Integers
- Floats
- Tuples
- But we can't create a dictionary using lists as keys
>>> lists_integers = {[1,1]:1, [2,2]:2, [3,3]:3}
Traceback (most recent call last):
File <stdin>, line 1, in <module>
TypeError: unhashable type: 'list'
- Why this restriction?
- When a entry is added to a dictionary, the hash function runs on the key
- This function returns the slot number for the entry
- If the key is subsequently changed ...
- the function will give the wrong slot number
- So you won't be able to retrieve the value
Values in a Dictionary
- The keys in a dictionary must be immutable data types
- But the values can be anything
>>> jumble = {1:1, 2:2.0, 3:"three", 4:(4,4), 5:[5]}
>>> for key in jumble:
... print(jumble[key])
...
1
2.0
three
(4, 4)
[5]
- In this example all the keys are integers but all the values are of different
data types
- In this case all the keys were of the same data type
- That is the most common situation, but it is not a requirement
Dictionary Methods
- Dictionaries are
objects so they have have methods
- Here are some of the more useful dictionary methods
| Method |
Description |
| get(key) |
Gets the value associated with a specified key.
If the key is not found, the method does not raise an
exception. Instead, it returns a default value.
To change the default value, provide a 2nd argument.
|
| pop(key) |
Returns the value associated with a specified key and removes
that key-value pair from the dictionary.
If the key is not found, the method returns a default value.
To change the default value, provide a 2nd argument.
|
| popitem() |
Returns the last key-value pair added to the
dictionary as a tuple and removes that key-value pair
from the dictionary.
|
The get Method
- We usually access the value for a key using the bracket operator, like this
>>> quiz_scores["Mary Jones"]
[98, 95, 93]
- But if we get the key wrong, Python will raise an exception
>>> quiz_scores["Mary Jonez"]
Traceback (most recent call last):
File <stdin>, line 1, in <module>
KeyError: "Mary Jonez"
- The get method works just like the
[ ] operator when we use a valid key
>>> quiz_scores.get("Mary Jones")
[98, 95, 93]
- But when we use an invalid key, get does not
throw an exception
- Instead it returns the special value
None
>>> scores = quiz_scores.get("Mary Jonez")
>>> print(scores)
None
- If you use a variable whose value is
None in an
if statement
- Python treats this value as false
>>> bool(None)
False
The pop Method
- The pop method takes a key as an argument ...
- returns the value associated with that key ...
- and removes the key-value pair from the dictionary
>>> quiz_scores
{"Mary Jones": [98, 95, 93], "Tim Tyler": [88, 81, 79], "John Smith": [100, 90, 85]}
>>> quiz_scores.pop("Mary Jones")
[98, 95, 93]
>>> quiz_scores
{"Tim Tyler": [88, 81, 79], "John Smith": [100, 90, 85]}
The popitem Method
- popitem is like pop
- But it returns returns the last key-value pair added to the dictionary
- It it also removes that entry from the dictionary
>>> quiz_scores
{"Tim Tyler": [88, 81, 79], "John Smith": [100, 90, 85]}
>>> quiz_scores.popitem()
("Tim Tyler", [88, 81, 79])
>>> quiz_scores
{"John Smith": [100, 90, 85]}
Attendance
New Material
Sets in Mathematics
- It's hard to take a college level Math course without encountering the concept
of a
set
- The definition of a set is simple
- It is an unordered collection of distinct objects
- You can put anything into a set
- But you can't have two of anything
- The set with nothing in it is called the
empty set
Set Membership
- If the value x is contained in set
A, we say that x is a
member
of A
- In mathematics the assertion that x
is an element of A is written
x ∈ A
Subsets and Supersets
- If all the values in set A are also in B
we say that A is
subset
of B
- The situation is shown in the following diagram
- In mathematics, the assertion that
A
is a subset
of B
is written
A ⊂ B
- Another way to describe this relationship
is to say that B is a
superset
of A
- In mathematics this relationship is written
B ⊃ A
Union of Sets
- There are a number of operations on sets that can create new sets
- Let's say we have two sets, A and B
- A set which has all the elements of the both sets ..
- is called the
union
of A and B ...
- and is written
A ∪ B
- In the diagram below the union of A and
B is shown in red
Intersection of Sets
- A set which only has elements that are in both A
and B ...
- is called the
intersection
of A and B ...
- and is written
A ∩ B
- In the diagram below, the intersection of A
and B is shown in red
Difference between Sets
- A set of all the elements in A which are not
in B ...
- is called the
difference
between A and B ...
- and is written
A - B
- In the diagram below, the difference between A
and B is shown in red
Symmetric Difference between Sets
- The set of all elements in A not in
B ...
- and all the elements in B not in
A ...
- is called the
symmetric difference
between A and B
...
- and is written
A Δ B
- In the diagram below the symmetric difference between
A and B is shown in
red
Sets in Python
- Sets in Python are objects
- They follow the mathematical definition of a set
- A Python set is an object which holds an unordered collection
of unique items
- The values in a Python set must be
immutable
- That means the elements can be
- Integers
- Floats
- Strings
- Booleans
- Tuples
- But they cannot be lists or dictionaries
Set Literals
- A list
literal
is has values, separated by commas, inside square brackets
>>> list_1 = [1, 2, 3, 4, 5]
>>> type(list_1)
<class "list">
- A set literal uses curly braces
>>> nonsense = {"foo", "bar", "bletch"}
>>> type(nonsense)
<class "set">
Creating a Set in Python
- You can create a set in Python using the builtin
set function
set takes a single argument
- That argument must be
iterable
- A Python object is iterable if you can use it in a
for loop
- This means you can use any of the following as an argument to
set
- Lists
- Tuples
- Dictionaries
- Strings
- Let's see this in action with a list
>>> num_list = [1,2,3]
>>> num_set = set(num_list)
>>> num_set
{1, 2, 3}
- It also works with a
tuple
>>> letter_tuple = ("a", "b", "c")
>>> letter_set = set(letter_tuple)
>>> letter_set
{'a', 'c', 'b'}
- And a string
>>> letter_set_2 = set("abcde")
>>> letter_set_2
{'b', 'a', 'c', 'd', 'e'}
- Notice that the letters do not appear in the same order ...
- as they do in the string
- When we use a dictionary to create a set
>>> numb_set_2 = set({"one": 1, "two": 2, "three": 3})
>>> numb_set_2
{"one", "two", "three"}
only the keys are used
- If the argument to
set contains duplicate values
- Only one is used
>>> letter_set_3 = set("Mississippi")
>>> letter_set_3
{"i", "M", "s", "p"}
The Empty Set
- We can use empty square brackets to create an empty list
>>> empty = []
>>> type(empty)
<class "list">
- But we cannot use empty curly braces to create a empty set
- The empty curly braces denote an empty dictionary
>>> empty = {}
>>> type(empty)
<class "dict">
- When the creators of Python got to set literals
- They ran out of symbols to enclose the elements
- So they had to reuse { }
- So how do you create an empty set?
- You run
set with no arguments
>>> set_1 = set()
>>> set_1
set()
- You cannot create an empty set like this
>>> set_2 = {}
- This creates not a set but a dictionary
>>> type(set_2)
<class 'dict'>
- That is why an empty set
empty_set = set()
- Looks like this
>>> empty_set
set()
Adding Elements to a Set
- Sets are
mutable
- They can be changed
- There are two set methods that can be used to add elements to a set
- add adds a single element to a set
- So if we start with an empty set
>>> set_1 = set()
>>> set_1
set()
- We can use add to add individual elements
>>> set_1.add(1)
>>> set_1
{1}
>>> set_1.add("two")
>>> set_1
{1, "two"}
>>> set_1.add((3,3,3))
>>> set_1
{(3, 3, 3), 1, "two"}
- If you add an element to a set that is already in the set ...
- nothing will change
>>> set_1.add(1)
>>> set_1
{(3, 3, 3), 1, "two"}
- But this won't raise an
exception
- The update method adds several elements to a set
- It takes one argument, which must be iterable
>>> set_2 = set()
>>> set_2
set()
>>> set_2.update([1, 2, 3])
>>> set_2
{1, 2, 3}
>>> set_2.update("foo")
>>> set_2
{1, 2, 3, "f", "o"}
- Notice that only one "o" was added to the set ...
- and no exception was raised
Removing Elements from a Set
- To remove an element from a set, use one of two methods
- Both methods take a single argument ...
- the value that is to be removed
>>> numb_set
{1, 2, 3, 4, 5}
>>> numb_set.discard(2)
>>> numb_set
{1, 3, 4, 5}
>>> numb_set.remove(4)
>>> numb_set
{1, 3, 5}
- The only difference is what happens ...
- when you remove a value that is not in the set
- discard will say nothing
>>> numb_set.discard(2)
>>> numb_set
{1, 3, 5}
- But remove will raise an exception
>>> numb_set.remove(4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 4
Why Must Set Elements Be Immutable?
- The elements of a set must be immutable
- That means we can add numbers, strings and tuples to a set
>>> s = set()
>>> s
set()
>>> s.add(1)
>>> s.add(2.0)
>>> s.add("three")
>>> s.add((4,4,4,4))
>>> s
{1, 2.0, (4, 4, 4, 4), 'three'}
- But not dictionaries
s.add({})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
- The reason is that Python implements sets using
hash tables
- It does this for efficiency
- A basic question you can ask a set ...
- is if it contains a specific value
- If sets were implemented using lists ...
- Python would have search the entire list ...
- to find that some value was not in the set
- Also, think what happens when a value is added to a set
- Python needs to check that it is not already in the set
- Because a set cannot have duplicate entries
- So each time we add a value we might have to search the entire list
- But with hash tables all we have to do is run the hash function
- That will give us the slot number for each new element
- If the slot is empty, we can add it
- If not, we can't
- This is why the order in which values are added to the set ...
- is not the order in which the appear ...
- in a
for loop
- If we create a set with elements in a certain order
>>> strings = set()
>>> strings.add("foo")
>>> strings.add("bar")
>>> strings.add("bletch")
>>> strings.add("ding")
>>> strings.add("dong")
- We will usually not see that order when we print the set
>>> strings
{'bar', 'foo', 'dong', 'ding', 'bletch'}
- This used to be true of dictionaries too
- But programmers objected
- So they had to add complexity to the implementation of dictionaries ...
- to order entries in the order in which they were entered
Class Exercise
Class Quiz