<jupyter_start><jupyter_text>Dictionary Views I want to come back to dictionaries quickly to explain dictionary views. Dictionaries contain key/value pairs. By default we have seen how when we iterate directly over a dictionary we are in fact iterating over the keys.But what if we want to iterate over the values instead? Or maybe the keys and values at the same time? Dictionaries offer three "views" that are basically generators (remember those?) used to represent:- just the keys- just the values- both the keys and the values as tuples All those views are iterables, so we can do the following:<jupyter_code>d = {
    'a': 10,
    'b': 20,
    'c': 30
}
for k in d.keys():
    print(k)
for v in d.values():
    print(v)
for item in d.items():
    print(item)<jupyter_output>('a', 10)
('b', 20)
('c', 30)<jupyter_text>The first two are straightforward, but the last one returns not single values, but tuples containing the key and the value of each item in the dictionary.So, we can use unpacking to our advantage here!<jupyter_code>for k, v in d.items():
    print('key:', k, '\tvalue:', v)<jupyter_output>key: a 	value: 10
key: b 	value: 20
key: c 	value: 30<jupyter_text>So using the `items()` view and unpacking can make some code that needs to work with both the keys and the values much easier to write. **CAUTION**One big word of caution here.Views are dynamic (i.e. the will reflect changes in the dictionary right away), so **DO NOT** change the dictionary by adding/removing elements as you iterate over any of the views. This will lead to trouble! Just say no :-) Another property about these views is that some of them can behave as sets.The `keys()` view actually behaves like a **set** - which makes sense if we remember that keys in a dictionary have the same characteristics as elements in a set - they cannot be repeated (so they are unique), and they have no particular order.The `values()` view on the other hand, never behaves like a set, while the `items()` view *may* behave like a set. Why, and under what circumstances this is true is beyond the scope of this primer.For the majority of programming needs, we only really need to work with the keys as sets. Why is being able to treat the keys in a dictionary in a set useful? Consider this problem where you have two dictionaries, and you want to find all the elements whose keys are in *both* dictionaries. For example, suppose we have two servers that return data results to us telling us the number of some particualr widgets sold.We are tasked with finding which widgets were sold on one or the other server, but not both.<jupyter_code>server_1 = {
    'yPad': 10,
    'yPhone': 100,
    'yWatch': 30,
    'yPen': 20
}

server_2 = {
    'yPad': 10,
    'yWatch': 20,
    'yBookPro': 5
}<jupyter_output><empty_output><jupyter_text>So we can see that the items that were sold on one server or the other (but not both), are: `yPhone`, `yPen`, and `yBookPro`. This might indicate to us that we have an inventory problem that needs to be fixed. So how can we go about getting this information programmatically? Well, the `keys()` views behave like sets - let's see how we can find widgets that were sold on *both* servers first:<jupyter_code>widgets_1 = server_1.keys()
widgets_2 = server_2.keys()

# intersection of the sets
widgets_1 & widgets_2<jupyter_output><empty_output><jupyter_text>Now we really need to find the other widgets - we could do it this way using a union and subtgracting the intersection:<jupyter_code>widgets_1 | widgets_2<jupyter_output><empty_output><jupyter_text>As you can see this is the union (and no repeated elements of course), and now we remove the intersection:<jupyter_code>(widgets_1 | widgets_2) - (widgets_1 & widgets_2)<jupyter_output><empty_output><jupyter_text>And there you are!But there is a simpler way yet - remember the **symmetric difference** of two sets?Yep, we can use that here:<jupyter_code>widgets_1 ^ widgets_2<jupyter_output><empty_output><jupyter_text>Or, without using intermediary symbols, directly from the dictionaries thus:<jupyter_code>server_1.keys() ^ server_2.keys()<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup