Concepts / Aliasing and References in Python

Aliasing and References in Python

Lists are mutable and the default choice for most tasks; tuples are immutable and solve specific problems.

  • Programming
Interactive lab

Try it: Names and Objects

How Python variables are names bound to objects: assignment never copies, mutating a list is seen through every name that points at it, and ints are replaced rather than changed.

How it works

  1. name = object binds a name; b = a makes b point at the same object.
  2. Mutating a list (append, +=) changes the one shared object.
  3. a = a + [x] and y = y + 1 create NEW objects and re-point one name.
  4. Passing a list to a function passes the reference, so the function can change it.

Default run (7 steps): Two names, one list. Every name is a label that points at an object. … Printed: [1, 2, 3] / True

Simplified: Six fixed scripts on a tiny heap; you choose the values. Object numbers are illustrative, not real id() values.

Educational simulation

Loading the simulation…

The Shared-Collection Problem

Lists and tuples both hold ordered collections of related values, but they support different programming decisions. A list is mutable, so its elements can be added, removed, or changed after creation. A tuple is immutable, so its contents are fixed. The important question is not which type is universally better. The question is whether later code should be allowed to change the collection.

Aliasing becomes important when more than one variable name refers to the same mutable list. If the list is changed through one name, code using another name can observe the changed collection. This flexibility is useful when shared updates are intentional, but it can also create aliasing bugs when a function or part of a program changes data unexpectedly.

refers torefers tofirst_nameMutable listshared collectionsecond_name
What happens when two variable names refer to the same mutable list and one name changes it?

Tracing a Mutation

What do you think happens?

Suppose two names refer to one mutable list. If the list is changed through the first name, what should the second name observe?

  • The second name observes the changed list
  • The second name keeps an independent unchanged list
  • The operation is impossible because lists cannot change
Reveal answer

Answer: The second name observes the changed list.

Both names refer to the same mutable list in this example. Mutating that shared collection changes the state visible through either name.

A Shared List After an Update

Two parts of a program use the same list of tasks. One part adds a new task. What should the other part see?

Initial state: Both names refer to the same mutable collection of tasks.

Mutation: The first part adds an item to the list. Adding an item is one of the changes that lists support after creation.

Observation: The second part sees the added item because it also refers to that shared list.

Design check: This behavior is appropriate when both parts are meant to share updates. It is a liability when the second part was expected to receive protected, unchangeable data.

Use a mutable list when shared changes are intentional; avoid exposing shared mutable state when accidental changes would be difficult to debug.

same shared listsame shared listfirst_nameitems A, Bfirst_nameitems A, B, Csecond_nameitems A, Bsecond_nameitems A, B, C
What changes when one reference mutates a shared list, and which references observe the result?

When Lists Fit

Lists are the default choice for most tasks because they are flexible. Choose a list when a collection must grow, shrink, or have individual elements changed after creation. The source material identifies building a collection of user inputs, accumulating results in a loop, filtering data, and sorting in place as situations where list mutability is useful.

Task constraintBetter sequence choiceReason
The collection must grow or shrinkListLists can have elements added or removed after creation.
Elements must be changed during processingListLists allow elements to be changed after creation.
The collection should remain fixedTupleTuples are immutable.
The collection must be used as a dictionary keyTupleDictionaries require immutable keys.
A function should not modify the original dataTuplePassing a tuple guarantees that the function cannot modify the original data.

Three Reasons to Choose Tuples

Tuples are not merely lists with a different appearance. Their immutability solves three specific problems. First, tuples must be used as dictionary keys because dictionaries require immutable keys. Second, tuples provide cleaner syntax for returning multiple values from a function. Third, passing a tuple to a function guarantees that the function cannot modify the original data, which prevents a class of aliasing bugs.

Matching the Type to the Constraint

Select a list or tuple for each situation: a fixed group of related values, a collection that must accept new items, a dictionary key, a function input that must not be modified, and a function result containing multiple values.

Fixed group: Choose a tuple because the group is not intended to change.

Growing collection: Choose a list because the task requires adding items.

Dictionary key: Choose a tuple because dictionary keys must be immutable.

Protected function input: Choose a tuple because the called function cannot modify the original tuple data.

Multiple returned values: Choose a tuple when the fixed group of returned values benefits from tuple return syntax.

Tuples are preferable when fixed structure, dictionary-key use, clean multi-value returns, or protection against modification is the important constraint. Lists are preferable when the collection must change.

supportssupportsListmutable; can changeGrowing collectionTupleimmutable; fixedDictionary key
Which sequence communicates flexibility, and which communicates a fixed protected collection?

Selecting Under Constraints

evaluateyesnoyesno, if key or protected input is requiredSequence taskMust change?add, remove, or changeitemsListmutable and flexibleMust stay fixed?protect from modificationTupleimmutable
How should mutation, fixed structure, safe sharing, and dictionary-key requirements guide the choice?
MEDIUM

For each task, choose list or tuple and explain the constraint that determines your choice: a collection of user inputs that will grow; a fixed group of related values; a dictionary key; a function input that must not be modified; and a collection that will be filtered and sorted in place.

Hints
  • Ask whether the collection must change after creation.
  • Remember that dictionary keys must be immutable.
  • A tuple can prevent a function from modifying the original data.
  • Choosing a list automatically for every ordered collection

    The collection can be changed even though the task does not require mutation, increasing the risk of aliasing bugs.

    Fix: Choose a tuple when immutability provides a real benefit.

  • Choosing a tuple when the task requires additions or removals

    Tuples are immutable and are not the appropriate tool for a collection that must change.

    Fix: Choose a list when the collection must grow, shrink, or have elements changed.

  • Trying to use a list as a dictionary key

    Dictionaries require immutable keys.

    Fix: Use a tuple for a dictionary key.

  • Ignoring shared mutable state

    Shared mutable data can lead to aliasing bugs.

    Fix: Pass a tuple when the function must be unable to modify the original data.

Deliberate Sequence Choices

  1. A list is mutable and is the default choice for most tasks.
  2. Aliasing occurs when multiple names refer to shared mutable data, so a mutation through one name can affect what another name observes.
  3. Choose a tuple when the collection should remain fixed or when a function must be unable to modify the original data.
  4. Tuples must be used as dictionary keys because dictionaries require immutable keys.
  5. Tuples also provide cleaner syntax for returning multiple values from a function.

Key Takeaways

  • Use a list when a collection must be added to, reduced, or changed.
  • Treat mutability as a liability when shared data should not be altered accidentally.
  • Use a tuple for fixed data, dictionary keys, protected function inputs, and clean multiple-value returns.
  • Make the sequence choice from the task's constraints rather than choosing by habit.