Copying Objects · Exercises
Beginner

Copying Objects Exercises

4 exercises that build on the Copying Lists and Dicts lesson, from easy to hard. Each one is checked in your browser when you press Check. Stuck? Use the hint before peeking at the solution.

What this lesson covers: Assigning a list or dict to another name does not copy it, it only adds a second name for the same object; a shallow copy builds a new outer container that still shares the inner objects, and copy.deepcopy duplicates everything all the way down. By the end you can tell an alias from a copy with is and ==, make shallow copies in several ways, explain why nested data is still shared, use copy.deepcopy when you need a fully independent clone, and avoid aliasing bugs with function arguments and default values. You will practise: Take a snapshot; Predict the shared rows; Fix the task list; Discount without touching the original.

0 / 4 completed

Copying Objects practice exercises

1. Take a snapshot

Write code Easy

Write snapshot(items) that returns a new list or dict with the same contents as items, so that later changes to the original do not show up in the snapshot. It must work for both lists and dicts.

Your code
def snapshot(items):
    # return an independent copy of the list or dict
    pass

cart = ["milk", "eggs"]
saved = snapshot(cart)
cart.append("bread")
print(saved)

2. Predict the shared rows

Predict the output Medium

Read the code and type exactly what it prints. Think about which rows are shared and which were replaced.

Read this code
rows = [[1, 2], [3, 4]]
twin = rows[:]
deep = [row[:] for row in rows]
twin[0][0] = 99
twin[1] = [7, 7]
print(rows)
print(twin)
print(deep)
print(rows[0] is twin[0], rows[1] is twin[1])

3. Fix the task list

Fix the bug Medium

add_task(task, tasks=...) adds a task to a list and returns it. The program should print ['email'] and then ['call'], but both lines show ['email', 'call']. Fix the function. When the caller passes a list in, it must still add the task to that list and return it.

Your code
def add_task(task, tasks=[]):
    tasks.append(task)
    return tasks

today = add_task("email")
tomorrow = add_task("call")
print(today)
print(tomorrow)

4. Discount without touching the original

Write code Hard

Write apply_discount(order, percent) for an order dict with a nested "customer" dict and a list of item dicts under "items". It must return a new order in which every item's "price" is reduced by percent percent and rounded to 2 decimals. Every other field is kept.

The original order must not change, and the returned order must not share any inner list or dict with it (changing the new customer dict must not affect the original). The module copy is already imported.

Your code
import copy

def apply_discount(order, percent):
    # return a new order with every item price reduced by percent
    pass

order = {
    "id": 7,
    "customer": {"name": "Asha", "city": "Pune"},
    "items": [{"name": "lamp", "price": 20.0}, {"name": "mug", "price": 8.5}],
}
sale = apply_discount(order, 10)
print(sale["items"])
print(order["items"])

Next lessonPython collections Module

More Copying Lists and Dicts examples · All Python exercises