Lab

12.3.2. Lab#

  • Use this lab to practice the chapter’s coding skills in runnable Python code.

  • Sign in from the account menu before you start working on the lab.

  • Launch Live Code (the rocket) to write and run code in the coding cells.

  • Multiple submissions are allowed. The highest score is kept.

### Question 1: Build a Query String
# Build the query string for a search request without using requests
# or any network call; use plain string and dict manipulation.
# Write a function url_encode(value) that converts value to a string
# and replaces spaces with %20.
# This simplified encoder only handles spaces; real URL encoding (urllib.parse.quote or requests' params=) also escapes characters such as &, =, and #.
# Build query_string by joining 'key=value' pairs from params with '&',
# url-encoding each value.
# Combine base_url, '?', and query_string into full_url and print it:
# https://api.example.test/search?q=python%20generators&page=3&limit=10
base_url = "https://api.example.test/search"
params = {"q": "python generators", "page": 3, "limit": 10}
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
base_url = "https://api.example.test/search"
params = {"q": "python generators", "page": 3, "limit": 10}

def url_encode(value):
    return str(value).replace(" ", "%20")

query_parts = [f"{key}={url_encode(value)}" for key, value in params.items()]
query_string = "&".join(query_parts)
full_url = f"{base_url}?{query_string}"
print(full_url)
https://api.example.test/search?q=python%20generators&page=3&limit=10
### Question 2: Safe Nested JSON Traversal
# payload represents a pre-fetched API response (a plain dict).
# Write a function get_city(payload) that safely returns
# payload["user"]["address"]["city"], using .get() chains with
# default {} for missing dicts and default "unknown" for the city,
# so it never raises KeyError even when fields are missing.
# Call it on payload, then on {'user': {}}, and print exactly:
# Austin
# unknown
payload = {
    "user": {
        "id": 55,
        "address": {"city": "Austin", "zip": "78701"},
    },
}
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
payload = {
    "user": {
        "id": 55,
        "address": {"city": "Austin", "zip": "78701"},
    },
}

def get_city(payload):
    return payload.get("user", {}).get("address", {}).get("city", "unknown")

print(get_city(payload))
print(get_city({"user": {}}))
Austin
unknown
### Question 3: Summarize a Response Payload
# order_payload represents a pre-fetched order response.
# Write a function summarize_order(payload) that returns a dict with:
# - "order_id": payload["order_id"]
# - "total": the sum of each item's "price", minus payload.get("discount", 0),
#   rounded to 2 decimal places
# - "item_count": the number of items
# Note: payload may not include a discount key -- default it to 0.
# Call summarize_order(order_payload) and print exactly:
# {'order_id': 4821, 'total': 21.25, 'item_count': 2}
order_payload = {
    "order_id": 4821,
    "items": [{"name": "notebook", "price": 12.5}, {"name": "pen", "price": 8.75}],
}
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
order_payload = {
    "order_id": 4821,
    "items": [{"name": "notebook", "price": 12.5}, {"name": "pen", "price": 8.75}],
}

def summarize_order(payload):
    total = sum(item["price"] for item in payload.get("items", []))
    discount = payload.get("discount", 0)
    return {
        "order_id": payload["order_id"],
        "total": round(total - discount, 2),
        "item_count": len(payload.get("items", [])),
    }

print(summarize_order(order_payload))
{'order_id': 4821, 'total': 21.25, 'item_count': 2}
### Question 4: Simulate Pagination
# pages simulates paginated API responses already fetched into memory:
# a list of page dicts, each with 'items' and a 'next' index (or None
# on the last page -- the sentinel that stops pagination).
# Write a function fetch_all(pages) that starts at index 0, collects
# every page's 'items' into one list, and follows 'next' until it
# equals None. Return the combined list.
# Call fetch_all(pages) and print exactly:
# ['alpha', 'beta', 'gamma', 'delta', 'epsilon']
pages = [
    {"items": ["alpha", "beta"], "next": 1},
    {"items": ["gamma"], "next": 2},
    {"items": ["delta", "epsilon"], "next": None},
]
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
pages = [
    {"items": ["alpha", "beta"], "next": 1},
    {"items": ["gamma"], "next": 2},
    {"items": ["delta", "epsilon"], "next": None},
]

def fetch_all(pages):
    collected = []
    index = 0
    while index is not None:
        page = pages[index]
        collected.extend(page["items"])
        index = page["next"]
    return collected

print(fetch_all(pages))
['alpha', 'beta', 'gamma', 'delta', 'epsilon']
### Question 5: Parse and Re-serialize a JSON Payload
# raw_response simulates a JSON string already received from an API
# (no network call -- it is just a string literal here).
# Use json.loads to parse it into parsed.
# Write a function get_result_names(parsed) that returns a list of each
# result's "name", using .get("name", "unnamed") as a safe default.
# Build summary as a JSON string (json.dumps) of a dict with
# "status" (default "unknown" if missing) and "count" (len(names)).
# Print names, then print summary, exactly:
# ['Alpha', 'Beta']
# {"status": "ok", "count": 2}
import json

raw_response = '{"status": "ok", "results": [{"id": 1, "name": "Alpha"}, {"id": 2, "name": "Beta"}]}'
parsed = json.loads(raw_response)
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
import json

raw_response = '{"status": "ok", "results": [{"id": 1, "name": "Alpha"}, {"id": 2, "name": "Beta"}]}'
parsed = json.loads(raw_response)

def get_result_names(parsed):
    return [item.get("name", "unnamed") for item in parsed.get("results", [])]

names = get_result_names(parsed)
summary = json.dumps({"status": parsed.get("status", "unknown"), "count": len(names)})
print(names)
print(summary)
['Alpha', 'Beta']
{"status": "ok", "count": 2}