<jupyter_start><jupyter_text>All the IPython Notebooks in **Python Datatypes** lecture series by **[Dr. <NAME>](https://www.linkedin.com/in/milaanparmar/)** are available @ **[GitHub](https://github.com/milaan9/02_Python_Datatypes)**  Python DictionaryIn this class, you'll learn everything about Python dictionaries; how they are created, accessing, adding, removing elements from them and various built-in methods.  What is Dictionary in Python?Python dictionary is an unordered collection of items. Each item of a dictionary has a **`key/value`** pair. Dictionaries are optimized to retrieve values when the key is known.**Example:**```python>>> dict = { }  empty dictionary>>> dict = {1:'Python',2:'Java',3:'C++'}```* **Dictionary is mutable** i.e., value can be updated.* Key must be unique and immutable. Value is accessed by key. Value can be updated while key cannot be changed. * Dictionary is known as Associative array since the Key works as Index and they are decided by the user.  Summary| Data types     | Type          |         || :------------: | :-----------: |:------: || **String**     | **immutable** |  || **List**       | **mutable**   |✎|| **Tuple**      | **immutable** |  || **Dictionary** | **mutable**   |✎|  Creating Python DictionaryCreating a dictionary is as simple as placing items inside curly braces **`{}`** separated by commas or the **[dict()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/015_Python_dict%28%29.ipynb)** built-in function.An item has a **`key`** and a corresponding **`value`** that is expressed as a pair {**key: value**}.The **`key`** and the **`value`** is separated by a colon **`:`**. Items are separated from each other by a comma **`,`**.While the values can be of any data type and can repeat, keys must be of immutable type (**[string](https://github.com/milaan9/02_Python_Datatypes/blob/main/002_Python_String.ipynb)**, **[number](https://github.com/milaan9/02_Python_Datatypes/blob/main/001_Python_Numbers.ipynb)** or **[tuple](https://github.com/milaan9/02_Python_Datatypes/blob/main/004_Python_Tuple.ipynb)** with immutable elements) and must be unique.<jupyter_code># Example: empty dictionary

d = {}; l = []; t = (); s = set(); st = ""
print(d,l,t,s,st)     # ▶ {} [] () set() 
print(type(d),type(l),type(t), type(s), type(st)) 
# ▶ <class 'dict'> <class 'list'> <class 'tuple'> <class 'set'> <class 'str'>

# dictionary with integer keys
my_dict1 = {1: 'apple', 2: 'ball'}
print(my_dict1)        # ▶ {1: 'apple', 2: 'ball'}

# dictionary with mixed keys
my_dict2 = {1:"hi", "name":666, 1.5:("yes","very much"), 9: [3, 6, 9]}
print(my_dict2)        # ▶ {1: 'hi', 'name': 666, 1.5: ('yes', 'very much'), 9: [3, 6, 9]}

# from sequence having each item as a pair
my_dict3 = dict([(1,'apple'), (2,'ball')])
print(type([(1,'apple'), (2,'ball')])) # nested list
print(my_dict3)        # ▶ {1: 'apple', 2: 'ball'}
print(len(my_dict3))   # ▶ 2
dict([(1, 100), ('bar', 200)]), dict(foo=100, bar=200)<jupyter_output><empty_output><jupyter_text>As you can see from above, we can also create a dictionary using the built-in **`dict()`** function.  Accessing Elements from DictionaryWhile indexing is used with other data types to access values, a dictionary uses **`keys`**. Keys can be used either inside square brackets **`[]`** or with the **`get()`** method.If we use the square brackets **`[]`**, **`KeyError`** is raised in case a key is not found in the dictionary. On the other hand, the **`get()`** method returns **`None`** if the key is not found.<jupyter_code># Example: get vs [] for retrieving elements

my_dict = {1:'Python', 2:'Java', 3:'C++', 'c': 'Gods language'}

# method: 1
print(my_dict[1])         # ▶ Python

# method: 2
print(my_dict.get('c'))   # ▶ Gods language

# Trying to access keys which doesn't exist in dictionary:
print(my_dict.get(4))     # ▶ None

print(my_dict[4])         # ▶ KeyError!<jupyter_output>Python
Gods language
None<jupyter_text>* iterate all elemnet using for loop for **`keys()`** method, **`keys()`** method return list of all keys in dictionary.<jupyter_code># Example:

dict = {1:'Python', 2:'Java', 3:'C++', 'c': 'Gods language'}
print(dict.keys())
for x in dict.keys():
    print(dict[x])<jupyter_output>dict_keys([1, 2, 3, 'c'])
Python
Java
C++
Gods language<jupyter_text>Changing and Adding Dictionary elementsDictionaries are mutable. We can add new items or change the value of existing items using an assignment operator.If the key is already present, then the existing value gets updated. In case the key is not present, a new **`(key: value)`** pair is added to the dictionary.<jupyter_code># Example 1: Changing and adding Dictionary Elements

my_dict = {'name':'Arthur', 'age':24}

my_dict['age'] = 25   # update value
print(my_dict)        # ▶ {'age': 25, 'name': 'Arthur'}

my_dict['address'] = 'Downtown'  # add item
print(my_dict)        # ▶ {'name': 'Arthur', 'age': 25, 'address': 'Downtown'}
# Example 2: 

my_dict = {1:'Python', 2:'Java', 3:'C++'}
my_dict[3]="R"     # update value
my_dict[4]="PHP"   # insert new value
print(my_dict)     # ▶ {1: 'Python', 2: 'Java', 3: 'R', 4: 'PHP'}<jupyter_output>{1: 'Python', 2: 'Java', 3: 'R', 4: 'PHP'}<jupyter_text>Removing elements from DictionaryWe can remove a particular item in a dictionary by using the **`pop()`** method. This method removes an item with the provided **`key`** and returns the **`value`**.The **`popitem()`** method can be used to remove and return an arbitrary **`(key, value)`** item pair from the dictionary. All the items can be removed at once, using the **`clear()`** method.We can also use the **`del`** keyword to remove individual items or the entire dictionary itself.<jupyter_code># Example: Removing elements from a dictionary


squares = {1:1, 2:4, 3:9, 4:16, 5:25}   # create a dictionary

# remove a particular item, returns its value
print(squares.pop(4))    # ▶ 16
print(squares)           # ▶ {1: 1, 2: 4, 3: 9, 5: 25}

# remove an arbitrary item, return (key,value)
print(squares.popitem()) # ▶ (5, 25)
print(squares)           # ▶ {1: 1, 2: 4, 3: 9}

squares.clear()          # remove all items
print(squares)           # ▶ {}

del squares              # delete the dictionary itself
print(squares)           # ▶ NameError!!!
# Example:

my_dict = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
del my_dict[3]    # ▶ {1: 'Python', 2: 'Java', 4: 'PHP'} ∵ remove entry with key '3'
print(my_dict)    # ▶ {}

my_dict.clear()   # remove all entries in dict
print("my_dict : ",my_dict)  # ▶ my_dict :  {}

del my_dict       # delete entire dictionary
print(my_dict[2]) # ▶ NameError!!!<jupyter_output>{1: 'Python', 2: 'Java', 4: 'PHP'}
my_dict :  {}<jupyter_text>Dictionary Built-in Dictionary FunctionsBuilt-in functions like **`all()`**, **`any()`**, **`len()`**, **`cmp()`**, **`sorted()`**, **`str()`**, **`typ()`**, etc. are commonly used with dictionaries to perform different tasks. | Function | Description ||:----| :--- || **[all()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/003_Python_all%28%29.ipynb)** | Returns **`True`** if all keys of the dictionary are true (or if the dictionary is empty). | | **[any()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/002_Python_any%28%29.ipynb)** | Returns **`True`** if any key of the dictionary is true. If the dictionary is empty, return **`False`**. | | **[len()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/040_Python_len%28%29.ipynb)** | Returns the length (the number of items) in the dictionary. | | **cmp()** | Compares items of two dictionaries. (Not available in Python 3). | | **[sorted()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/060_Python_sorted%28%29.ipynb)** | Returns a new sorted list of keys in the dictionary. | | **[str()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/061_Python_str%28%29.ipynb)** | Produces a printable string representation of a dictionary. | | **[type()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/064_Python_type%28%29.ipynb)** | Returns the type of the passed variable. If passed variable is dictionary,then it would return a dictionary type. |  Here are some examples that use built-in functions to work with a dictionary.<jupyter_code># Example: Dictionary Built-in Functions

# all will give True if all "Key" is "True". 0 is also consider as False 

squares = {0:0, 1:1, 3:9, 5:25, 7:49, 9:81}

print(all(squares))     # ▶ False
print(any(squares))     # ▶ True
print(len(squares))     # ▶ 6
print(sorted(squares))  # ▶ [0, 1, 3, 5, 7, 9]<jupyter_output>False
True
6
[0, 1, 3, 5, 7, 9]<jupyter_text>`all(dict)` - The `all()` function returns True when all elements in the given iterable are true. If not, it returns False.In case of dictionaries, if all keys (not values) are true or the dictionary is empty, **`all()`** returns **`True`**. Else, it returns **`false`** for all other cases.<jupyter_code># Example 1: How all() works with Python dictionaries?
# In case of dictionaries, if all keys (not values) are true or the dictionary is empty, 
# all() returns True. Else, it returns false for all other cases.

my_dict = {0:'False', 1:'False'}
print(all(my_dict))   # ▶ False

my_dict = {1:'True', 2:'True'}
print(all(my_dict))   # ▶ True

my_dict = {1:'True', False:0}
print(all(my_dict))   # ▶ False

my_dict = {}
print(all(my_dict))   # ▶ True

# 0 is False
# '0' is True
my_dict = {'0':'True'}
print(all(my_dict))   # ▶ True<jupyter_output>False
True
False
True
True<jupyter_text>`any(dict)` - The `any()` function returns True if any element of an iterable is True. If not, any() returns False.In the case of dictionaries, if all keys (not values) are false or the dictionary is empty, **`any()`** returns **`False`**. If at least one key is true, **`any()`** returns **`True`**.<jupyter_code># Example 1: How any() works with Python dictionaries?

my_dict = {0:'False'}             
print(any(my_dict))                # ▶ False ∵ 0 is False

my_dict = {0:'False', 1:'True'}  
print(any(my_dict))                # ▶ True ∵ 1 is True

my_dict = {0:'False', False:0}   
print(any(my_dict))                # ▶ False ∵ both 0 and False are False

my_dict = {}                       
print(any(my_dict))                # ▶ False ∵ iterable is empty

# 0 is False
# '0' is True
my_dict = {'0':'False'}           
print(any(my_dict))                # ▶ True<jupyter_output>False
True
False
False
True<jupyter_text>**`len(dict)`** - The `len()` function gives the total length of the dictionary. This would be equal to the number of items in the dictionary.<jupyter_code># Example:

my_dict = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
print(len(my_dict))  # ▶ 4<jupyter_output>4<jupyter_text>**`sorted(dict)`** - The `sorted()` function sorts the elements of a given iterable in a specific order (either **ascending** or **descending**) and returns the sorted iterable as a list.<jupyter_code># Example:

my_dict = {'e':1, 'a':2, 'u':3, 'o':4, 'i':5}
print(sorted(my_dict))               # ▶ ['a', 'e', 'i', 'o', 'u']
print(sorted(my_dict, reverse=True)) # ▶ ['u', 'o', 'i', 'e', 'a']<jupyter_output>['a', 'e', 'i', 'o', 'u']
['u', 'o', 'i', 'e', 'a']<jupyter_text>**`str(dict)`** - The `str()` function produces a printable string representation of a dictionary.<jupyter_code># Example:

my_dict = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
print(str(my_dict)) # ▶ {1: 'Python', 2: 'Java', 3: 'C++', 4: 'PHP'}<jupyter_output>{1: 'Python', 2: 'Java', 3: 'C++', 4: 'PHP'}<jupyter_text>**`type()`** - The `type()` function returns the type of the passed variable. If passed variable is dictionary then it would return a dictionary type.<jupyter_code># Example:

my_dict = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
print(type(my_dict))  # ▶ <class 'dict'><jupyter_output><class 'dict'><jupyter_text>Python Dictionary MethodsMethods that are available with a dictionary are tabulated below. Some of them have already been used in the above examples.| Method | Description ||:----| :--- || **[clear()](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/001_Python_Dictionary_clear%28%29.ipynb)** | Removes all items from the dictionary. | | **[copy()](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/002_Python_Dictionary_copy%28%29.ipynb)** | Returns a shallow copy of the dictionary. | | **[fromkeys(seq[, v])](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/003_Python_Dictionary_fromkeys%28%29.ipynb)** | Returns a new dictionary with keys from **`seq`** and value equal to **`v`** (defaults to **`None`**). | | **[get(key[,d])](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/004_Python_Dictionary_get%28%29.ipynb)** | Returns the value of the **`key`**. If the **`key`** does not exist, returns **`d`** (defaults to **`None`**). | | **[items()](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/005_Python_Dictionary_items%28%29.ipynb)** | Return a new object of the dictionary's items in **`(key, value)`** format. | | **[keys()](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/006_Python_Dictionary_keys%28%29.ipynb)** | Returns a new object of the dictionary's keys. | | **[pop(key[,d])](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/007_Python_Dictionary_pop%28%29.ipynb)** | Removes the item with the **`key`** and returns its value or **`d`** if **`key`** is not found. If **`d`** is not provided and the **`key`** is not found, it raises **`KeyError`**. | | **[popitem()](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/008_Python_Dictionary_popitem%28%29.ipynb)** | Removes and returns an arbitrary item **`(key, value)`**. Raises **`KeyError`** if the dictionary is empty. | | **[setdefault(key[,d])](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/009_Python_Dictionary_setdefault%28%29.ipynb)** | Returns the corresponding value if the **`key`** is in the dictionary. If not, inserts the **`key`** with a value of **`d`** and returns **`d`** (defaults to **`None`**). | | **[update([other])](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/010_Python_Dictionary_update%28%29.ipynb)** | Updates the dictionary with the key/value pairs from **`other`**, overwriting existing keys. |  | **[values()](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/011_Python_Dictionary_values%28%29.ipynb)** | Returns a new object of the dictionary's values. |  Here are a few example use cases of these methods.<jupyter_code># Example: Dictionary Methods

marks = {}.fromkeys(['Math', 'English', 'Science'], 0)
print(marks)                        # ▶ {'English': 0, 'Math': 0, 'Science': 0}

for item in marks.items():
    print(item)

print(list(sorted(marks.keys())))   # ▶ ['English', 'Math', 'Science']<jupyter_output>{'Math': 0, 'English': 0, 'Science': 0}
('Math', 0)
('English', 0)
('Science', 0)
['English', 'Math', 'Science']<jupyter_text>**`clear()`** - The method `clear()` removes all items from the dictionary.<jupyter_code># Example:

my_dict = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}

