These tips on how to work with Python lists will help you write code that is memory-efficient, clean, concise, and readable.
The lists data structures in Python are ordered, mutable, and can contain elements of diverse data types. Numerous methods and function operations are offered by Python for accessing and manipulating specific elements or ranges of lists.
Python lists support nested structures. Python’s dynamic typing system gives flexibility in data representation and manipulation. One important advantage of Python lists is their mutable nature, which allows for in-place modifications. Here are a few tips for sorting a list, using the list as a double-sided queue, list multiplication, Python arrays, and Python’s ‘any()’ and ‘all()’ functions. Mastering them will help you have a better understanding of how to use Python lists.
Sorting lists: sort() vs sorted()
There are two ways to sort lists in Python: ‘list.sort()’ and ‘sorted(list)’. ‘sort()’ sorts the list in-place (modifies the original), while ‘sorted()’ creates a new sorted list, and the original list is preserved. Use the ‘sorted()’ function when the original data needs to be preserved, or when working with strings or tuples.
list1 = [5, 4, 3, 2, 1] # In-place sort list1.sort() print(list1) # Output: [1, 2, 3, 4, 5] # Create a new sorted list original_list = [5, 4, 3, 2, 1] new_list = sorted(original_list) print(original_list) # Output: [5, 4, 3, 2, 1] (original is unchanged) print(new_list) # Output: [1, 2, 3, 4, 5]
Adding and removing elements from both sides of a list: ‘deque’
A normal list lets you add and remove elements from the end of the list. If you need to efficiently add or remove elements from both ends of a list, use ‘deque’ (double-ended queue) from the ‘collections’ module. Unlike standard lists, deque provides fast O (1) performance for ‘appendleft()’ and ‘popleft()’ operations. These operations are slow (O (n)) for lists.
from collections import deque dq = deque([10, 15, 20]) #Appending an element dq.appendleft(5) #appendleft() adds element to the left end of the list #append() #adds element to the right end of the list dq.append(25) print(dq) # Output: deque([5, 10, 15, 20, 25]) #Popping an element l_element = dq.popleft() r_element = dq.pop() print(l_element) # Output: 5 print(r_element) # Output: 25 print(dq) # Output: deque([10, 15, 20])
ʽdequeʼ is useful in queue-based algorithms, real-time data processing, and web scraping.
Quick list initialisation: Multiplication
Python’s list multiplication operator (*) provides a time and memory-efficient method of list initialisation. It is useful for creating pre-populated lists quickly and works with any data type. Memory is allocated before the list is created to improve speed.
#Create a list named list1 containing ten 1’s. list1 = [1] * 10 print(list1) #Output: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
The above code is equivalent to writing ʽ[1, 1, 1, 1,..,1]ʼ
(10 times) and is a concise method to initialise such lists.
Caution: Using it with mutable elements can lead to unexpected behaviour. An example is given here.
nested_list = [ [0] * 3 ] * 2 nested_list [ 0 ] [ 0 ] = 1 print(nested_list) # Output: [[1, 0, 0], [1, 0, 0]]
This is due to all sublists referencing the same object.
Memory-efficient lists: The array module
For lists containing only one data type (e.g., all integers or all floats), the array module offers a memory-efficient alternative. ‘array’ stores data more compactly, since there is no need for additional type information for each element. But it’s limited to a single data type.
When creating an array, the specific type of data that it will hold has to be mentioned. We create an array that will hold only integer data types. The ‘i’ represents the data type for integers.
from array import array #Create an integer array i_array = array(‘i’, [5,10,15,20,25 ]) print(i_array) #Output: array(‘i’, [ 5, 10, 15, 20, 25 ])
Trying to add another data type will generate a type error. Most common list operations like slicing, indexing, len(), extend(), and append() can be done on arrays.
i_array = array(‘i’, [5,10,15,20,25]) i_array.append(50) print(i_array) # Output: array(‘i’, [ 5, 10, 15, 20, 25, 50 ])
Operations that add a different data type element to the array cannot be carried out and will generate errors.
i_array.append(5.5) #Output: Error message
Similarly, an array that holds only floating-point numbers can be created. The ‘f’ represents the data type code for floating-point numbers.
from array import array #Array of floats f_array = array(‘f’, [ 1.1, 1.3, 1.5, 1.7, 1.9 ]) print(f_array) #Output: array(‘f’, [1.100000023841858, …, 1.899999976158142])
When working with large datasets of homogeneous data, such as sensor readings in IoT devices, or numerical data in scientific applications, arrays are particularly useful. The memory savings offered by arrays can be substantial in such scenarios, allowing you to process and store more data without running out of memory.
Table 1: Common codes for the array module
Type of
code |
C type | Python type | Minimum size (Bytes) |
‘b’ | signed char | int | 1 |
‘B’ | unsigned char | int | 1 |
‘h’ | signed short | int | 2 |
‘H’ | unsigned short | int | 2 |
‘i’ | signed int | int | 2 |
‘I’ | unsigned int | int | 2 |
‘l’ | signed long | int | 4 |
‘L’ | unsigned long | int | 4 |
‘q’ | signed long long | int | 8 |
‘Q’ | unsigned long long | int | 8 |
‘f’ | float | float | 4 |
‘d’ | double | float | 8 |
Python’s ‘any()’ and ‘all()’ functions
The ‘any()’ and ‘all()’ functions can be used to check for complex and verbose conditions efficiently. They can be useful for validating user inputs, filtering data, or checking conditions. The resultant code is much cleaner and more expressive, and improves code readability as a result. ‘any()’ is similar to the logical operator ‘or’ and ‘all()’ is similar to the logical ‘and’ operators. These two functions are a Pythonic way to evaluate multiple conditions and work with lists, tuples, dictionaries, and strings.
In Python, every object can be evaluated as either True or False in a Boolean context. Python has the concept of ‘truthiness’. Truthy values are values that are considered True, including non-empty sequences (strings, lists, tuples), non-zero numbers, and objects that are not None. Falsy values are those that evaluate to False such as empty sequences (empty lists).
These functions short-circuit, implying that ‘any()’ stops at the first truthy element and ‘all()’ stops at the first falsy element.
False values:
- The number zero: 0, 0.0
- Empty sequences: “”, [],()
- None
- False itself
- Truthy values:
- Non-zero numbers: 1, -1, 3.14
- Non-empty sequences: “hello”, [1, 2, 3], (4, 5, 6)
- Objects that are not None
The ‘any()’ function:
The ‘any()’ function is a built-in Python method that takes an iterable as an argument and returns ‘True’ if at least one element in the iterable is True, and returns ‘False’ otherwise. ‘any()’ returns False if the iterable is empty.
#Checking if any number is divisible by 3 numlist = [1, 4, 6, 9, 11, 14] if any(num % 3 == 0 for num in numlist): print(“At least one number is divisible by 3.”) #Output: At least one number is divisible by 3 # Checking if any number in a list is even numbers = [1, 2, 3, 4, 5] if any(num % 2 == 0 for num in numbers): print(“At least one number is even!”) #Output: At least one number is even! list2 = [0, 1, 0] print(any(list2)) # Output: True set1 = {0, 1} print(any(set1)) # Output: True
The ‘all()’ function
The ‘all()’ function, on the other hand, takes an iterable as an argument and returns True if every element in the iterable is truthy. It also returns True if the iterable is empty.
numlist = [6, 9, 12] if all(num % 3 == 0 for num in numlist): print(“All numbers are divisible by 3.”) #Output: All numbers are divisible by 3. # Checking if all numbers in a list are positive numbers = [1, 2, -3, 4, 5] if all(num > 0 for num in numbers): print(“All numbers are positive!”) else: print(“ All numbers are not positive.”) #Output: All numbers are not positive.
Using ‘any()’ and ‘all()’ makes the code readable and efficient. These also help to express complex conditions in a single line of code.
Mastering the above techniques will help you write more efficient, readable, and maintainable code, and elevate your Python programming skills. Go ahead and start experimenting with Python lists!