Create your own
Lesson illustration

Choosing the Right Python Data Structure

Good to see you again. In the last lesson, you worked with individual Python values—numbers, strings, Booleans, and None—and traced how assignments changed program state. Real data work rarely involves just one value: you may have many event records, a fixed coordinate pair, a collection of permitted categories, or information attached to a particular customer ID.

This lesson introduces Python’s four core built-in collection types: lists, tuples, sets, and dictionaries. The goal is not to memorize punctuation alone. It is to read a data task’s requirements—Does order matter? Can values repeat? Will the collection change? Do I need a named lookup?—and choose a structure whose behavior matches.


Start with the data requirement, not the brackets

A collection stores multiple values together. The same values can often be put into different collection types, but the choice changes what your code means and what operations are sensible.

For example, these all contain course names:

courses_list = ["python", "sql", "python"]

courses_tuple = ("python", "sql", "python")

courses_set = {"python", "sql", "python"}

They do not preserve the same information:

print(courses_list)
print(courses_tuple)
print(courses_set)

The list and tuple retain both occurrences of "python". The set retains only one, because a set represents unique values.

Use this compact comparison as your first decision aid:

StructureTypical syntaxKeeps position/order?Allows duplicates?Can change after creation?Best first use case
List["a", "b"]YesYesYesA changing sequence of items
Tuple("a", "b")YesYesNoA fixed ordered grouping
Set{"a", "b"}No guaranteed usable orderNoYesUnique values or membership checks
Dictionary{"key": "value"}Insertion order is retained in modern PythonKeys: no; values: yesYesLook up a value by a meaningful key

“Ordered” here means that lists and tuples have positions: item 0, item 1, and so on. That makes indexing meaningful. A dictionary preserves the order in which keys were added in current Python versions, but its main purpose is still a mapping from names or IDs to values—not position-based access.

The infographic compares lists, tuples, sets, and dictionaries by mutability, order, uniqueness, and key-value lookup. Its upper panels are a useful overview, but its bottom summary table incorrectly marks tuples and dictionaries as unordered; tuples are ordered, and modern Python dictionaries preserve insertion order.

That inconsistency is a useful reminder for professional data work: diagrams and AI-generated summaries can be helpful, but validate claims against code or reliable documentation before building on them.

Python Lists vs Tuples vs Sets: Visually Explained

Watch “Python Lists vs Tuples vs Sets: Visually Explained” from Visually Explained for a short visual comparison of the three sequence-like collection types. It will give you a clear mental picture before you use them in data-oriented examples.

Watch the syntax to distinguish the brackets used to create each structure. Then watch uniqueness and order, focusing on why a set removes repeated values and cannot be indexed. Watch mutability for the practical difference between editable lists, fixed tuples, and editable sets. Finish with the recap; pause before it and try to state the choice rule yourself.


Lists: ordered collections that are expected to change

A list is usually the default choice when you have a sequence of related values, their order matters, duplicates may be meaningful, and you expect to add, remove, or update items.

Imagine collecting a customer’s page visits in chronological order:

page_visits = ["home", "pricing", "home", "checkout"]

This needs to be a list:

  • The first "home" visit and the later "home" visit are both real events, so duplicates matter.
  • The order tells a behavioral story.
  • More visits may arrive.

Lists use square brackets and positions begin at zero:

print(page_visits[0])
print(page_visits[2])

Output:

home
home

Although the values happen to be the same, page_visits[0] and page_visits[2] refer to different events at different positions.

Because a list is mutable, operations can alter the object itself:

page_visits.append("support")
page_visits[1] = "product_page"

print(page_visits)

The resulting list is:

["home", "product_page", "home", "checkout", "support"]

The call to .append() does not make a new list and assign it somewhere. It changes the existing list. When tracing list code, keep a record of its state after every modifying line, just as you traced variable assignments in the previous lessons.

Use a list when the task sounds like:

  • “Keep the submitted records in their original order.”
  • “Store a queue of files to process.”
  • “Track each daily metric, including repeated values.”
  • “Build up a collection as the program runs.”

Do not choose a list merely because it is familiar if the real task is “keep only distinct values” or “find a customer record by ID.” Sets and dictionaries communicate those intentions more directly.