print(str(my_dict))  # ▶ {1: 'Python', 2: 'Java', 3: 'C++', 4: 'PHP'}
dict.clear()
print(str(my_dict))  # ▶ {}<jupyter_output>{1: 'Python', 2: 'Java', 3: 'C++', 4: 'PHP'}
{1: 'Python', 2: 'Java', 3: 'C++', 4: 'PHP'}<jupyter_text>**`copy()`** - The method `copy()` returns a shallow copy of the dictionary.<jupyter_code># Example:

dict1 = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
dict2 = dict1.copy()
print(dict2)  # ▶ {1: 'Python', 2: 'Java', 3: 'C++', 4: 'PHP'}<jupyter_output>{1: 'Python', 2: 'Java', 3: 'C++', 4: 'PHP'}<jupyter_text>**`itmes()`** - The method `items()` returns a list of dict's (key, value) tuple pairs.<jupyter_code># Example:

my_dict = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
print(my_dict.items()) # ▶ dict_items([(1, 'Python'), (2, 'Java'), (3, 'C++'), (4, 'PHP')])<jupyter_output>dict_items([(1, 'Python'), (2, 'Java'), (3, 'C++'), (4, 'PHP')])<jupyter_text>**`keys()`** - The method `keys()` returns a list of all the available keys in the dictionary.<jupyter_code># Example:

