Python - Datatype - List Tutorial
The list is used to store the sequence of various types of elements like int, float, string, etc.
It is stored under a square bracket [] and each element is separated with commas.
We can use indexing to access an item on the list separately.
Its indexing starts from 0 and ends at n-1, where n is the total number of elements.
It supports both +ve and -ve indexing. It can contain duplicate values.
Trying to access other indexes that are not in the list will give IndexError. An index must be always an integer.
# empty list
list_a = []
print(list_a)
# list of integers
list_b = [2, 9, 12]
print(list_b)
# Accessing the 1st element of the list_b
print(list_b[0])
# list with mixed data types
list_c = [1, "Hello", 1.02]
print(list_c)
# Accessing the last element of the list_c
print(list_c[2])
Output-
[]
[2, 9, 12]
2
[1, 'Hello', 1.02]
1.02
The list is mutable, unlike string and tuple. It means we can modify or change the value of the element in the list after it is created.
# list of integers
list_b = [2, 9, 12]
print(list_b)
# Modifying the 2nd element to a string
list_b[0]="String"
print(list_b)
Output-
[2, 9, 12]
['String', 9, 12]
The list can also have another list as an item. This is called a nested list.
# Nested List
list_b = [2, 9, ['Sam', 2.14, 5]]
# Accessing the nested list
# Accessing 1st item of list
print(list_b[1])
# Accessing 1st item of the 3rd item of list
print(list_b[2][0])
# Accessing 3rd item of the 3rd item of list
print(list_b[2][2])
Output-
9
Sam
5
Negative Indexing
In python, we can use negative indexing. Suppose we want to access the last element of the list and we are unaware of the number of elements in the list. In that case, we can use negative indexing to access the list element from the end.
The index of -1 refers to the last index, -2 refers to the second last index, and so on.
# list of integers
list_b = [2, 9, 12]
print(list_b)
# Accessing the last element of the list_b
print(list_b[-1])
# Accessing the last 2nd element of the list_b
print(list_b[-2])
Output-
[2, 9, 12]
12
9
Slicing List
We can get a particular range of elements from the list using a colon (:)
# list
list_b = [2, 9, 12, "fresherbell", "python", "tutorial", 2.24, 21.3]
# Accessing the element 4th to 6th
print(list_b[3:6])
# Accessing the element from start to 3rd
print(list_b[:3])
# Accessing the element 5th to last
print(list_b[4:])
# Accessing the element last 5th to last
print(list_b[-5:])
Output-
['fresherbell', 'python', 'tutorial']
[2, 9, 12]
['python', 'tutorial', 2.24, 21.3]
['fresherbell', 'python', 'tutorial', 2.24, 21.3]
Addition Of Element In The List
The list is mutable. We can add, remove or modify the element in the list.
append() & extend()
We can add one item to the list using the append() method.
To add several items we use extend() method.
Both will add the item at the last of the list.
# list of integers
list_b = [2, 9, 12]
# Adding one item in the list using append
list_b.append("fresherbell")
print(list_b)
# Adding multiple item in the list using extend
list_b.extend(["python", 'tutorial', 2.12])
print(list_b)
Output-
[2, 9, 12, 'fresherbell']
[2, 9, 12, 'fresherbell', 'python', 'tutorial', 2.12]
Concatenation or combining two lists using the + operator.
# list of integers
list_a = [2, 9, 12]
# list of string
list_b = ['fresherbell', 'python', 'tutorial']
# Adding two list or Concatenating
list_c = list_a + list_b
print(list_c)
Output-
[2, 9, 12, 'fresherbell', 'python', 'tutorial']
insert()
To insert an item at a particular position, we will use the insert() method.
With the insert() method, we can insert one or multiple items at the required position.
# list of integers
list_a = [2, 9, 12]
# inserting item into list at particular position
list_a.insert(2,"fresherbell")
print(list_a)
# It will insert [21,7] at position 3
# another item will get moved to next position
list_a[3:3] = [21, 7]
print(list_a)
# It will insert [19,5] at position 3, by replacing position 3 item
# other items will get moved to the next position
list_a[3:4] = [19, 5]
print(list_a)
# It will insert [19,5] at position 3, by replacing position 3 & 4th item
# other items will get moved to next position
list_a[3:5] = [18, 3, 4]
print(list_a)
Output-
[2, 9, 'fresherbell', 12]
[2, 9, 'fresherbell', 21, 7, 12]
[2, 9, 'fresherbell', 19, 5, 7, 12]
[2, 9, 'fresherbell', 18, 3, 4, 7, 12]
Removal Of Element From The List
We can remove one item or multiple items from the list using the del keyword.
It can also delete the whole list.
# list
list_a = [2, 9, 'fresherbell', 18, 3, 4, 7, 12]
# delete the particular element(4th item) from list
del list_a[3]
print(list_a)
# delete multiple elements (from 2nd to 4th item) from the list
del list_a[2:4]
print(list_a)
# deleting the whole list
del list_a
print(list_a)
Output-
[2, 9, 'fresherbell', 3, 4, 7, 12]
[2, 9, 4, 7, 12]
NameError: name 'list_a' is not defined
We can also remove the item, by assigning an empty list to a slice of an element.
# list
list_a = [2, 9, 2, 8, 2, 18, 19, 20, 2]
# To remove the item from 2nd to 5th position
list_a[2:6] = []
print(list_a)
[2, 9, 19, 20, 2]
remove()
remove() method is used to remove an item irrespective of its position. It will remove only one item that will occur at starting position.
Suppose we have to remove a particular number (e.g 2) from a list. Then we can use a remove() method.
# list
list_a = [2, 9, 2, 8, 2, 18, 19, 20, 2]
# remove value 2 from the first occurrence of list
list_a.remove(2)
print(list_a)
Output-
[9, 2, 8, 2, 18, 19, 20, 2]
pop()
the pop() method is used to remove an item at a given index or it will remove the last item from the list if the index is not provided.
# list
list_a = [2, 9, 2, 8, 2, 18, 19, 20, 2]
# remove 5th position of list
list_a.pop(5)
print(list_a)
# It will remove last element if index is not provided
list_a.pop()
print(list_a)
Output-
[2, 9, 2, 8, 2, 19, 20, 2]
[2, 9, 2, 8, 2, 19, 20]
clear()
the clear() method will clear the list and return empty list
# list
list_a = [2, 9, 2, 8, 2, 18, 19, 20, 2]
# To empty the list
list_a.clear()
print(list_a)
Output-
[]
index()
To get an index of a particular item in the list, we will use the index() method.
Syntax-
list.index(element, start position, end position)
Start and end positions are optional.
If no element is found in the list, It will raise a ValueError exception.
It will return only the first occurrence of an element.
# list
list_a = [2, 9, 2, 8, 2, 18, 19, 20, 2]
# To get the index of 2
i = list_a.index(2)
print(i)
# To get the index of 2, from position 3 to 7
i = list_a.index(2,3,7)
print(i)
Output-
0
4
count()
To count() the number of times the particular item is on the list. We will use the count() method.
Syntax-
list.count(element)
Example-
# list
list_a = [2, 9, 2, 8, 2, 18, 19, 20, 2]
# To get the count of 2
c = list_a.count(2)
print(c)
Output-
4
sort()
To sort items in the list in ascending or descending order. We will use the sort() method.
It will only sort homogenous data.
Syntax-
list.sort(key=…,reverse=….)
Here key and reverse are optional.
If the reverse is true, it will sort the list in descending order. If the reverse is false, then it will sort the list in ascending order.
By default it is false
# list
list_a = [2, 9, 2, 8, 2, 18, 19, 20, 2]
# To sort the list_a in ascending order (default)
list_a.sort()
print(list_a)
list_a.sort(reverse=False)
print(list_a)
# To sort the list_a in descending order
list_a.sort(reverse=True)
print(list_a)
Output-
[2, 2, 2, 2, 8, 9, 18, 19, 20]
[2, 2, 2, 2, 8, 9, 18, 19, 20]
[20, 19, 18, 9, 8, 2, 2, 2, 2]
Suppose a list has a key: value pair, then we can sort the list using a particular key.
Using the key, we can also sort several strings according to their length.
# list_a
list_a = ['Welcome', 'To', 'Fresherbell', 'Python', 'Tutorial']
list_a.sort(key = len)
print(list_a)
#list_b
list_b = [{'Subject': 'Math', 'Mark': 85},
{'Subject': 'Science', 'Mark': 35},
{'Subject': 'English', 'Mark': 95},
{'Subject': 'Hindi', 'Mark': 65}]
# custom functions to get info
def get_subject(list_b):
return list_b.get('Subject')
# To sort the list_b on the basis of a subject
list_b.sort(key = get_subject)
print(list_b)
# To sort the list_b on the basis of a mark using Lambda function
list_b.sort(key=lambda x: x.get('Mark'))
print(list_b)
Output-
['To', 'Python', 'Welcome', 'Tutorial', 'Fresherbell']
[{'Subject': 'English', 'Mark': 95}, {'Subject': 'Hindi', 'Mark': 65}, {'Subject': 'Math', 'Mark':
85}, {'Subject': 'Science', 'Mark': 35}]
[{'Subject': 'Science', 'Mark': 35}, {'Subject': 'Hindi', 'Mark': 65}, {'Subject': 'Math', 'Mark':
85}, {'Subject': 'English', 'Mark': 95}]
reverse()
the reverse() method will reverse the elements of the list.
Syntax-
list.reverse()
Example-
# list_a
list_a = ['Welcome', 'To', 'Fresherbell', 'Python', 'Tutorial', 5]
print("Original List ",list_a)
# Not permanent changes
print("Using Slicing ",list_a[::-1])
print("Original List remain same ",list_a)
# Permanent changes using reverse()
list_a.reverse()
print("Reversed List ",list_a)
Output-
Original List ['Welcome', 'To', 'Fresherbell', 'Python', 'Tutorial', 5]
Using Slicing [5, 'Tutorial', 'Python', 'Fresherbell', 'To', 'Welcome']
Original List remain same ['Welcome', 'To', 'Fresherbell', 'Python', 'Tutorial', 5]
Reversed List [5, 'Tutorial', 'Python', 'Fresherbell', 'To', 'Welcome']
copy()
To copy elements from one list to another list. We can use the copy() method.
We can also use assignment operator ( = ) to copy list.
Syntax-
new_list = old_list.copy()
Example-
# list_a
list_a = ['Welcome', 'To', 'Fresherbell', 'Python', 'Tutorial']
print(list_a)
list_b = list_a.copy()
print(list_b)
# Using Assignment Operator
list_c = list_a
print(list_c)
Output-
['Welcome', 'To', 'Fresherbell', 'Python', 'Tutorial']
['Welcome', 'To', 'Fresherbell', 'Python', 'Tutorial']
['Welcome', 'To', 'Fresherbell', 'Python', 'Tutorial']
Shallow and Deep Copy
In Python, we use =
operator to create a copy of an object. It doesn't create a new object. It only creates a new variable that will refer to the original object.\
Example-
old_list = [1, 2, 3]
new_list = old_list
#if you modify the new list, the change will be visible in both
new_list[2]=5
print('Old List:', old_list)
print('ID of Old List:', id(old_list))
print('New List:', new_list)
print('ID of New List:', id(new_list))
#old_list and new_list shares the same identity
Output-
Old List: [1, 2, 5]
ID of Old List: 140436364171072
New List: [1, 2, 5]
ID of New List: 140436364171072
In the above program, both lists share the same identity, and any changes made in the new list will also be visible in the old list.
Sometimes you are required to modify the old copies, without changing the original data. In that case, two methods are used to create copies.
- Shallow Copy
- Deep Copy
Copy module
we use the copy module of Python for shallow and deep copy operations to copy the list.
Syntax-
import copy
copy.copy(x)
copy.deepcopy(x)
Here copy.copy(x) will return a shallow copy of list x. And copy.deepcopy(x) will return a deep copy of list x.
Shallow Copy
The shallow copy will create a new object, which stores the reference of the original element.
This means shallow copy doesn't create a copy of the nested object and any modification in the nested object will also modify the original list nested object.
Example-
import copy
old_list = [[1,2,3],[4,5,6],[7,8]]
new_list = copy.copy(old_list)
print("Old list:", old_list)
print("New list:", new_list)
#If we append any element in new_list, then the changes is not visible in original list
new_list.append(9)
print("Old list:", old_list)
print("New list:", new_list)
Output-
Old list: [[1, 2, 3], [4, 5, 6], [7, 8]]
New list: [[1, 2, 3], [4, 5, 6], [7, 8]]
Old list: [[1, 2, 3], [4, 5, 6], [7, 8]]
New list: [[1, 2, 3], [4, 5, 6], [7, 8], 9]
From the above example, it is clear that a shallow copy will create a new and independent object.
But if we make any changes to the nested list or sublist of the new_list, then changes will be visible in the original list. This is because both lists share the reference of the same nested objects.
Example-
import copy
old_list = [[1,2,3],[4,5,6],[7,8]]
new_list = copy.copy(old_list)
print("Old list:", old_list)
print("New list:", new_list)
#If we make any changes in the nested/sublist of new_list, then the changes is visible in original list
new_list[2][1]=9
print("Old list:", old_list)
print("New list:", new_list)
Output-
Old list: [[1, 2, 3], [4, 5, 6], [7, 8]]
New list: [[1, 2, 3], [4, 5, 6], [7, 8]]
Old list: [[1, 2, 3], [4, 5, 6], [7, 9]]
New list: [[1, 2, 3], [4, 5, 6], [7, 9]]
Deep Copy
The deep copy will create a new object and all the nested objects of the original object
This means any modification in the nested object will not modify the original list nested object.
Example-
import copy
old_list = [[1,2,3],[4,5,6],[7,8]]
new_list = copy.deepcopy(old_list)
print("Old list:", old_list)
print("New list:", new_list)
#If we make any changes in the nested/sublist of new_list, then the changes will not visible in original list
new_list[2][1]=9
print("Old list:", old_list)
print("New list:", new_list)
Output-
Old list: [[1, 2, 3], [4, 5, 6], [7, 8]]
New list: [[1, 2, 3], [4, 5, 6], [7, 8]]
Old list: [[1, 2, 3], [4, 5, 6], [7, 8]]
New list: [[1, 2, 3], [4, 5, 6], [7, 9]]
From the above example, it is clear that in deep copy old_list and new_list are independent.
List Comprehension
List Comprehension is a short syntax or one-line code used when you want to create a new list based on the values of an existing list.
Syntax-
newList = [ expression(element) for element(iterable) in oldList if condition ]
Advantages are-
- Time Efficient & Space Efficient
- Fewer lines of code
For example, suppose we want to extract only an alphabetic username from the email id given in the list.
email=['12345@gmail.com','vaibsm@outlook.com','sam@hotmail.com','helpdesk@fresherbell.com']
username1=[]
# Using for loop it will take 3 line to extract only alphabetic username
for i in email:
if(i.split('@')[0].isalpha()):
username1.append(i.split('@')[0])
print(username1)
# Using list comprehension it will take 1 line to extract only alphabetic username
username2=[i.split('@')[0] for i in email if i.split('@')[0].isalpha()]
print(username2)
Output-
['vaibsm', 'sam', 'helpdesk']
['vaibsm', 'sam', 'helpdesk']
In the above example, list comprehension will only take 1 line, while normal code will take 3 lines to write logic.
List Comprehension vs Lambda Function
We can achieve short syntax or one line of code from Lambda Function also. Lambda function is a built-in function and can create and modify the list in fewer lines of code.
But the problem with the lambda function is, that it will return something, otherwise, it will give an error, if the value is not returned.
Example-
email=['12345@gmail.com','vaibsm@outlook.com','sam@hotmail.com','helpdesk@fresherbell.com']
# Using list comprehension it will take 1 line to extract only alphabetic username
username2=[i.split('@')[0] for i in email if i.split('@')[0].isalpha()]
print(username2)
# Also using lambda function it will take 1 line to extract only alphabetic username
username3=list(map(lambda x: x.split('@')[0] if(x.split('@')[0].isalpha()) else "", email))
print(username3)
#It will give error, if value is not returned
username4=list(map(lambda x: x.split('@')[0] if(x.split('@')[0].isalpha()), email))
print(username4)
Output-
['vaibsm', 'sam', 'helpdesk']
['', 'vaibsm', 'sam', 'helpdesk']
File "C:\Users\ssaur\AppData\Local\Temp/ipykernel_9892/2835995980.py", line 8
username4=list(map(lambda x: x.split('@')[0] if(x.split('@')[0].isalpha()), email))
^
SyntaxError: invalid syntax
In the above example,
in a part of username3, it returns some value if the value is true, otherwise, it will return an empty string on false
in a part of username4, it returns some value if the value is true, but there is no else condition. hence nothing is returned in else part. which will throw an error.
Hence, list comprehension is a more readable and elegant way to define logic.