One variable holds one thing. A shopping trip is not one thing. It is bread and milk and eggs and ten more items, and you do not want ten variables named item1 through item10. Python has a container built for exactly this, and it is the one you will reach for every single day.
items = ['bread', 'milk', 'eggs'] print(items) print(len(items), 'items')
['bread', 'milk', 'eggs'] 3 items
That is a list. One name, many values, kept in order. This part covers the list and its two quieter cousins, the tuple and the set, and where each one earns its place.
All you need is Python 3 and about thirty five minutes. This part sits on top of the loops from Part 6, because a list and a for loop are made for each other. Nothing here touches files or paths, so the code runs the same on Windows, macOS and Linux. Copy any block, run it, and your screen should match. One warning first. If you copy code off a web page and Python complains about a SyntaxError near a quote, your straight quotes may have turned curly on the way over. Type the quotes yourself and it clears up. Career switchers, this is the part where your programs stop handling one value and start handling real batches of data.
Four containers, one quick map
Before any code, here is the whole chapter on one screen. Python gives you four everyday containers. You will spend most of your time in the first one, but knowing when the others fit saves real effort later.
| Container | Brackets | In order | Duplicates | Change later | Reach for it when |
|---|---|---|---|---|---|
| list | [ ] | yes | allowed | yes | almost anything, the default |
| tuple | ( ) | yes | allowed | no | a fixed group that stays put |
| set | { } | no | removed | add or remove only | unique items, fast checks |
| dict | { key: value } | yes | keys unique | yes | labelled pairs, see Part 8 |
The dictionary is next in Part 8, so this part spends its time on the first three. Keep one detail from that last row in mind now, because it trips up everyone once. An empty pair of curly brackets {} makes a dictionary, not a set. For an empty set you write set().
The list: your default container
A list is an ordered run of values inside square brackets, separated by commas. The values can be numbers, strings, or a mix. Order is kept, so the first thing you put in is the first thing you get back.
Reading items by position
Each item sits at a numbered position called its index, and counting starts at 0, not 1. That zero is the single most important fact about lists, so it is worth saying plainly. The first item is at index 0. A negative index counts from the end, so -1 is the last item. A slice with a colon pulls out a range.
fruits = ['apple', 'banana', 'cherry'] print(fruits[0]) print(fruits[-1]) print(fruits[1:3])
apple cherry ['banana', 'cherry']
The slice fruits[1:3] starts at index 1 and stops before index 3, the same left out end you met with range in Part 6. So it gives you positions 1 and 2, and not 3.
The same four items carry two sets of positions. items[0] and items[-4] are both bread.
Changing a list in place
Lists are made to be edited. append adds to the end, sort reorders in place, in tests membership, and len counts. A few of them together:
nums = [3, 1, 2] nums.append(4) nums.sort() print(nums) print(len(nums)) print(2 in nums)
[1, 2, 3, 4] 4 True
Notice the list itself changed. append and sort did not hand back a new list, they rearranged the one you already had. That in place habit is the root of the one gotcha every beginner meets with lists.
a = [1, 2, 3] b = a a.append(4) print(b)
[1, 2, 3, 4]
The tuple: a list you promise not to change
A tuple is an ordered group of values, like a list, but frozen. Once you make it, you cannot add, remove, or replace items. You write it with round brackets.
point = (3, 4) print(point[0]) x, y = point print(x, y)
3 3 4
Reading a tuple works exactly like a list, with the same index positions. The last line is a small trick called unpacking. It hands the two values in point straight into x and y in one line. Try point[0] = 5 and Python stops you with a TypeError that says a tuple does not support item assignment, which is the whole point of a tuple.
The one comma that matters
There is a trap with a single item tuple. Brackets alone do not make a tuple, the comma does.
one = (5,) not_a_tuple = (5) print(type(one)) print(type(not_a_tuple))
<class 'tuple'> <class 'int'>
Without the trailing comma, (5) is just the number 5 with some brackets around it. The comma in (5,) is what tells Python you meant a one item tuple. For two or more values the comma is already there, so this only bites on single item tuples.
Here is a plain opinion, since beginners often ask when tuples matter. Most days, they do not. Use a list and move on. Reach for a tuple in two honest cases: when a small group of values belongs together and must not be edited by accident, like a pair of coordinates or a fixed row, and later, when you need something that can act as a dictionary key, which a list cannot. If neither is true, a tuple is just a list you cannot fix when requirements change. Do not sprinkle them everywhere for the feeling of safety.
The set: unique items, fast checks
A set holds only unique items and does not keep them in any order. Put a duplicate in and it simply collapses to one. That single behaviour makes sets the cleanest way to strip repeats and the fastest way to ask does this contain X.
colors = {'red', 'blue', 'red'}
print(len(colors))
print('red' in colors)2 True
Three values went in, two came out, because the second red was a duplicate. One warning about sets. They have no order, so printing a set may show its items in any arrangement, and you cannot ask for colors[0]. There is no position 0 to fetch. If you need order or positions, use a list.
The most common real use is removing duplicates from a list in a single line. Wrap the list in set() and the repeats vanish.
names = ['ana', 'bob', 'ana'] unique = set(names) print(len(unique))
2
Four items with three apples go in. The set keeps one apple and one pear.
A worked example: cleaning a guest list
Here is a small job you might actually be handed. Someone gives you a guest list where a few people were entered twice, and they want to know how many real people are coming. Build it up the way you would for real.
guests = ['Ana', 'Bob', 'Ana', 'Cara', 'Bob']
unique = set(guests)
print('Invited entries:', len(guests))
print('Real people:', len(unique))Invited entries: 5 Real people: 3
Five entries, three people. Now say you try to print the first unique guest by position, out of habit:
print(unique[0])
Traceback (most recent call last):
File 'guests.py', line 5, in <module>
print(unique[0])
TypeError: 'set' object is not subscriptableRead the last line first, the habit from Part 6. It says a set is not subscriptable, which is the formal way of saying you cannot index it with [0]. That is expected, not a mistake in your logic. A set has no positions. If you want them back in order, and you want the first copy of each name kept, there is one clean move:
ordered = list(dict.fromkeys(guests)) print(ordered)
['Ana', 'Bob', 'Cara']
dict.fromkeys walks the list once, keeps the first time it sees each name, and drops later repeats, and because dictionaries remember insertion order in Python 3, the result stays in the original order. Wrap it in list() and you have a deduplicated list that a set alone could not give you.
print('My Expense Tracker')
amounts = []
while True:
category = input('Category or done: ')
if category == 'done':
break
amount = float(input('Amount: '))
amounts.append(amount)
print('Saved', amount, 'for', category)
print('Entries:', len(amounts))
print('Total spent:', sum(amounts))My Expense Tracker Category or done: Groceries Amount: 250 Saved 250.0 for Groceries Category or done: Bus Amount: 40 Saved 40.0 for Bus Category or done: done Entries: 2 Total spent: 290.0
Highest: 90 Different prices: 3
Show solution
prices = [40, 15, 40, 90, 15]
print('Highest:', max(prices))
print('Different prices:', len(set(prices)))Highest: 90 Different prices: 3
max scans the list for the biggest number, and set(prices) collapses the two 40s and two 15s so len counts three distinct values.
Questions that come up with collections
When should I use a tuple instead of a list? Use a tuple when the group should not change, like a fixed pair of coordinates or a record you do not want edited by accident. If you will add or remove items, use a list.
Why did my second variable change when I only changed the first? Because b = a makes two names for one list, not a copy. Change one and both see it. Make a real copy with b = a.copy() when you want them independent.
How do I remove duplicates from a list? Wrap it in set(), as in unique = set(my_list). If you also need the original order kept, use list(dict.fromkeys(my_list)), which keeps the first copy of each.
Why can I not do my_set[0]? A set has no order and no positions, so indexing makes no sense and Python raises a TypeError. Loop over the set, or turn it into a list first with list(my_set).
What is the comma in (5,) for? Without it, (5) is just the number 5 in brackets. The comma is what makes it a one item tuple. For two or more values, like (5, 6), the comma is already there.
You can now build a list, read items by position including from the end, slice a range out of it, grow and sort it with append and sort, protect a fixed group inside a tuple, and strip duplicates or test membership fast with a set.
Part 8 gives each expense a label instead of a bare number by pairing a key with a value in a dictionary, the container that finally lets one entry hold an amount, a category and a note together. Keep expenses.py exactly as it stands, because Part 8 builds on this list. Try the prices task before you open the solution.
References
Python docs: data structures, lists and sets
Python docs: tuples
Python docs: dict.fromkeys


DrJha