my_dict = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
all_keys=my_dict.keys()
print(all_keys)  # ▶ dict_keys([1, 2, 3, 4])<jupyter_output>dict_keys([1, 2, 3, 4])<jupyter_text>**`fromkeys()`** - The method `fromkeys()` creates a new dictionary with keys from seq and values set to value.**Syntax:**```python dict.fromkeys(seq[, value])```<jupyter_code># Example:

seq = ('Python', 'Java', 'C++')
my_dict = my_dict.fromkeys(seq)

print ("new_dict : %s" % str(my_dict)) # ▶ new_dict : {'python': None, 'java': None, 'c++': None}
my_dict = my_dict.fromkeys(seq, 50)
print ("new_dict : %s" % str(my_dict)) # ▶ new_dict : {'python': 50, 'java': 50, 'c++': 50}<jupyter_output>new_dict : {'Python': None, 'Java': None, 'C++': None}
new_dict : {'Python': 50, 'Java': 50, 'C++': 50}<jupyter_text>**`setdefault()`** - The method `setdefault()` is similar to `get` but will set `dict[key] = default` if key is not already in dict.**Syntax:**```pythondict.setdefault(key, default = None)```* key −> This is the key to be searched. * default −> This is the Value to be returned in case key is not found.<jupyter_code># Example:

