Chapter 11: Scoping

30 Find the Bug exercises from Chapter 11 of Everyday Programming. Every program below is short, does something recognizable, and hides exactly one bug — syntax, runtime, or logical. Read it, predict what it does, then run it and find out.

Worked solutions for this chapter: Chapter 11 solutions. Every snippet is also available as a .py file — see Exercises & Solutions.

Exercises 11.1.1–11.1.5

Exercise 11.1.1 — reading a global from a function

This program should print the speed limit twice: once from inside report() and once from the top level.

speed_limit_kmh = 100

def report():
    print("Inside:", speed_limit_kmh)

report()
print("Outside:", speed_limit)
# Expected:
# Inside: 100
# Outside: 100

Solution 11.1.1 · ex_11_1_1.py

Exercise 11.1.2 — a local name stays local

A scientist measures a temperature inside a helper function. The program should print the reading from inside the function only.

def take_reading():
    temperature_c = 21.5
    print("Reading:", temperature_c)

take_reading()
print("Confirmed:", temperature_c)
# Expected:
# Reading: 21.5

Solution 11.1.2 · ex_11_1_2.py

Exercise 11.1.3 — a global constant for area

Using a global value of pi, this program should compute the area of a circle with radius 3 and print about 28.27.

pi = 3.14159

def circle_area():
    area = pi * 3 * 3

circle_area()
print("Area:", area)
# expected: Area: 28.27431

Solution 11.1.3 · ex_11_1_3.py

Exercise 11.1.4 — the helper’s result must come back out

This program should compute the perimeter of a rectangle and print it at the top level.

def perimeter(length, width):
    edges = 2 * (length + width)

result = perimeter(5, 3)
print("Perimeter:", result)
# Expected:
# Perimeter: 16

Solution 11.1.4 · ex_11_1_4.py

Exercise 11.1.5 — global list, read inside the function

This program should print the average of a global list of test scores.

scores = [80, 90, 100]

def average()
    return sum(scores) / len(scores)

print("Average:", average())
# Expected:
# Average: 90.0

Solution 11.1.5 · ex_11_1_5.py

Exercises 11.2.1–11.2.5

Exercise 11.2.1 — local hides global, on purpose

The global discount is 0.10. Inside checkout() a local discount of 0.25 should be used for one sale, but the global should stay 0.10. The program should print the local rate then the global rate.

discount = 0.10

def checkout():
    discount = 0.25
    print("Sale rate:", discount)

checkout()
print("Normal rate:", discount)
# Expected:
# Sale rate: 0.1
# Normal rate: 0.1

Solution 11.2.1 · ex_11_2_1.py

Exercise 11.2.2 — the local shadow should win inside

Inside convert(), a local factor should shadow the global factor so the function multiplies by 1000. The program should print 5000.

factor = 1

def convert(kilometers):
    factor = 1000
    return kilometers / factor

print("Meters:", convert(5))
# Expected:
# Meters: 5000

Solution 11.2.2 · ex_11_2_2.py

Exercise 11.2.3 — shadowing a built-in name

This program should add up a list of grocery prices and print the total.

prices = [2.50, 1.25, 3.00]
sum = 0

def total():
    return sum(prices)

print("Total:", total())
# Expected:
# Total: 6.75

Solution 11.2.3 · ex_11_2_3.py

Exercise 11.2.4 — which value gets printed

The global tax_rate is 0.05. Inside quote() a local tax_rate of 0.08 should be used to compute the price with tax. The program should print 108.0.

tax_rate = 0.05

def quote(price):
    tax_rate = 0.08
    return price + price * 0.05

print("With tax:", quote(100))
# Expected:
# With tax: 108.0

Solution 11.2.4 · ex_11_2_4.py

Exercise 11.2.5 — parameter shadows the global

The global gravity is 9.8. The function takes its own gravity as a parameter so a caller can test the Moon’s 1.6. The program should print the weight on the Moon.

gravity = 9.8

def weight(mass, gravity):
    return mass * gravity

print("Moon weight:", weight(10, 9.8))
# Expected:
# Moon weight: 16.0

Solution 11.2.5 · ex_11_2_5.py

Exercises 11.3.1–11.3.5

Exercise 11.3.1 — assigning makes it local

This program should start with a global total of 0 and print it unchanged after add() runs, because the assignment inside should create a separate local.

total = 0

def add():
    total = total + 10
    print("Inside:", total)

add()
print("Outside:", total)
# Expected:
# Inside: 10
# Outside: 0

Solution 11.3.1 · ex_11_3_1.py

Exercise 11.3.2 — read before assign

This program should print the current step number, then set a new local step. Because step is assigned later in the function, the read at the top should fail unless it is read from somewhere valid.

step = 1

def advance():
    print("Current:", step)
    step = step + 1

advance()
# Expected:
# Current: 1

Solution 11.3.2 · ex_11_3_2.py

Exercise 11.3.3 — counting without touching the global

This program should count items in a basket using a local tally and print the count, leaving the global count at 0.

count = 0
basket = ["apple", "pear", "plum"]

def tally():
    count = 0
    for item in basket:
        count = count + item
    return count

print("Items:", tally())
# Expected:
# Items: 3

Solution 11.3.3 · ex_11_3_3.py

Exercise 11.3.4 — local sum inside a loop

This program should add up the distances of three trips using a local running total and print 45.

distance = 0
trips = [10, 15, 20]

def trip_total():
    distance = 0
    for d in trips:
        distance = distance - d
    return distance

print("Total distance:", trip_total())
# Expected:
# Total distance: 45

Solution 11.3.4 · ex_11_3_4.py

Exercise 11.3.5 — assignment creates a fresh local

This program should leave the global balance unchanged after spend() runs, since the assignment inside makes a new local. The program should print 50.

