### Python Lists
A Python list is a data structure that is mutable, ordered, and allows duplicate elements. Lists are highly versatile and can hold elements of different data types, including numbers, strings, objects, or even other lists. Lists are defined by placing elements within square brackets, separated by commas.
“`python
numbers = [1, 2, 3, 4, 5]
fruits = [‘apple’, ‘banana’, ‘cherry’, ‘date’]
mixed = [1, ‘apple’, 3.14, True]
“`
### Indexing
Lists in Python are zero-indexed, meaning the first element is accessed with index 0. Negative indexing is also supported and starts from the end of the list.
“`python
numbers = [10, 20, 30, 40, 50]
# Positive Indexing
first_num = numbers[0] # 10
third_num = numbers[2] # 30
# Negative Indexing
last_num = numbers[-1] # 50
second_last_num = numbers[-2] # 40
“`
### Slicing
Slicing allows you to obtain a sublist from a list. The syntax is `[start:stop:step]`. The ‘start’ index is inclusive while the ‘stop’ index is exclusive.
“`python
numbers = [10, 20, 30, 40, 50, 60]
# Basic Slicing
sublist1 = numbers[1:4] # [20, 30, 40]
# Omitting the start index defaults to 0
sublist2 = numbers[:3] # [10, 20, 30]
# Omitting the stop index includes all elements till the end
sublist3 = numbers[3:] # [40, 50, 60]
# Slicing with step
sublist4 = numbers[::2] # [10, 30, 50]
“`
### Appending and Extending
– **`append()`**: Adds a single element to the end of the list.
– **`extend()`**: Adds all elements of an iterable (like a list) to the end of the list.
“`python
fruits = [‘apple’, ‘banana’]
# Append
fruits.append(‘cherry’) # [‘apple’, ‘banana’, ‘cherry’]
# Extend
fruits.extend([‘date’, ‘elderberry’]) # [‘apple’, ‘banana’, ‘cherry’, ‘date’, ‘elderberry’]
“`
### Removing Elements
– **`remove()`**: Removes the first occurrence of a value.
– **`pop()`**: Removes an element at a specified position (default is the last element).
– **`clear()`**: Removes all elements from the list.
“`python
fruits = [‘apple’, ‘banana’, ‘cherry’, ‘date’]
# Remove by value
fruits.remove(‘banana’) # [‘apple’, ‘cherry’, ‘date’]
# Pop by index
popped_fruit = fruits.pop(1) # ‘cherry’, and now fruits is [‘apple’, ‘date’]
# Clear entire list
fruits.clear() # []
“`
### Sorting
Lists can be sorted in ascending or descending order. Use the `sort()` method for in-place sorting, or `sorted()` for returning a new sorted list.
“`python
numbers = [3, 1, 4, 1, 5, 9]
# In-place sort
numbers.sort() # [1, 1, 3, 4, 5, 9]
# Reverse sorting
numbers.sort(reverse=True) # [9, 5, 4, 3, 1, 1]
# Using sorted() for a new sorted list
sorted_numbers = sorted(numbers) # [1, 1, 3, 4, 5, 9]
“`
### List Comprehensions
List comprehensions offer a concise way to create lists and can include conditional logic to filter elements.
“`python
# Squaring numbers
squares = [x**2 for x in range(6)] # [0, 1, 4, 9, 16, 25]
# Filtering and transforming
long_fruits = [fruit.upper() for fruit in fruits if len(fruit) > 5] # [‘BANANA’, ‘CHERRY’]
“`
### Performance Considerations
– **Access Time**: Lists provide O(1) access using indices, which is very efficient.
– **Append Time**: Append operations are amortized O(1) because lists grow dynamically.
– **Insert/Remove Time**: Both operations are O(n) since elements may need to be shifted.
– **Memory**: Lists are not the most memory-efficient as they allocate blocks of memory.
### When Lists Are Not the Best Choice
– **Immutable Data**: If immutability is important, consider using tuples.
– **High Performance**: For better performance, especially with operations like insertions/removals at arbitrary positions, `collections.deque` is often more efficient.
– **Hash-Based Operations**: If you need fast membership tests or unique elements, `set` is more appropriate.
Python lists are incredibly versatile, offering a broad range of utilities for various programming needs. They come with trade-offs in terms of performance and can be substituted with other data structures when their limitations become a bottleneck.