Tuples: ordered collections that should stay fixed

A tuple is an ordered collection like a list, but it is immutable: once created, its items cannot be replaced, added, or removed.

A geographic location is a natural example. Latitude is the first value and longitude is the second; that positional meaning matters, but the two-part representation should not casually change halfway through a calculation.

store_location = (40.7128, -74.0060)

latitude = store_location[0]
longitude = store_location[1]

print(latitude)
print(longitude)

You can read a tuple by index, but this fails:

store_location[0] = 41.0

Python raises a TypeError because tuple item assignment is not allowed.

For now, interpret a tuple as a signal to a future reader of your code:

“This is a small, ordered grouping whose contents are intended to remain fixed.”

A tuple is suitable for:

  • A coordinate: (latitude, longitude)
  • A fixed RGB color: (255, 255, 255)
  • A stable pair such as (minimum_value, maximum_value)
  • A defined sequence of field names that should not be changed accidentally
required_model_fields = ("age", "income", "tenure_months")

The tuple does not make the values inherently true or validated; it protects the collection from accidental list-style edits in your program. If you need to add a new field regularly, a list is the more honest choice.

One syntax detail is worth saving for later: a one-item tuple needs a comma.

not_a_tuple = ("age")
one_item_tuple = ("age",)

Without the comma, ("age") is simply the string "age" inside parentheses.


Sets: unique values and “is this allowed?” checks

A set is a collection of unique values. It is ideal when repeated entries have no additional meaning and you care about membership: whether a value is present.

Suppose a raw event feed includes repeated campaign codes:

campaign_codes = ["SPRING", "EMAIL10", "SPRING", "REFERRAL", "EMAIL10"]

To identify which campaigns appeared at least once:

unique_campaign_codes = set(campaign_codes)

print(unique_campaign_codes)

The order you see when printing a set is not something to rely on, but the important fact is that it contains only these three values:

SPRING
EMAIL10
REFERRAL

Sets are especially valuable for rules such as “these are the valid categories”:

allowed_regions = {"north", "south", "east", "west"}

print("north" in allowed_regions)
print("central" in allowed_regions)

Output:

True
False

The in operator produces a Boolean, connecting directly to your previous lesson. In the next lesson, you will use those Booleans in if statements:

region = "central"

# You will learn the full conditional syntax next.
region_is_allowed = region in allowed_regions

Sets can change by adding or removing whole values:

allowed_regions.add("central")
allowed_regions.remove("west")

But sets have no item positions. This is invalid:

# allowed_regions[0]

There is no meaningful “first region” in a set. If order or position matters, choose a list or tuple instead.

At this stage, remember two practical constraints:

  1. A set removes duplicates automatically.
  2. Set elements must be stable, hashable values such as strings, integers, and tuples of simple values. You cannot put a list or dictionary inside a set.

There is also a common empty-set trap:

empty_dictionary = {}
empty_set = set()

Curly braces by themselves create an empty dictionary, not an empty set.


Dictionaries: attach values to meaningful names or identifiers

A dictionary stores key-value pairs. Use one when the important question is not “what is item number 2?” but “what value belongs to this particular named field, customer, or ID?”

A simple customer record might look like this:

customer = {
    "customer_id": 1042,
    "segment": "returning",
    "order_count": 3,
    "has_marketing_consent": True,
}

Each key describes what its value means. Retrieve a value with its key:

print(customer["segment"])
print(customer["order_count"])

Output:

returning
3

This is clearer and safer than relying on an arbitrary position such as customer_data[1]. A reader can see immediately what "segment" means; they cannot infer the meaning of index 1 without extra documentation.

Dictionaries are mutable, so you can update an existing key or add a new one:

customer["order_count"] = 4
customer["last_contact_date"] = None

print(customer)

Dictionary keys must be unique. If you write the same key twice in a dictionary literal, the later value replaces the earlier one:

bad_record = {
    "status": "active",
    "status": "inactive",
}

print(bad_record)

The dictionary contains only one "status" key, with value "inactive". This behavior can silently discard information, so duplicate keys in a record definition are usually a bug.

