Python Tutorial Episode 2

This tutorial is following book "Smarter Way to learn Python"
chapters 20 until 40

Sheet Written by Ahsan Farooqui, www.blog.ahsanfarooqui.xyz

Download editable notebook from Here

Chapter 20 - Tuples

  • Tuples are like lists but they cannot be changed.
  • In lists, we were adding/deleting items, in tuples it is not possible to do so.
  • This is good in a way for those lists that you dont want to be changed.
Syntax
  • The Tuples are bounded by parenthesis at the time of definition.
    tuple_name = ("some element","some element too","some element three")
In [2]:
#Tuple Example:
# We know provinces of Pakistan will not change for a while, so we can define a tuple and reference it. 
provinces_of_pakistan = ("Baluchistan","Gilgit Baltistan","Punjab","Sindh","KPK")
print(provinces_of_pakistan)
('Baluchistan', 'Gilgit Baltistan', 'Punjab', 'Sindh', 'KPK')
In [3]:
# You can access the individual elements of tuple in same way as you were doing for the list. 
#Let's print each element individually.

print(provinces_of_pakistan[0])
print(provinces_of_pakistan[1])
print(provinces_of_pakistan[2])
print(provinces_of_pakistan[3])
print(provinces_of_pakistan[4])

# You can also check type of a variable in same way:
type(provinces_of_pakistan)
Baluchistan
Gilgit Baltistan
Punjab
Sindh
KPK
Out[3]:
tuple
In [4]:
# now, if I want to replace a value or assign a new value, it will give error. lets try doing it:
provinces_of_pakistan[0] = "Islamabad"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-35038b8f4e54> in <module>
      1 # now, if I want to replace a value or assign a new value, it will give error. lets try doing it:
----> 2 provinces_of_pakistan[0] = "Islamabad"

TypeError: 'tuple' object does not support item assignment

Chapter 21 - For Loops

  • suppose we have a program, that requires you to perform a same action many times.
  • For example, lets say we have to print "Hello World" 10 times.
    • Easiest way would be to write 10 print statements
    • But that is a very manual and quite fatigue to write same statement 10 times
  • Or lets say, in above example, we used a tuple. What if we want to print all the names in tuple without using multiple print statements?
  • to do the repetitive work, we use loops.
  • Loops are used differently in different functions. You can loop through a list, a tuple and even loop between two numbers
  • We shall now see examples of For Loops
Syntax:
  • In simple number iterations, we use range function. range function returns consecutive numbers between two end points. its syntax is range(0,10). Note that if you put one number in range i.e. range(10), it will automatically assume that the starting point is 0.

  • Note that the if you set range (0,10), it will go from 0 until 9, running exactly 10 times.

  • syntax for for loop is as follows:

      for any_variable in range(0,10):
          whatever you want to print is indented inside for loop block.
      This will not be a part of for loop
In [6]:
#Print Hello World 10 times
for i in range(0,10): 
    print("Hello World")
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
In [7]:
#Now Lets try to print the range value in each loop
for i in range(0,10): 
    print(f"This is the {i} iteration of loop") 
This is the 0 iteration of loop
This is the 1 iteration of loop
This is the 2 iteration of loop
This is the 3 iteration of loop
This is the 4 iteration of loop
This is the 5 iteration of loop
This is the 6 iteration of loop
This is the 7 iteration of loop
This is the 8 iteration of loop
This is the 9 iteration of loop
In [8]:
#Let's try to add an if condition and seggregate the even and odd numbers of i.
for i in range(0,10): 
    if(i%2==0): # we have used remainder operator and equated it equal to 0 to check if the number is fully divisible by 2 or not. 
        print(f"The {i} is even") 
    else:
        print(f"The {i} is odd")
The 0 is even
The 1 is odd
The 2 is even
The 3 is odd
The 4 is even
The 5 is odd
The 6 is even
The 7 is odd
The 8 is even
The 9 is odd
In [9]:
# Similarly, lets try to print a list with for loop

fruits = ["Apple","Orange","Guava","Pear","Grapes","Mango","Watermelon"]
for i in fruits:   # Here, instead of range, we have given directly the name of list. Now i, in each iteration, will be the entry of the list. 
    print(i)       #Simply printing i will give us the list elements one by one. 
