<jupyter_start><jupyter_text>Beginning Programming in Python Dictionaries/Sets CSE20 - Spring 2021Interactive Slides: [https://tinyurl.com/cse20-spr21-dictionaries-sets](https://tinyurl.com/cse20-spr21-dictionaries-sets)  Dictionaries- A mapping type that defines **key:value** relationships between values- A **key** is a unique value that is associated with its respective **value**- All of the **key**s in a dictionary have to be unique and can be any hashable type. **Value**s do not have to be unique. - **key**s can be any type and a single dictionary can use multiple types as keys- Dictionaries are a mutable type- No particular naming convention for variables, just choose informative variable names  Dictionaries: Instantiation (Creation)- There are a few ways to instantiate a dictionary. The way we'll go over today is using curly braces `{key:value}`<jupyter_code>nums_to_strings = {1:"one", 2:"two", 3:"three"}
strings_to_nums = {
    "one":1,
    "two":2,
    "three":3
}<jupyter_output><empty_output><jupyter_text>Dictionaries: Instantiation (Creation)<jupyter_code>mixed_types_dict = {
    1: "one",
    "two": 2.0,
    "another_dict": {"three": 3},
    "a list": [1, 2, 3]
}

print(mixed_types_dict)<jupyter_output>{1: 'one', 'two': 2.0, 'another_dict': {'three': 3}, 'a list': [1, 2, 3]}<jupyter_text>Dictionaries: Access- To access/retrieve the **value**s stored in a dictionary we use square brackets with the **key** `[key]`- We can only access a single value at a time using a single key- Dictionaries are considered **unordered** so the keys are not guaranteed to be in the order that they were added in.  Dictionaries: Access<jupyter_code>nums_to_strings = {1:"one", 2:"two", 3:"three"}
strings_to_nums = {
    "one":1,
    "two":2,
    "three":3
}

print(nums_to_strings[2])
print(strings_to_nums["two"])<jupyter_output>two
2<jupyter_text>Dictionaries: Access- If you try to use a key doesn't exists in the dictionary it will raise a `KeyError`- If your not sure if a key is in a dictionary you can use the membership operators `in` and `not in` to check for the key<jupyter_code>nums_to_strings = {1:"one"}

print(2 in nums_to_strings)
print(nums_to_strings[1])<jupyter_output>False
one<jupyter_text>Dictionaries: Updates- To update/add **value**s stored in a dictionary we use square brackets with the **key** `[key]`<jupyter_code>nums_to_strings = {1:"one"}
print(nums_to_strings)
nums_to_strings[1] = "ONE"
nums_to_strings["2"] = "TWO"
print(nums_to_strings)<jupyter_output>{1: 'one'}
{1: 'ONE', '2': 'TWO'}<jupyter_text>`dict`: Methods- Dictionaries are considered `object`s, we'll go over `object`s in more detail when we go over Object Oriented Programming (OOP).- For now you need to know that objects can have functions called `methods`, which can be "called" by using the `dict_variable.method_name()` notation.   `dict` Methods: `clear()`- `clear()`removes all items from the dictionary<jupyter_code>nums_to_strings = {1:"one"}
print(nums_to_strings)
nums_to_strings.clear()
print(nums_to_strings)<jupyter_output>{1: 'one'}
{}<jupyter_text>`dict` Methods: `get()`- `get()` works just like using square brackets `[]`<jupyter_code>nums_to_strings = {1:"one", 2:"two"}
print(nums_to_strings.get(1))
print(nums_to_strings[1])<jupyter_output>one
one<jupyter_text>`dict` Methods: `items()`- Returns a "view" of the key:value pairs in the dictionary. - Note these views are dynamic and change as the dictionary changes<jupyter_code>nums_to_strings = {1:"one", 2:"two"}
items = nums_to_strings.items()
print(nums_to_strings, items) 
nums_to_strings[3] = "three"
print(nums_to_strings, items)<jupyter_output>{1: 'one', 2: 'two'} dict_items([(1, 'one'), (2, 'two')])
{1: 'one', 2: 'two', 3: 'three'} dict_items([(1, 'one'), (2, 'two'), (3, 'three')])<jupyter_text>`dict` Methods: `keys()`- Returns a "view" of the keys in the dictionary. - Note these views are dynamic and change as the dictionary changes<jupyter_code>nums_to_strings = {1:"one", 2:"two"}
keys = nums_to_strings.keys()
print(nums_to_strings, keys) 
nums_to_strings[3] = "three"
print(nums_to_strings, keys)<jupyter_output>{1: 'one', 2: 'two'} dict_keys([1, 2])
{1: 'one', 2: 'two', 3: 'three'} dict_keys([1, 2, 3])<jupyter_text>`dict` Methods: `values()`- Returns a "view" of the keys in the dictionary. - Note these views are dynamic and change as the dictionary changes<jupyter_code>nums_to_strings = {1:"one", 2:"two"}
vals = nums_to_strings.values()
print(nums_to_strings, vals) 
nums_to_strings[3] = "three"
print(nums_to_strings, vals)<jupyter_output>{1: 'one', 2: 'two'} dict_values(['one', 'two'])
{1: 'one', 2: 'two', 3: 'three'} dict_values(['one', 'two', 'three'])<jupyter_text>`dict` Methods: `pop()`- Returns the value at the given key while removing the key<jupyter_code>nums_to_strings = {1:"one", 2:"two"}
val_at_1 = nums_to_strings.pop(1)
print(nums_to_strings, val_at_1)<jupyter_output>{2: 'two'} one<jupyter_text>`dict` Methods: `popitem()`- Returns the key/value:    - Last In First Out (LIFO) order. (Python 3.7+)    - Arbitrary order (Python < 3.7)<jupyter_code>nums_to_strings = {1:"one", 2:"two", 3:"three"}
val_at_1 = nums_to_strings.popitem()
print(nums_to_strings)
print(val_at_1)<jupyter_output>{1: 'one', 2: 'two'}
(3, 'three')<jupyter_text>`dict` Methods: `setdefault()`- If the key argument that is passed to the method exists in the dictionary, then it is returned. If it not in the dictionary, then an optional default argument can be used. If no default argument is provided, the it is set to `None`   Quick aside: `None` and `pass`- `None` is a special type in python that is intended to represent the absence information. - It usually means, "Not Anything" or "null"- `pass` is a placeholder statement in Python that doesn't perform any actions but can be used to ensure no syntax errors, i.e:```pythonif [boolean]:    passelse:    pass```  `dict` Methods: `setdefault()`- If the key argument that is passed to the method exists in the dictionary, then it is returned. If it not in the dictionary, then an optional default argument can be used. If no default argument is provided, the it is set to `None`<jupyter_code>nums_to_strings = {1:"one", 2:"two"}

val_at_2 = nums_to_strings.setdefault(2, "three")
print(nums_to_strings, val_at_2)

val_at_3 = nums_to_strings.setdefault(3, "three")
print(nums_to_strings, val_at_3)<jupyter_output>{1: 'one', 2: 'two'} two
{1: 'one', 2: 'two', 3: 'three'} three<jupyter_text>`dict` Methods: `update()`- Merges the dictionary that the method is being called on with the one that is passed as an argument in the method<jupyter_code>nums_to_strings = {1:"one", 2:"two"}
print(nums_to_strings)

nums_to_strings_three = {3:"three"}
nums_to_strings.update(nums_to_strings_three)
print(nums_to_strings)<jupyter_output>{1: 'one', 2: 'two'}
{1: 'one', 2: 'two', 3: 'three'}<jupyter_text>Built-in Functions That are Compatible With `dict`s- `len()` returns the number of items in a `dict`- `list()` returns the keys in the dictionary as a list<jupyter_code>nums_to_strings = {1:"one", 2:"two"}
print(nums_to_strings)
print("There are", len(nums_to_strings), "items in the dictionary")
print("The following keys are in the dictionary:", list(nums_to_strings))<jupyter_output>{1: 'one', 2: 'two'}
There are 2 items in the dictionary
The following keys are in the dictionary: [1, 2]<jupyter_text>Sets- `set`s are an **unordered** collection containing **no** duplicates - They are functionally similar to mathematical sets. We can perform common set operations like:    - membership    - subsets    - supersets    - intersections    - etc ...  `set`: instantiation (creation)- Sets can be created a few ways. Today we'll go over two ways: curly braces `{}` and the type constructor `set()`<jupyter_code>a_set = {1, 2, 5}
another_set = set([1, 2, 5])

print(a_set, another_set)<jupyter_output>{1, 2, 5} {1, 2, 5}<jupyter_text>Common `set` operations: Membership- You can use the membership operators `in` and `not in` to see if a value is a member of the set<jupyter_code>a_set = {1, 2, 5}
val = 2

print(val in a_set)<jupyter_output>True<jupyter_text>Common `set` operations: isdisjoint()- The `isdisjoint()` methods returns `True` if the two sets don't have any elements in common<jupyter_code>a_set = {1, 2, 3}
another_set = {4, 5, 6}

a_set.isdisjoint(another_set)<jupyter_output><empty_output><jupyter_text>Common `set` operations: subset- `issubset()` and `<=` will test if all of the elements in the set on the left side are in the set on the right side.- `<` will test if the set on the left is a proper subset.<jupyter_code>a_set = {1, 2, 3}
another_set = {1, 2, 3}

print(a_set.issubset(another_set))
print(a_set <= another_set)
print(a_set < another_set)<jupyter_output>True
True
False<jupyter_text>Common `set` operations: superset- `issuperset()` and `>=` will test if all of the elements in the set on the right side are in the set on the left side.- `>` will test if the set on the left is a proper superset.<jupyter_code>a_set = {1, 2, 3, 4}
another_set = {1, 2, 3}

print(a_set.issuperset(another_set))
print(a_set >= another_set)
print(a_set > another_set)<jupyter_output>True
True
True<jupyter_text>Common `set` operations: union and intersection- `union()` and `|` will return the union of the set on the left and the set on the right.- `intersection()` and `&` will return the intersection of the set on the left and on the right<jupyter_code>a_set = {1, 2, 3}
another_set = {2, 3, 4}

print(a_set | another_set)
print(a_set & another_set)<jupyter_output>{1, 2, 3, 4}
{2, 3}<jupyter_text>Common `set` operations: difference and symmetric difference - `difference()` and `-` will return a new set with the elements in the set on the left that are not in the set on the right- `symmetric_difference()` and `^` will return a new set containing the elements that both sets don't have in common<jupyter_code>a_set = {1, 2, 3}
another_set = {2, 3, 4}

print(a_set - another_set)
print(a_set ^ another_set)<jupyter_output>{1}
{1, 4}<jupyter_text>`set` Methods: `add()`- `add()` adds the given element to the set<jupyter_code>a_set = {1, 2, 3}
a_set.add("4")
a_set.add(5.0)
a_set.add(2)
print(a_set)<jupyter_output>{1, 2, 3, 5.0, '4'}<jupyter_text>`set` Methods: `remove()` & `discard()`- `remove()` removes the given element from the set and raises an error if the element isn't in the set- `discard()` removes the given element from the set and **doesn't** raise an error if the element isn't in the set<jupyter_code>a_set = {1, 2, 3, 5}
a_set.remove(2)
a_set.discard(4)
print(a_set)<jupyter_output>{1, 3, 5}<jupyter_text>`set` Methods: `pop()` & `clear()`- `pop()` removes and returns an arbitrary element from the set- `clear()` removes all elements from the set<jupyter_code>a_set = {1, 2, 3}
print(a_set.pop())
print(a_set)
a_set.clear()
print(a_set)<jupyter_output>1
{2, 3}
set()<jupyter_text>Built-in Functions That are Compatible With `set`s- `len()` returns the number of items in a `set`<jupyter_code>a_set = {1, 2, 3}
print(a_set)
print("There are", len(a_set), "elements in the set")<jupyter_output>{1, 2, 3}
There are 3 elements in the set
StarcoderdataJupyterStructuredCleanDedup