Python gives you several ways to store a group of values. Two of the most important choices you will make early on are whether your collection should be ordered — keeping items in a fixed, predictable sequence — or unordered — storing items without any guaranteed position. Getting this distinction right from the start will save you from confusing bugs later.
Before writing a single line of Python, it helps to understand that the language has three workhorse collection types you will encounter constantly: list, tuple, and set. A list and a tuple are ordered. A set is unordered. Each one exists because different problems call for different guarantees about how data is stored and retrieved.
What "ordered" means in Python
When Python documentation says a collection is ordered, it means the collection remembers the exact position of every item. The position is called an index, and it always starts at zero. If you put "apple" first, it stays first — always at index 0 — no matter what happens to the rest of the list.
# A Python list is ordered
fruits = ["apple", "banana", "cherry"]
print(fruits[0]) # apple — always the first item
print(fruits[1]) # banana — always the second item
print(fruits[2]) # cherry — always the third item
# You can also count from the end using negative indexes
print(fruits[-1]) # cherry — the last item
Because list is ordered, you can retrieve any item you want by its index position. This is called indexing. It is predictable and fast. Python knows exactly where to look without checking every item.
A tuple is also ordered and uses the same zero-based index system as a list. The difference is that a tuple is immutable — you cannot change its contents after you create it. Use parentheses to create one: my_tuple = ("a", "b", "c").
Both list and tuple support slicing, a way to grab a range of items in one step. Slicing only works because the collection is ordered — without a defined sequence, a range of positions would have no meaning.
# Slicing an ordered list — grab items from index 1 up to (not including) index 3
fruits = ["apple", "banana", "cherry", "date"]
print(fruits[1:3]) # ['banana', 'cherry']
print(fruits[:2]) # ['apple', 'banana'] — from the start
print(fruits[2:]) # ['cherry', 'date'] — to the end
A slice like fruits[1:3] means "start at index 1, stop before index 3." The stop index is always exclusive. This catches new learners off guard — write a small test and print the result until the pattern clicks.
Build a Python list called colors that holds three string values in this order: "red", "green", "blue".
[ and ]. Curly braces create a set or dictionary, and parentheses create a tuple. The variable name comes first, then the assignment operator =, then the opening bracket, the items separated by commas, and the closing bracket.
What "unordered" means in Python
An unordered collection stores items without assigning them a position. Python's set type works this way. When you create a set, Python does not promise that the items will come out in the same sequence you put them in. There is no index — and that means you cannot use my_set[0] to access the first item, because from Python's perspective there is no first item.
# A Python set is unordered
fruits = {"apple", "banana", "cherry"}
# Printing a set may show items in any order
print(fruits) # Could be: {'cherry', 'apple', 'banana'} — not guaranteed
# This raises a TypeError — sets have no index
# print(fruits[0]) # TypeError: 'set' object is not subscriptable
# You can still check membership — that is what sets are good at
print("apple" in fruits) # True
print("grape" in fruits) # False
Sets have two defining characteristics that make them useful in the right situation. First, they automatically remove duplicate values. If you add the same item twice, the set only keeps one copy. Second, checking whether a value exists in a set (item in my_set) is very fast — much faster than scanning through a list one item at a time.
# Sets deduplicate automatically
tags = {"python", "beginner", "python", "tutorial", "beginner"}
print(tags) # {'python', 'beginner', 'tutorial'} — duplicates removed
# A common use: remove duplicates from a list
numbers = [4, 7, 2, 7, 4, 9, 2]
unique_numbers = list(set(numbers))
print(unique_numbers) # [2, 4, 7, 9] — order may vary
Do not create an empty set with {}. Python interprets empty curly braces as an empty dictionary, not an empty set. Use set() instead: empty_set = set().
The code below tries to access the first item of a set by index. One line contains the bug. Click it, then hit check.
animals[0] and instead iterate over the set or convert it to a list first: first = list(animals)[0]. Sets are unordered and do not support index access. Python raises a TypeError: 'set' object is not subscriptable on line 4.
Ordered vs Unordered: a side-by-side look
The table below compares the three main collection types you will use as a beginner. Click any row to expand the details.
- Syntax
my_list = [1, 2, 3]— square brackets, comma-separated values- Index access
- Yes.
my_list[0]returns the first item reliably every time. - Allows duplicates
- Yes.
[1, 1, 2, 3]is a valid list with two copies of 1. - Mutable
- Yes. You can add, remove, or change items after creation using methods like
.append()and.remove(). - Best used for
- Any sequence where position matters — steps in a process, ranked results, or data that will be modified over time.
- Syntax
my_tuple = (1, 2, 3)— parentheses, comma-separated values- Index access
- Yes.
my_tuple[0]works exactly like a list index. - Allows duplicates
- Yes.
(1, 1, 2, 3)is a valid tuple. - Mutable
- No. Once a tuple is created, its contents cannot be changed. Attempting to assign a new value raises a
TypeError. - Best used for
- Fixed collections of related values that should not change — coordinates, RGB colors, configuration constants, or function return values with multiple parts.
- Syntax
my_set = {1, 2, 3}— curly braces, comma-separated. Useset()for an empty set.- Index access
- No. Sets do not support index access. There is no guaranteed order, so there is no index 0.
- Allows duplicates
- No. Adding a duplicate value to a set has no effect. The set keeps only one copy of each value.
- Mutable
- Yes. You can add items with
.add()and remove them with.discard()or.remove(). - Best used for
- Membership testing, deduplication, and set operations like union and intersection where position does not matter.
How to choose the right collection type
Picking the right collection type is a four-question process. Work through each question in order and you will land on the right answer every time.
-
Decide whether order matters
Ask yourself whether the position of each item is meaningful. If the first item must always be the first — such as steps in a process, ranked results, or a log of events — you need an ordered type:
listortuple. If position is irrelevant, asetmay be the right fit. -
Decide whether duplicates are allowed
If your data can contain the same value more than once and you need to keep all copies — for example, a list of user-submitted votes — use a
list. If you only care about unique values and want duplicates removed automatically, use aset. -
Decide whether the collection will change
If you need to add, remove, or update items after creation, use a
listorset— both are mutable. If the data should stay fixed after creation — like a pair of GPS coordinates or a set of constant settings — use atuple. Its immutability also makes it slightly more memory-efficient than a list. -
Write the collection literal
Use square brackets for a list:
["a", "b", "c"]. Use curly braces for a set:{"a", "b", "c"}. Use parentheses for a tuple:("a", "b", "c"). Each syntax signals intent clearly to anyone reading your code.
Practical examples with all three types
Seeing all three types in a real scenario makes the differences concrete. Imagine you are building a small program that tracks a to-do list, a set of unique tags, and a fixed point on a map.
# list — ordered, mutable to-do items
tasks = ["Buy groceries", "Write report", "Call dentist"]
tasks.append("Pay bills") # add to end
print(tasks[0]) # Buy groceries — first item always at index 0
# set — unordered, unique tags
tags = {"python", "tutorial", "beginner"}
tags.add("python") # duplicate — silently ignored
print(len(tags)) # 3 — still only three unique tags
print("tutorial" in tags) # True — fast membership check
# tuple — ordered, immutable coordinates
location = (29.7604, -95.3698) # Houston latitude, longitude
print(location[0]) # 29.7604 — latitude never changes
# location[0] = 30.0 # TypeError — tuples cannot be modified
"Lists are mutable sequences, typically used to store collections of homogeneous items." — Python Documentation
One thing that surprises new learners is that you can convert between these types. list(my_set) turns a set into a list. set(my_list) turns a list into a set and removes duplicates in the process. tuple(my_list) creates an immutable snapshot of a list. Conversions are useful, but be careful — converting a set to a list produces a list whose order is not guaranteed to match anything predictable.
# Converting between types
numbers_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
numbers_set = set(numbers_list) # duplicates removed
numbers_tuple = tuple(numbers_list) # immutable snapshot
print(numbers_list) # [3, 1, 4, 1, 5, 9, 2, 6, 5] — original with duplicates
print(numbers_set) # {1, 2, 3, 4, 5, 6, 9} — unique values, any order
print(numbers_tuple) # (3, 1, 4, 1, 5, 9, 2, 6, 5) — fixed copy
Key points to remember
- A list is ordered and mutable. Use it when position matters and the data will change. Access items with square-bracket indexing:
my_list[0]. - A tuple is ordered and immutable. Use it for fixed collections where the values should not change after creation. It supports the same index syntax as a list.
- A set is unordered and stores only unique values. Use it when you need fast membership testing or want to remove duplicates. Index access raises a
TypeError. - You can convert between types with
list(),set(), andtuple()— but converting from an unordered set to an ordered list gives you unpredictable item order.
Building the habit of choosing the right collection type from the start will make your code clearer and faster. When you reach for a list by default, pause and ask whether order actually matters for your situation. The answer shapes which type you should use.
Frequently Asked Questions
An ordered list in Python is a collection that remembers the position of every item. A list defined as ['apple', 'banana', 'cherry'] will always keep 'apple' at index 0. Python's built-in list and tuple types are ordered sequences.
An unordered collection does not guarantee any fixed position for its items. Python's set type is the primary example. You cannot use an index like my_set[0] on a set because there is no guaranteed first item.
A list is ordered, allows duplicate values, and is mutable. A set is unordered, stores only unique values, and is also mutable. Use a list when order and duplicates matter. Use a set when you only care whether something is present, not where it is.
No. Because sets are unordered, Python does not assign index numbers to their items. Attempting my_set[0] raises a TypeError: 'set' object is not subscriptable. To access individual items you must iterate over the set or convert it to a list first.
Both list and tuple are ordered sequences. The key difference is mutability. A list is mutable — you can add, remove, or change items after creation. A tuple is immutable — once created its contents cannot be changed. Tuples are created with parentheses and are slightly more memory-efficient than lists.
Use a list when the order of items matters, when you need to access items by position using an index, or when your data may contain duplicate values that you want to preserve. Use a set when you only need to track unique values and order does not matter.
As of Python 3.7, dictionaries maintain insertion order. Items you add first appear first when you iterate over the dictionary. However, dictionaries are accessed by key, not by numeric index, which makes them different from lists and tuples.
Create a list using square brackets: my_list = ['item1', 'item2', 'item3']. Items are stored in the order you write them and can be retrieved with an index such as my_list[0]. You can also build a list dynamically by starting with an empty list and using .append().