Choosing How to Store Several Values
Choose a collection according to how the program will access and change its data.
Some collections can contain objects of different types, but each type has its own rules. Dictionary keys and set members, for example, must remain hashable while they are in the collection. The collection type also determines whether its contents can change after creation.
Python provides five common built-in collections:
- A string stores an immutable sequence of characters
- A list stores an ordered sequence whose elements can change
- A tuple stores an ordered sequence whose positions cannot change
- A dictionary stores key-value pairs
- A set stores unique members without indices
Python Lists
A list preserves element order and allows its contents to change. One list may contain values of different types, although a consistent element shape is usually easier to process.
Unlike a fixed-size low-level array, a Python list can grow and shrink. It stores references to Python objects, so mutating a nested object can be visible through every reference to that object.
List Properties
Compare order, mixed types, and mutability when choosing a list. Ordered means that every element has a position. It does not mean that values are automatically sorted.
| Characteristic | Explanation | Example |
|---|---|---|
| Ordered | Each element has a position | [1, 2, 3] is different from [3, 2, 1] |
| Heterogeneous | Can hold various data types | [1, 'text', 3.14, True] |
| Mutable | Contents can be changed after creation | Can add, remove, or modify elements |
Writing a List
A list literal uses square brackets and separates its elements with commas. A list can contain values of different types or other lists.
# Various list types based on data types
a = [True, False, True] # Value: [True, False, True]
b = [1, 2, 3] # Value: [1, 2, 3]
c = [1.5, 2.5, 3.5] # Value: [1.5, 2.5, 3.5]
d = ['red', 'green', 'blue'] # Value: ['red', 'green', 'blue']
# Empty lists
empty1 = [] # Value: []
empty2 = list() # Value: []
# Heterogeneous list (mixed data types)
mixed = [False, 2, 3.5, 'blue'] # Value: [False, 2, 3.5, 'blue']
# Nested list
nested = [1, [2.5, False, 'red'], 3.5, 'blue'] # Value: [1, [2.5, False, 'red'], 3.5, 'blue']List Indexing
Indexing accesses one list element by its position. Python uses zero-based indexing, so the first element has index .
Python list indices follow these rules:
- Positive indices start from for the first element
- Negative indices start from for the last element
- An index outside the valid range raises
IndexError
# Example of indexing on nested lists
nested = [1, [2.5, False, 'red'], 3.5, 'blue']
print('nested =', nested) # Output: nested = [1, [2.5, False, 'red'], 3.5, 'blue']
# Indexing main elements
print('nested[0] =', nested[0]) # Output: nested[0] = 1
print('nested[-1] =', nested[-1]) # Output: nested[-1] = blue
print('nested[1] =', nested[1]) # Output: nested[1] = [2.5, False, 'red']
# Indexing elements in nested lists
print('nested[1][2] =', nested[1][2]) # Output: nested[1][2] = red
# Indexing characters in strings (double indexing)
print('nested[1][2][1] =', nested[1][2][1]) # Output: nested[1][2][1] = eSlicing with Stride
Slicing takes part of a list. The step sets the distance between selected elements.
The complete syntax is list[start:stop:step], where:
startis the first included indexstopis the first excluded indexstepis the distance between selected indices
# List for slicing examples
x = [0, 1, 2, 3, 4, 5]
print('x =', x) # Output: x = [0, 1, 2, 3, 4, 5]
# Basic slicing
print('x[1:4] =', x[1:4]) # Output: x[1:4] = [1, 2, 3]
# Slicing from negative index to end
print('x[-3:] =', x[-3:]) # Output: x[-3:] = [3, 4, 5]
# Slicing with step (stride)
print('x[1:4:2] =', x[1:4:2]) # Output: x[1:4:2] = [1, 3]
# Reversing list with negative step
print('x[::-1] =', x[::-1]) # Output: x[::-1] = [5, 4, 3, 2, 1, 0]Slicing selects a contiguous or regularly spaced part of a list. For x = [0, 1, 2, 3, 4, 5], x[1:4] returns the elements at indices , , and . The end index is excluded. The expression x[1:4:2] uses a step of , so it selects indices and .
Lists and Strings
Lists provide operations for reading and changing data. Their indexing and slicing syntax matches the syntax used for strings.
# Various ways to display lists
nested = [1, [2.5, False, 'red'], 3.5, 'blue']
# Display with assignment
print('nested =', nested)
# Output: nested = [1, [2.5, False, 'red'], 3.5, 'blue']
# Display without assignment
print(nested)
# Output: [1, [2.5, False, 'red'], 3.5, 'blue']
# Display with print function
print('List content:', nested)
# Output: List content: [1, [2.5, False, 'red'], 3.5, 'blue']Lists and strings both support indexing and slicing.
| Operation | String | List |
|---|---|---|
| Indexing | Get individual characters | Get individual elements |
| Slicing with a step | Get part of a string | Get part of a list |
The main difference is mutability. A string cannot change after creation, while a list can. List methods can therefore add, remove, replace, or reorder elements.
| Method | Description | Usage Example |
|---|---|---|
append(element) | Add element at end of list | Adding new item |
extend(list2) | Merge with elements from another list | Combining two lists |
insert(index, element) | Insert element at specific position | Adding in middle of list |
index(element) | Find first index of element | Finding item position |
pop() | Remove and return last element | Taking last item |
reverse() | Reverse list order directly | Reversing order |
remove(element) | Remove first occurrence of element | Removing specific item |
sort() | Sort list directly | Sorting data |
copy() | Create a shallow copy | Copy the list without copying nested objects |
count(element) | Count occurrences of element | Counting frequency |
# Demonstration of various list methods
my_list = [1, 2, 3]
print('Original list:', my_list) # Output: Original list: [1, 2, 3]
# Adding elements
my_list.append(4)
print('After append(4):', my_list) # Output: After append(4): [1, 2, 3, 4]
my_list.extend([5, 6])
print('After extend([5, 6]):', my_list) # Output: After extend([5, 6]): [1, 2, 3, 4, 5, 6]
my_list.insert(0, 0)
print('After insert(0, 0):', my_list) # Output: After insert(0, 0): [0, 1, 2, 3, 4, 5, 6]
# Searching elements
idx = my_list.index(3)
print('Index of 3:', idx) # Output: Index of 3: 3
my_list.append(3)
count = my_list.count(3)
print('Count of 3:', count) # Output: Count of 3: 2
# Removing elements
my_list.remove(3)
print('After remove(3):', my_list) # Output: After remove(3): [0, 1, 2, 4, 5, 6, 3]
popped = my_list.pop()
print('Popped element:', popped) # Output: Popped element: 3
print('After pop():', my_list) # Output: After pop(): [0, 1, 2, 4, 5, 6]
# Organizing elements
my_list.reverse()
print('After reverse():', my_list) # Output: After reverse(): [6, 5, 4, 2, 1, 0]
my_list.sort()
print('After sort():', my_list) # Output: After sort(): [0, 1, 2, 4, 5, 6]
copied = my_list.copy()
print('Copied list:', copied) # Output: Copied list: [0, 1, 2, 4, 5, 6]The copy() method creates a new outer list, while nested objects remain shared. Changing salinan[0][0] appears in both lists, but appending a row changes only the outer list salinan.
original = [[1, 2], [3, 4]]
salinan = original.copy()
salinan[0][0] = 99
print(original) # Output: [[99, 2], [3, 4]]
print(salinan) # Output: [[99, 2], [3, 4]]
salinan.append([5, 6])
print(len(original), len(salinan)) # Output: 2 3Common List Forms
A list can be empty, contain mixed types, or contain other lists:
-
Empty Lists
Both
[]andlist()create an empty list that can be filled later. -
Heterogeneous Lists
One list can contain a name, an age, and a Boolean value. Use mixed types only when each position has a clear meaning.
-
Nested Lists
A nested list contains other lists as its elements. Equal-length inner lists can represent rows of a matrix or table.
# Empty lists - two creation methods
a = [] # Value: []
b = list() # Value: []
# Heterogeneous list - various data types
mixed = [False, 2, 3.5, 'blue'] # Value: [False, 2, 3.5, 'blue']
# Nested list - list within list
nested = [1, [2.5, False, 'red'], 3.5, 'blue'] # Value: [1, [2.5, False, 'red'], 3.5, 'blue']
print('Empty list 1:', a)
print('Empty list 2:', b)
print('Mixed types:', mixed)
print('Nested structure:', nested)Nested lists can represent rows, trees, or small table-like structures. They do not automatically form a rectangular matrix. Multiple elements can also refer to the same inner list. Chained indexing such as nested[1][2] selects one element at each level.
Other Containers
Three other common containers have different rules about order, duplicates, and changes after creation. A tuple fixes its positions, a dictionary maps each unique key to one value, and a set keeps only unique items without promising an order.
Tuple
A tuple resembles a list, but its positions cannot be replaced after creation. Several values can be packed into one tuple and later unpacked into separate variables.
A tuple cannot replace its own elements, but an element may refer to a mutable object whose contents can still change.
| Aspect | Tuple | List |
|---|---|---|
| Mutability | Immutable | Mutable |
| Syntax | () or without parentheses | [] |
| Usage | Data with fixed positions, such as coordinates | Data that needs additions or changes |
# Tuple syntax - two creation methods
t1 = (0, 1, 2) # Value: t1 = (0, 1, 2)
t2 = 3, 4, 5 # Value: t2 = (3, 4, 5)
print('t1 =', t1)
print('t2 =', t2)
# Tuple unpacking - separating values
a, b, c = t2
print('a, b, c =', a, b, c) # Output: a, b, c = 3 4 5
# Error handling for unpacking
try:
a, b = (0, 1, 2) # Too many values
except ValueError as e:
print('ValueError:', e) # Output: ValueError: too many values to unpack (expected 2)
try:
a, b, c, d = 0, 1, 2 # Not enough values
except ValueError as e:
print('ValueError:', e) # Output: ValueError: not enough values to unpack (expected 4, got 3)
# Tuple with mutable objects
t = (0, [1, 2, 3], 4)
print('Original t =', t) # Output: Original t = (0, [1, 2, 3], 4)
t[1][0] = 'x' # Modifying list contents in tuple
print('After modifying inner list:', t) # Output: After modifying inner list: (0, ['x', 2, 3], 4)
# Tuple immutable but objects inside can be mutable
# t[1] = [9, 8, 7] # Error: cannot change reference
# t[1][0] = 'y' # OK: can modify mutable object contentsDictionary
A dictionary stores key-value pairs. Each key must be unique and remain hashable while it is in the dictionary. Values may repeat and may refer to mutable objects. A dictionary literal uses {} with a colon between each key and value.
# Creating dictionary
kontak = {'Alice': 'alice@example.com', 'Bob': 'bob@example.com'}
print('kontak =', kontak)
# Output: kontak = {'Alice': 'alice@example.com', 'Bob': 'bob@example.com'}
# Accessing values by key
print("kontak['Alice'] =", kontak['Alice']) # Output: kontak['Alice'] = alice@example.com
# Adding new key-value pairs
kontak['David'] = 'david@example.com'
print('After adding David:', kontak)
# Output: After adding David: {'Alice': 'alice@example.com', 'Bob': 'bob@example.com', 'David': 'david@example.com'}Set
A set stores unique, hashable elements and supports mathematical set operations. It provides no element indices and makes no iteration-order guarantee. Nonempty set literals use {}, while an empty set must be created with set() because {} creates an empty dictionary.
# Creating set
angka = {1, 2, 3, 4, 5}
print('angka =', sorted(angka)) # Output: angka = [1, 2, 3, 4, 5]
# Adding elements to set
angka.add(6)
print('After adding 6:', sorted(angka)) # Output: After adding 6: [1, 2, 3, 4, 5, 6]
# Set operations
genap = {2, 4, 6, 8}
ganjil = {1, 3, 5, 7}
# Union (combination)
print('genap | ganjil =', sorted(genap | ganjil))
# Output: genap | ganjil = [1, 2, 3, 4, 5, 6, 7, 8]
# Intersection
print('genap & ganjil =', genap & ganjil) # Output: genap & ganjil = set()Collection Type Comparison
The four built-in collections differ in order, mutability, and duplicate handling. The table compares them so you can pick one from the task at hand.
| Container | Syntax | Ordered | Mutable | Duplicates | Main Usage |
|---|---|---|---|---|---|
| List | [1, 2, 3] | Yes | Yes | Yes | Data that needs changing |
| Tuple | (1, 2, 3) | Yes | No | Yes | Fixed data, coordinates |
| Dictionary | {'a': 1} | Yes* | Yes | No (keys) | Key-value mapping |
| Set | {1, 2, 3} | No | Yes | No | Unique elements, set operations |
Dictionary iteration preserves insertion order as a language guarantee since Python
3.7. Updating an existing key keeps its position. Deleting and reinserting it places it at the end.