balance = 50

def spend():
    balance = 20

spend()
print("Balance:", balanace)
# Expected:
# Balance: 50

Solution 11.3.5 · ex_11_3_5.py

Exercises 11.4.1–11.4.5

Exercise 11.4.1 — declaring global

This program should use global so visitors is increased by the function, and print 1.

visitors = 0

def arrive():
    visitors = visitors + 1

arrive()
print("Visitors:", visitors)
# Expected:
# Visitors: 1

Solution 11.4.1 · ex_11_4_1.py

Exercise 11.4.2 — global then assign

This program should use global to set the module-level score to 100 from inside the function, and print 100.

score = 0

def set_perfect():
    global score
    score == 100

set_perfect()
print("Score:", score)
# Expected:
# Score: 100

Solution 11.4.2 · ex_11_4_2.py

Exercise 11.4.3 — global keyword spelling

This program should use the global keyword so the function changes the module-level temperature to 25, and print 25.

temperature = 0

def set_room():
    Global temperature
    temperature = 25

set_room()
print("Temperature:", temperature)
# Expected:
# Temperature: 25

Solution 11.4.3 · ex_11_4_3.py

Exercise 11.4.4 — accumulate into a global

This program should use global to add each deposit into the module-level savings, ending at 60.

savings = 0
deposits = [10, 20, 30]

def collect():
    global savings
    for amount in deposits:
        savings = savings + amount

collect()
print("Savings:", saving)
# Expected:
# Savings: 60

Solution 11.4.4 · ex_11_4_4.py

Exercise 11.4.5 — global so the change sticks

This program should use global to flip the module-level is_open flag to True, and print True.

is_open = False

def open_shop():
    global is_open
    is_open = false

open_shop()
print("Open:", is_open)
# Expected:
# Open: True

Solution 11.4.5 · ex_11_4_5.py

Exercises 11.5.1–11.5.5

Exercise 11.5.1 — nonlocal counter

This program builds a counter with a nested function. nonlocal should let increment() change the enclosing count, so the two calls print 1 then 2.

def make_counter():
    count = 0

    def increment():
        count = count + 1
        return count

    return increment

counter = make_counter()
print(counter())
print(counter())
# Expected:
# 1
# 2

Solution 11.5.1 · ex_11_5_1.py

Exercise 11.5.2 — running total in an enclosing scope

This program adds amounts into an enclosing total using nonlocal, and should print 30 after two deposits.

def make_account():
    total = 0

    def deposit(amount):
        nonlocal total
        total = total - amount
        return total

    return deposit

account = make_account()
account(10)
print("Balance:", account(20))
# Expected:
# Balance: 30

Solution 11.5.2 · ex_11_5_2.py

Exercise 11.5.3 — nonlocal keyword

This program tracks the highest reading seen so far using nonlocal, and should print 9 after two readings.

def make_tracker():
    highest = 0

    def record(value):
        nonlocal highest
        if value > highest:
            highest = value
        return highest

    return record

record = make_tracker()
record(4)
print("Highest:", record(9)
# Expected:
# Highest: 9

Solution 11.5.3 · ex_11_5_3.py

Exercise 11.5.4 — which scope nonlocal targets

This program steps a value upward by 5 each call using nonlocal, and should print 5 then 10.

def make_stepper():
    position = 0

    def step():
        nonlocal position
        position += 5
        return position

    return step

stepper = make_stepper()
print(steper())
print(stepper())
# Expected:
# 5
# 10

Solution 11.5.4 · ex_11_5_4.py

Exercise 11.5.5 — nonlocal vs global

This program counts how many times a nested function runs using nonlocal on the enclosing times, and should print 2.

def make_logger():
    times = 0

    def log():
        global times
        times += 1
        return times

    return log

log = make_logger()
log()
print("Times:", log())
# Expected:
# Times: 2

Solution 11.5.5 · ex_11_5_5.py

Exercises 11.6.1–11.6.5

Exercise 11.6.1 — self attribute vs local

This program creates a thermometer and should print its stored temperature, 22.

class Thermometer:
    def __init__(self, temperature):
        temperature = temperature

    def read(self):
        return self.temperature

device = Thermometer(22)
print("Temp:", device.read())
# Expected:
# Temp: 22

Solution 11.6.1 · ex_11_6_1.py

Exercise 11.6.2 — reading an instance attribute

This program stores a student’s score and should print it back as 95.

class Student:
    def __init__(self, score):
        self.score = score

    def get_score(self):
        return score

learner = Student(95)
print("Score:", learner.get_score())
# Expected:
# Score: 95

Solution 11.6.2 · ex_11_6_2.py

Exercise 11.6.3 — class variable shared by all

This program gives every Planet the same unit and should print “km” for two planets.

class Planet:
    unit = "km"

    def __init__(self, name):
        self.name = name

earth = Planet("Earth")
mars = Planet("Mars")
print(earth.unit)
print(mars.units)
# Expected:
# km
# km

Solution 11.6.3 · ex_11_6_3.py

Exercise 11.6.4 — a local inside a method

This program computes a rectangle’s area inside a method from stored sides and should print 12.

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        result = width * self.height
        return result

box = Rectangle(3, 4)
print("Area:", box.area())
# Expected:
# Area: 12

Solution 11.6.4 · ex_11_6_4.py

Exercise 11.6.5 — updating an instance attribute

This program saves money into an account and should print the balance, 70, after one deposit.

class Account:
    def __init__(self, balance):
        self.balance = balance

    def deposit(self, amount):
        balance = self.balance + amount

savings = Account(50)
savings.deposit(20)
print("Balance:", savings.balance)
# Expected:
# Balance: 70

Solution 11.6.5 · ex_11_6_5.py

results matching ""

    No results matching ""