my_dict={'emp_name':'Milaan', 'age':96, 'emp_id':999}
my_dict.setdefault('company','JLUFE')
print(my_dict['emp_name'])   # ▶ Milaan
print(my_dict['company'])    # ▶ JLUFE<jupyter_output>Milaan
JLUFE<jupyter_text>**`update()`** - The method `update()` adds dictionary dict2's key-values pairs in to dict. This function does not return anything.**Syntax:**```pythondict.update(dict2)```<jupyter_code># Example:

dict1 = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
dict2 = {1: 'Python3',5:'C'}  # update Python to Python3
dict1.update(dict2)
print(dict1)   # ▶ {1: 'Python3', 2: 'Java', 3: 'C++', 4: 'PHP', 5: 'C'}<jupyter_output>{1: 'Python3', 2: 'Java', 3: 'C++', 4: 'PHP', 5: 'C'}<jupyter_text>**`value()`** - The method `values()` returns a list of all the values available in a given dictionary.<jupyter_code># Example:

dict1 = {1:'Python', 2:'Java', 3:'C++', 4:'PHP'}
values= dict1.values()
print(values)  # ▶ dict_values(['Python', 'Java', 'C++', 'PHP'])<jupyter_output>dict_values(['Python', 'Java', 'C++', 'PHP'])<jupyter_text>Here is a complete list of all the **[built-in methods to work with Dictionary in Python](https://github.com/milaan9/02_Python_Datatypes/tree/main/005_Python_Dictionary_Methods)**.  Python Dictionary ComprehensionDictionary comprehension is an elegant and concise way to create a new dictionary from an iterable in Python.Dictionary comprehension consists of an expression pair **`(key: value)`** followed by a **`for`** statement inside curly braces **`{}`**.Here is an example to make a dictionary with each item being a pair of a number and its square.<jupyter_code># Example: Dictionary Comprehension