Apple
Orange
Guava
Pear
Grapes
Mango
Watermelon
In [10]:
# to find length of any string, we can use len(). 
# Now, lets try to find and print length of all entries in our fruits list
fruits = ["Apple","Orange","Guava","Pear","Grapes","Mango","Watermelon"]
for i in fruits:
    print(f"The length of {i} is {len(i)}")
The length of Apple is 5
The length of Orange is 6
The length of Guava is 5
The length of Pear is 4
The length of Grapes is 6
The length of Mango is 5
The length of Watermelon is 10
In [11]:
# Another example: lets try to add 10 numbers in a list using for loop
my_list = []             #We define an empty list for future use.
for i in range(1,11):    #Notice, I started from 1 and went until 11 so that loop goes from 1 to 10. 
    my_list.append(i)    #We saw in past the append function. It appends the value of i in my_list.

print(my_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [12]:
#Example:
#Lets say we have a list with some garbage values in them. 
#We know that garbage values have a length of 3 characters or lower and our required data has minimum 4 characters in it. 
# Using For loop, we can easily differentiate between actual data and garbage values
list1 = ["Table","Chair","???","$$","Tyre","^^","Pillow"]
filtered_list = []
for i in list1:
    if(len(i)>3):
        filtered_list.append(i)
print("original list was ",list1)
print("filtered list is ",filtered_list)
original list was  ['Table', 'Chair', '???', '$$', 'Tyre', '^^', 'Pillow']
filtered list is  ['Table', 'Chair', 'Tyre', 'Pillow']

Break

  • Let's take an example of a list
    • my_list = [1,4,3,5,4,5,6,1,4,6,5,3,5,6,7,4,3,1,4,4,5,1,0]
  • my_list has different numbers as elements.
  • Now, if we wish to find out if there is any 4 in the list, we will run loop, then check if every element is a 4 or not and even if we find 4 in our second element, we would still find a 4 throughout the list which is not necessary
  • For that we can use the break keyword. break keyword, as the name suggests, breaks out of the loop if a condition is met.
  • We'll see it in the example below
  • First we execute the code without the break command.
In [13]:
my_list = [1,4,3,5,4,5,6,1,4,6,5,3,5,6,7,4,3,1,4,4,5,1,0]
for i in my_list:
    if(i==4):
        print("found a 4")
    else:
        print(f"{i} is not a 4")
1 is not a 4
found a 4
3 is not a 4
5 is not a 4
found a 4
5 is not a 4
6 is not a 4
1 is not a 4
found a 4
6 is not a 4
5 is not a 4
3 is not a 4
5 is not a 4
6 is not a 4
7 is not a 4
found a 4
3 is not a 4
1 is not a 4
found a 4
found a 4
5 is not a 4
1 is not a 4
0 is not a 4
  • As you saw, it ran for the complete list.
  • Lets now find 4 in the list and break wherever we find a 4
In [14]:
my_list = [1,4,3,5,4,5,6,1,4,6,5,3,5,6,7,4,3,1,4,4,5,1,0]
for i in my_list:
    if(i==4):
        print("found a 4")
        break
    print(f"{i} is not a 4")
1 is not a 4
found a 4
So it broke out of the loop on 2nd element and didnt go further. That's the benefit of break.

Chapter 22 - Nested For Loops

Suppose we have two lists. First has the name of all students and second has the name of all subjects that these students want to learn.
Now, I want to generate all possible combinations of students-subjects, how can I do it?

For that, we have nested for loops.

  • As name suggests, Nested loop means one loop inside the other loop. This means when the outer loop runs once, the inner loop runs for the whole range and then outer loop runs again.
  • Total time for run will depend on both loops
  • We'll take some examples to see how these work
  • In first example, lets generate the student-subject combinations for two lists students and subjects:
In [15]:
# Example 1:
students = ["Ali","Asim","Sara","Hira"]
subjects = ["English","Math","Physics","Chemistry"]

#We take one loop for students and other for subjects
for student in students:
    for subject in subjects:
        print(student+"-"+subject) # Notice how print statement is written inside the inner for loop

        
#Explanations on why is it running so? 
#Lets go to line 6 and see when the for loop runs for the first time, student gets value of Ali i.e. 
#first element of students list. 
# now in line 7, another loop starts and subject gets value English. 
# so the value that gets printed is Ali-English
# Now, the loop goes back to line 7 as the subjects list is not finished and subject now gets the value Math. 
#Note that student still has value Ali since inner loop is not ended yet.
# Value printed now is Ali-Math
# In the same way the values are printed until Ali-Chemistry, after which the loop exits and goes to parent loop which now gets a new value for student and loop starts again.
Ali-English
Ali-Math
Ali-Physics
Ali-Chemistry
Asim-English
Asim-Math
Asim-Physics
Asim-Chemistry
Sara-English
Sara-Math
Sara-Physics
Sara-Chemistry
Hira-English
Hira-Math
Hira-Physics
Hira-Chemistry

Challenge Question for Nested for loops.

Brute Force Attack

  • In a brute force attack basically uses all possible combinations or phrases and hopes that at least one would work.
  • Lets say we have a 3 digit password and we want to see if we can break the password through nested for loops.
  • we will use random library to generate password. We haven't studied libraries yet but let's just say they are some python codes that other people have written and packaged so that we can use them without writing the code ourselves. We use import keyword to import a library and then use library functions.
In [16]:
#Step 1: generating password
#Password has format of 42_92_52 i.e. 3 random numbers concatenated with an underscore.

import random  #This command imports random library 
#Here, we are generating a random number using randint function 
#and giving it the range in which we need a number to be generated
#Note that the password will change everytime you run this cell. So make sure you run it everytime you want a new password.
code1 = str(random.randint(10,99))  
code2 = str(random.randint(10,99))
code3 = str(random.randint(10,99))
#Now Combining Password 
password = code1+"_"+code2+"_"+code3
In [17]:
#Here we have three loops nested within each other. 
for cd1 in range(10,99):
    for cd2 in range(10,99):
        for cd3 in range(10,99):
            i = str(cd1)+"_"+str(cd2)+"_"+str(cd3) #in the innermost loop, we have the string that matches format of password (lets say someone told us the format ;-))
            if(i==password): #If we get the password right? 
                print(f"Password decoded!. the password is {i}")
                break # this break statement helps us break out of the code as soon as we get the password and not continue further.
Password decoded!. the password is 69_26_21

Chapter 23 - Getting Information from Users and converting strings and numbers

To get any data from user, we use input() function.

Any data, that is taken through input is stored as a string

The numeric data is then required to be changed into a number explicitly.

Syntax:

  • The syntax is as follows:
      variable_name = input("Prompt that is to be shown to user:")
  • Input function always returns a string.
  • The variable name is where you store the input that is given by user.
  • whatever you wish to prompt goes inside the input parenthesis.
  • We take an example and get input from user. First his name and then his age. Then check the type of both variables.
In [18]:
name = input("Enter your name : ")
age = input("Enter your age: ")
Enter your name : Ahsan
Enter your age: 21
In [23]:
#you can use input() function directly in an if statement
#Note, you cannot save the marks, hence only one if statement is possible.
if(int(input("Enter your marks: "))>50):
    print("Pass")
else:
    print("Fail")
Enter your marks: 70
Pass
In [19]:
#checking the types:
print(type(name))
print(type(age))
<class 'str'>
<class 'str'>
In [22]:
#As you can see both inputs are strings even though age is a numberic number. 
#So we explicitly convert age into integer values now. 
name = input("Enter your name : ")
age = int(input("Enter your age: "))
Enter your name : Ahsan
Enter your age: 30
In [24]:
print(type(name))
print(type(age))
<class 'str'>
<class 'int'>

Type Casting

  • Converting one data type into another is called type casting
  • Type casting is used frequently to convert from string to integer or floating point values etc.

Syntax:

  • The syntax is normally like follows:
      data_type_to_be_converted_to(variable_name or input function)
  • for example, if I want to convert the variable age into integer, I'll use:
      int(age)
  • similarly, If I want to convert the temperature variable, which is a string, to floating point, I'll use as follows:
      float(temperature)
In [25]:
#Example:
age = "21"
temperature = "31.5"

print("Before converting, type of age is: ",type(age))
print("Before converting, type of temperature is: ",type(temperature))
print("After converting to int, type of age is: ",type(int(age)))
print("After converting to float, type of temperature is: ",type(float(temperature)))
Before converting, type of age is:  <class 'str'>
Before converting, type of temperature is:  <class 'str'>
After converting to int, type of age is:  <class 'int'>
After converting to float, type of temperature is:  <class 'float'>

Chapter 24 - Changing Case

Often, you need to change case of a string i.e. convert complete string to upper case, or lower case or title, i.e. only the first character in upper case.
We can use inbuilt functions of .lower(), .upper() and .title() with strings to convert them to respective cases. Title case converts strings like "HELLO" to "Hello".

Why do we need it???

  • One reason is string matching. When you take input from user, you cannot bound them to use lower or upper texts and they will use every kind of texts. So if you are matching string, you will face issues if you dont convert their cases.

Syntax:

  • Suppose you have an input string name.
  • To convert name into lower,upper or title cases, you do it like following:
      name = name.lower()
      name = name.upper()
      name = name.title()
In [26]:
name = "AhSaN FaRoOqUi"

print("Title: ",name.title())
print("Lower case: ",name.lower())
print("Upper case: ",name.upper())
Title:  Ahsan Farooqui
Lower case:  ahsan farooqui
Upper case:  AHSAN FAROOQUI
In [27]:
#Example:
# Lets define a list of fruits and everytime a user enters a fruit name, it checks whether the fruit name is available or not in the list.

fruits = ["Orange","Mango","Peach","Guava","Watermelon"]

for i in range(10): #Asking user 10 times
    user_input = input("Enter a fruit name: ")
    user_input = user_input.title()
    if(user_input in fruits):
        print("You guessed the fruit correctly.")
    else:
        print("Sorry!")
Enter a fruit name: Mango
You guessed the fruit correctly.
Enter a fruit name: Water Melon
Sorry!
Enter a fruit name: Guava
You guessed the fruit correctly.
Enter a fruit name: peach
You guessed the fruit correctly.
Enter a fruit name: orange
You guessed the fruit correctly.
Enter a fruit name: apple
Sorry!
Enter a fruit name: Man go
Sorry!
Enter a fruit name: O r a n g e
Sorry!
Enter a fruit name: p e a c h
Sorry!
Enter a fruit name: jackfruit
Sorry!

Bonus: What if the user enters water melon instead of watermelon?

Replace function

  • Clearly, our system will not capture the extra space with the implemenetation above.
  • But, if we somehow remove the spaces from the input, we may be able to get the output correctly.
  • To replace anything in a string, we use .replace() function ### Syntax:
  • To use a replace function, we use it as follows:
      string_name = string_name.replace("character/string to be replaced","character/string to be replaced with")
  • for example if I have a string "opponent" saved as my_string and I wish to insert a % sign anywhere I find an "o" in the string, I can do it like follows:
      my_string = my_string.replace("o","%")
In [31]:
# Example:
#Take a string from user and if the user string has any of the following words, replace them by aesteriks 
#Words: assignment,quiz,exam

user_input = input("enter a string: ")
user_input = user_input.lower()
user_input = user_input.replace("assignment","*********")
user_input = user_input.replace("quiz","****")
user_input = user_input.replace("exam","****")
# You can also use .replace in same line
# For example 
#user_input = user_input.replace("assignment","*********").replace("quiz","****").replace("exam","****")
print(user_input)
enter a string: The Exam was EaSy if YoU Have Prepared the Quiz and AssignMent Properly
the **** was easy if you have prepared the **** and ********* properly
In [1]:
#Example:
# Coming back to the fruits problem, now we can simply replace any spaces with a null string. 

fruits = ["Orange","Mango","Peach","Guava","Watermelon"]

for i in range(10): #Asking user 10 times
    user_input = input("Enter a fruit name: ")
    user_input = user_input.replace(" ","") #<--- Here's how I replaced any spaces with null strings
    user_input = user_input.title()#<-- Notice I converted the case after replacing the spaces. 
    if(user_input in fruits):
        print("You guessed the fruit correctly.")
    else:
        print("Sorry!")
Enter a fruit name: Water Melon
You guessed the fruit correctly.
Enter a fruit name: Wa Te  R  M   e  lo   n
You guessed the fruit correctly.
Enter a fruit name: P E A C H
You guessed the fruit correctly.
Enter a fruit name: P            e             a         c      h
You guessed the fruit correctly.
Enter a fruit name: ORA                N                GE
You guessed the fruit correctly.
Enter a fruit name: G u a v a
You guessed the fruit correctly.
Enter a fruit name: M a n g o
You guessed the fruit correctly.
Enter a fruit name: mango
You guessed the fruit correctly.
Enter a fruit name: orange
You guessed the fruit correctly.
Enter a fruit name: guava
You guessed the fruit correctly.

Chapter 25 to 28 - Dictionaries

Previously, we saw lists. They were defined as my_list = ["apple","orange","avocado"]. Now, when I need to access any value in the list, we can access it using index numbers i.e. my_list[0] returns apple and so on.
Sometimes, a list may contain specific information like my_list gets my first name, last name, age, gender and so on. Now, If I want to access the information, I would still have to use 0,1,2 which I may not remember everytime.
Dictionaries provide you the liberty to set your own index called Keys which you can access. The syntax is below:

Syntax:

  • A Dictionary is defined as a series of key-value pairs.
  • They are defined as
      my_name = {"first_name":"Ahsan","last_name":"Farooqui","age":29}
  • notice a dictionary is enclosed in curly brackets (instead of square brackets as in lists)
  • the first_name,last_name,age are called keys. They are strings most of the time but can be integer values too
  • Ahsan,Farooqui,29 are the values. They may be strings, integers, floating point numbers or any other values
  • Interestingly, the values can be lists too! We'll see some examples.
  • the key and value are separated by a colon sign. And after each key:value pair, we have a comma, followed by other pairs
  • to access a particular key, we can access it like my_name["first_name"] or my_name["age"] etc.
In [5]:
#Example1:
my_list = {"first_name":"John","last_name":"Doe","age":38,"score":45.5}
In [8]:
print(my_list["first_name"])
print(my_list["last_name"])
print(my_list["age"])
print(my_list["score"])
John
Doe
38
45.5
In [17]:
#Example2: We now define a dictionary that has keys countries, cities and population
# but instead of having one value, we have a list instead.
# lets see how we can now print values
# for this particular example, I used the same sequence i.e. first element of all lists relate to jordan and so on.
collections = {"countries":["jordan","syria","china","usa"],
               "cities":["Amman","Damascus","Beijing","Washington D.C"],
              "population":["9.956M","16.91M","1.39B","328.2M"]}
In [19]:
#Printing all countries
print(collections["countries"]) 
#Printing all cities
print(collections["cities"]) 
#Printing all popullations
print(collections["population"]) 
['jordan', 'syria', 'china', 'usa']
['Amman', 'Damascus', 'Beijing', 'Washington D.C']
['9.956M', '16.91M', '1.39B', '328.2M']
In [22]:
#Now, that the list is accessed, we can access any element in that list using same list referencing i.e. 0,1,2 etc. 
#Lets access first element of all lists

print(collections["countries"][0])
print(collections["cities"][0])
print(collections["population"][0])
jordan
Amman
9.956M
In [27]:
#Now, lets create a loop to display all options:
for i in range(len(collections["countries"])):
    print(f'First country name is {collections["countries"][i]}. Its capital is {collections["cities"][i]} and has a population of {collections["population"][i]}' ) 
First country name is jordan. Its capital is Amman and has a population of 9.956M
First country name is syria. Its capital is Damascus and has a population of 16.91M
First country name is china. Its capital is Beijing and has a population of 1.39B
First country name is usa. Its capital is Washington D.C and has a population of 328.2M

Keys can be integers as well.

In [6]:
#Keys can be integer values as well. Lets take an example:

things_to_remember = {0:"the lowest number",
                     12: "a dozen",
                     13:"a baker's dozen",
                     11: "snake eyes"}

print(things_to_remember[0])
print(things_to_remember[12])
print(things_to_remember[13])
print(things_to_remember[11])
the lowest number
a dozen
a baker's dozen
snake eyes

Chapter 29/30 - Updating Existing data and Creating new keys.

Once we have created a dictionary, we can add new keys to the dictionary

We can also update the information in the existing keys.

Taking the example of the dictionary created above, let's add two new keys 25 and 50 with information: "Silver" and "Gold" respectively.

Also, we will update the information against 0 to "smallest number"

In [7]:
things_to_remember[25] = "Silver"
things_to_remember[50] = "Gold"
things_to_remember[0] = "smallest number"
In [8]:
#The updated dictionary now becomes:
things_to_remember
Out[8]:
{0: 'smallest number',
 12: 'a dozen',
 13: "a baker's dozen",
 11: 'snake eyes',
 25: 'Silver',
 50: 'Gold'}

We can delete a key by simply using del keyword. Let's delete the 11 key from things_to_remember

In [9]:
del things_to_remember[11]
In [10]:
#Now the dictionary becomes:
print(things_to_remember)
{0: 'smallest number', 12: 'a dozen', 13: "a baker's dozen", 25: 'Silver', 50: 'Gold'}

Printing Keys and Values separately and together:

  • We can access the Keys using .keys() option in dictionary
  • We can access the values using .values() option in dictionary
  • We can get all key-value pairs in tuples using .items()
In [11]:
#Printing Keys and Values separately. 
print(things_to_remember.keys())
print(things_to_remember.values())
print(things_to_remember.items())
dict_keys([0, 12, 13, 25, 50])
dict_values(['smallest number', 'a dozen', "a baker's dozen", 'Silver', 'Gold'])
dict_items([(0, 'smallest number'), (12, 'a dozen'), (13, "a baker's dozen"), (25, 'Silver'), (50, 'Gold')])

Chapter 31,32 - Looping through the values and keys

In a dictionary, we have key-value pairs. We can use the for loop to loop through the values directly or loop through the keys and print values.

We saw earlier, how we can access keys and values separately.

Syntax:

  • We can access dictionary values directly using .values()
  • So syntax would be:
      for each_value in dictionary_name.values(): 
          print(each_value)
  • Notice the in keyword basically refers to the collection of values that is coming after it.
  • We can access key values directly using .keys()
  • So syntax would be:
      for each_key in dictionary_name.keys():
          print(each_key)
In [50]:
#Example for values
my_list1 = {"first_name":"Ahsan",
          "last_name":"Farooqui",
          "Age":29,
          0:"min value",
          100:"max value"}
for each_value in my_list1.values():
    print(each_value)
Ahsan
Farooqui
29
min value
max value
In [51]:
#Example for keys
for each_key in my_list1.keys():
    print(each_key)
first_name
last_name
Age
0
100

Chapter 33 - Looping through key-value pair

So far, we have just iterated through either key or the value separately.

But we can iterate through both as well.

Please find below the syntax for key-value pair

Syntax:

  • dictionary_name.items() gives
  • Syntax would be:
      for each_key,each_value in dictionary_name.items(): 
          print(each_value,each_key)
  • Notice that after for, we have now entered two variables separated by comma.
  • The first value will always respond to the key and the second value will always respond to value
  • Let's see an example for it
In [1]:
customer_data = {"name":"John",
                 "id":30,
                "joining date":"2019-04-01",
                "total spent":340000}
In [12]:
for key,value in customer_data.items():
    print(key,"-",value)
name - John
id - 30
joining date - 2019-04-01
total spent - 340000

Chapter 34/35 - Creating a list of dictionaries and accessing data

In the above customer_data, we see a dictionary that has the customer data in it.

Now, we may have multiple customers, each customer having their own id.

If we sort the customers with ids and put them in a list, we can have a list of dictionaries that can contain all users' data.

Syntax:

  • Syntax would be: customers_data = [
                      {first user data dictionary},
                      {second user data dictionary
                   ]
  • We can access the customers data accordingly. For example for first user, we can access it like
         customers_data[0][key_name]
  • If we dont pass a keyname, it will return the complete dictionary.
  • Example below:
In [1]:
#Let's create a list of dictionaries with 5 customer details

customers_data = [
    {"name":"John",
    "date_joined":"2019-02-02",
    "amount_spent":45000,
    "customer_level":"Gold"}
    ,
    {"name":"Robin",
    "date_joined":"2018-02-02",
    "amount_spent":120000,
    "customer_level":"Platinum"}
    ,
    
    {"name":"Rob",
    "date_joined":"2016-02-02",
    "amount_spent":100,
    "customer_level":"Rookie"}  
    
]
In [2]:
import pprint                         #An optional feature just to print dictionary in beautiful way, please comment it if you get library error.
pp = pprint.PrettyPrinter(indent=4)   #This is just to print the dictionary in a beautiful way. Totally optional.
#Now we print the first customer's complete data
pp.pprint(customers_data[0])
{   'amount_spent': 45000,
    'customer_level': 'Gold',
    'date_joined': '2019-02-02',
    'name': 'John'}
In [3]:
#Now let's get first customer's name only.
print(customers_data[0]["name"])

#How about last customer? 
print(customers_data[-1]["name"]) #Negative indexes corresponds to the values from last. -1 is for the last value in list, -2 is second last and so on. 
                                  #Negative indexes are helpful when you dont know the actual list length.
John
Rob
In [4]:
#Any ideas on how to get all names?
for customer in customers_data: #Each customer gets a dictionary value. 
    print(customer["name"])     #We can simply print the values in each iteration. 
#Try to get all information yourself.
John
Robin
Rob

Chapter 36 - How to append a new dictionary to a list of dictionaries

Here, we will discuss how to append a new dictionary in the existing list of dictionaries.

This may occur that a new customer joined and we wish to append their data in the list.

Syntax:

  • Create the new user's dictionary first separately.

      new_customer = {'amount_spent': 0,
      'customer_level': 'Newbie',
      'date_joined': '2020-05-20',
      'name': 'James'}
  • Protip: if you wish to append the list's index as id in the new customer's data, you can do it like following:

    • First get the length of list by len(list_name).
    • The length of the list is given by the total number of elements while the index of list go from 0 to one less than length of list.
    • So the length of a list gives us the next index value and we can simply use it as an id.
    • In our example, since we are not appending customer id in the data, we can ignore it.
  • Once we have the dictionary created, we can simply use the list's append function to append the new value.

      list_name.append(new_customer)
In [7]:
#Example:
#Defining the new customer's data:
new_customer = {'amount_spent': 0,
  'customer_level': 'Newbie',
  'date_joined': '2020-05-20',
  'name': 'James'}

#Now appending it to the original list
customers_data.append(new_customer)
In [11]:
#Printing afterwards:
customers_data
Out[11]:
[{'name': 'John',
  'date_joined': '2019-02-02',
  'amount_spent': 45000,
  'customer_level': 'Gold'},
 {'name': 'Robin',
  'date_joined': '2018-02-02',
  'amount_spent': 120000,
  'customer_level': 'Platinum'},
 {'name': 'Rob',
  'date_joined': '2016-02-02',
  'amount_spent': 100,
  'customer_level': 'Rookie'},
 {'amount_spent': 0,
  'customer_level': 'Newbie',
  'date_joined': '2020-05-20',
  'name': 'James'}]

Chapter 37 - Creating a dictionary that contains lists

We saw in the last chapter, the examples of a list of dictionaries. That is, a list contains multiple dictionaries.

What if we wish to store lists inside dictionary?

There can be a scenario where you need to have multiple values stored against a key.

For example, the discount cupons user is authorized to use, or the user's interests.

For that, we may simply use a list to store data.

Syntax:

  • We have following user's data.

      new_customer = {'amount_spent': 0,
      'customer_level': 'Newbie',
      'date_joined': '2020-05-20',
      'name': 'James'}
  • Now, we wish to add a list to it.

  • Using the syntax we studied before, we can define a new key.
      new_customer["discounts"] = ["10PercentOn4Items","5percentOn1Item"]
In [10]:
new_customer = {'amount_spent': 0,
        'customer_level': 'Newbie',
        'date_joined': '2020-05-20',
        'name': 'James'}

new_customer["discounts"] = ["10PercentOn4Items","5percentOn1Item"]
In [11]:
new_customer
Out[11]:
{'amount_spent': 0,
 'customer_level': 'Newbie',
 'date_joined': '2020-05-20',
 'name': 'James',
 'discounts': ['10PercentOn4Items', '5percentOn1Item']}

Chapter 38 - How to get information from a list in dictionary

In [12]:
#From previous example, lets take the customer's data
new_customer = {'amount_spent': 0,
        'customer_level': 'Newbie',
        'date_joined': '2020-05-20',
        'name': 'James'}

new_customer["discounts"] = ["10PercentOn4Items","5percentOn1Item"]
In [13]:
new_customer
Out[13]:
{'amount_spent': 0,
 'customer_level': 'Newbie',
 'date_joined': '2020-05-20',
 'name': 'James',
 'discounts': ['10PercentOn4Items', '5percentOn1Item']}
In [14]:
#Let's try to print the discounts list now. 
new_customer["discounts"]
Out[14]:
['10PercentOn4Items', '5percentOn1Item']
In [15]:
#Let us create a new keyword named discountpercent and put it equal to zero.
new_customer["discountpercent"] = 0
In [21]:
#Now lets make a for loop and search for discounts and add the percentages accordingly in a new keyword "discountpercent"

for item in new_customer["discounts"]:
    if(item=="10PercentOn4Items"):
        new_customer["discountpercent"] += 0.10
    elif(item=="5percentOn1Item"):
        new_customer["discountpercent"] +=0.05
    else:
        new_customer["discountpercent"]+=0
In [19]:
#So now the new dictionary becomes:
new_customer
Out[19]:
{'amount_spent': 0,
 'customer_level': 'Newbie',
 'date_joined': '2020-05-20',
 'name': 'James',
 'discounts': ['10PercentOn4Items', '5percentOn1Item'],
 'discountpercent': 0.15000000000000002}

Chapter 39 - Creating a dictionary that contains dictionaries

We saw examples of lists carrying dictionaries previously.

The problem with lists containing dictionaries is that we are strictly using the list indexes to access data.

What if we are to access the dictionary with a custom name? We can define a dictionary that contains dictionaries.

Each keyword can be customer's name or any identity and the data can contain a complete dictionary

Let us modify the previously used list of dictionaries and convert it into a dictionary of dictionaries.

In [1]:
# Previously we had the following list:

customers_data = [
    {"name":"John",
    "date_joined":"2019-02-02",
    "amount_spent":45000,
    "customer_level":"Gold"}
    ,
    {"name":"Robin",
    "date_joined":"2018-02-02",
    "amount_spent":120000,
    "customer_level":"Platinum"}
    ,
    
    {"name":"Rob",
    "date_joined":"2016-02-02",
    "amount_spent":100,
    "customer_level":"Rookie"}  
    
]
In [3]:
# Simply replacing the square brackets [] with {} to convert it into a dictionary:
#And we need to give a key name to these values. So lets try to give them the customer's name.

customers_data_dict = {
    "John":{"name":"John",
    "date_joined":"2019-02-02",
    "amount_spent":45000,
    "customer_level":"Gold"}
    ,
    "Robin":{"name":"Robin",
    "date_joined":"2018-02-02",
    "amount_spent":120000,
    "customer_level":"Platinum"}
    ,
    
    "Rob":{"name":"Rob",
    "date_joined":"2016-02-02",
    "amount_spent":100,
    "customer_level":"Rookie"}  
    
}

40 - How to get information out of a dictionary within another dictionary

In [7]:
#Now, Let's access John's data
customers_data_dict["John"]
Out[7]:
{'name': 'John',
 'date_joined': '2019-02-02',
 'amount_spent': 45000,
 'customer_level': 'Gold'}
In [8]:
#For any specific data from this dictionary, we use another index ahead of the key. 
customers_data_dict["John"]["customer_level"]
Out[8]:
'Gold'