A dictionary is the natural choice when the task sounds like:

  • “Find this customer’s profile from their customer ID.”
  • “Store a model run’s settings by descriptive name.”
  • “Represent one structured record with named fields.”
  • “Map a country code to a country name.”
  • “Count an outcome for each category.”

Python Data Structures: Lists, Dictionaries, Sets, Tuples – Dataquest

Read the “Dictionaries” section of “Python Data Structures: Lists, Dictionaries, Sets, Tuples” from Dataquest. It reinforces the central mapping idea and shows how a dictionary can hold a simple value or a more complex record.

In the “Dictionaries” section, begin at the mapping explanation. Focus on the difference between a key and a value, why keys must identify one entry, and why nested values are possible. Then continue through the creation, lookup, and update examples until the next main subsection, “Sets.” Ignore performance and internal implementation details for now; your priority is selecting a structure that accurately represents the task.


A reliable selection process

When a data task arrives, apply these questions in order.

  1. Do I need to associate each value with a meaningful key?
    Choose a dictionary.

    monthly_revenue = {
        "January": 12000,
        "February": 13500,
        "March": 12800,
    }
    
  2. Do I need only distinct values, or frequent membership checks?
    Choose a set.

    excluded_customer_ids = {101, 205, 411}
    
  3. Do positions and duplicates matter, and will the collection change?
    Choose a list.

    daily_signups = [18, 22, 22, 31, 27]
    
  4. Do positions and duplicates matter, but the grouped values should not change?
    Choose a tuple.

    confidence_interval = (0.41, 0.57)
    

Some realistic data workflows use more than one structure at once. That is normal.

orders = [
    {"order_id": 1, "region": "north", "items": 2},
    {"order_id": 2, "region": "south", "items": 1},
]

valid_regions = {"north", "south", "east", "west"}

model_feature_names = ("items", "days_since_last_order")

Here:

  • orders is a list because there are multiple records in a meaningful sequence.
  • Each order is a dictionary because its fields have names.
  • valid_regions is a set because each permitted label needs to appear only once.
  • model_feature_names is a tuple because it is a fixed ordered specification.

Later, pandas DataFrames will be your main structure for full tables. These core types still matter: API responses often arrive as dictionaries and lists, configuration commonly uses dictionaries, and sets are useful in data-quality checks.


Build and trace a small collection scratchpad

Spend 10–12 minutes in a notebook named collection_choice_practice.ipynb. Write the code yourself first; do not ask an AI tool to generate it. The point is to connect each requirement to syntax and then inspect the resulting state.

Create these four variables:

VariableRequired structureRequired contents
event_typesList"login", "purchase", "login", "logout" in that order
unique_event_typesSetCreated from event_types
model_input_fieldsTuple"age", "income", "tenure_months"
feature_defaultsDictionaryKeys for those three fields, each initially mapped to None

Then perform these actions:

  • Append "purchase" to event_types.
  • Change the default for "tenure_months" in feature_defaults from None to 0.
  • Print the first event from event_types.
  • Print the number of distinct items in unique_event_types.
  • Print whether "purchase" is in unique_event_types.
  • Print the value associated with "income" in feature_defaults.

Before running the cell, write a brief markdown prediction of what each printed value will be. For the set, predict only its size and membership behavior—not a display order. After execution, inspect the variables in your notebook and explain in one sentence why each used structure fits its task.

Keep one intentionally invalid line as a comment:

# model_input_fields.append("region")

You will not run it yet. Reading it should remind you that the tuple represents a fixed specification; if the specification needs regular edits, it should have been a list.


Key takeaways

Lists, tuples, sets, and dictionaries all store multiple values, but they communicate different requirements:

  • Use a list for an ordered, editable sequence where repeats can matter.
  • Use a tuple for an ordered grouping intended to remain fixed.
  • Use a set for unique values and membership checks where position does not matter.
  • Use a dictionary for named or ID-based lookup through key-value pairs.

The strongest habit is to select a structure from the task’s meaning rather than its appearance. Ask whether you need named lookup, uniqueness, position, duplicates, and mutation.

Next, you will use Boolean expressions such as region in valid_regions to write conditional statements that choose one correct action among mutually exclusive cases.

Can't find a good explanation? Sign up and we'll make it for you

Sign up