squares = {x: x*x for x in range(6)}
print(squares)  # ▶ {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}<jupyter_output>{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}<jupyter_text>This code is equivalent to<jupyter_code># Example:

squares = {}
for x in range(6):
    squares[x] = x*x
print(squares)  # ▶ {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}<jupyter_output>{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}<jupyter_text>A dictionary comprehension can optionally contain more **[for](https://github.com/milaan9/03_Python_Flow_Control/blob/main/005_Python_for_Loop.ipynb)** or **[if](https://github.com/milaan9/03_Python_Flow_Control/blob/main/001_Python_if_statement.ipynb)** statements.An optional **`if`** statement can filter out items to form the new dictionary.Here are some examples to make a dictionary with only odd items.<jupyter_code># Example: Dictionary Comprehension with if conditional

odd_squares = {x: x*x for x in range(11) if x % 2 == 1}
print(odd_squares)  # ▶ {1: 1, 3: 9, 5: 25, 7: 49, 9: 81}<jupyter_output>{1: 1, 3: 9, 5: 25, 7: 49, 9: 81}<jupyter_text>To learn more dictionary comprehensions, visit **[Python Dictionary Comprehension](https://github.com/milaan9/02_Python_Datatypes/blob/main/005_Python_Dictionary_Methods/Python_Dictionary_Comprehension.ipynb)**.  Other Dictionary Operations  1. Dictionary Membership TestWe can test if a **`key`** is in a dictionary or not using the keyword **`in`**. Notice that the membership test is only for the **`keys`** and not for the **`values`**.<jupyter_code># Example: Membership Test for Dictionary Keys

squares = {1: 1, 3: 9, 5: 25, 7: 99, 9: 61}

print(1 in squares)      # ▶ True

print(2 not in squares)  # ▶ True

# membership tests for key only not value
print(99 in squares)     # ▶ False<jupyter_output>True
True
False<jupyter_text>2. Iterating Through a DictionaryWe can iterate through each key in a dictionary using a **`for`** loop.<jupyter_code># Example: Iterating through a Dictionary

squares = {1: 1, 3: 9, 5: 25, 7: 49, 9: 81}
for i in squares:
    print(squares[i])<jupyter_output>1
9
25
49
81
{'fraction_non_alphanumeric': 0.1816052101391557, 'fraction_numerical': 0.03476549688422433, 'mean_word_length': 5.060193072118115, 'pattern_counts': {'":': 1, '<': 88, '<?xml version=': 0, '>': 96, 'https://': 27, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '26', 'dir': 'jupyter-structured-clean-dedup', 'id': '382561', 'license': 'MIT', 'n_tokens_mistral': 8151, 'n_tokens_neox': 7367, 'n_words': 2288, 'path': '005_Python_Dictionary.ipynb', 'repo_name': 'Maxc390/python-discrete-structures', 'size': '21350'}