Exercises#
This page contains four take-home exercises that reinforce the concepts from Lecture 6. Each exercise asks you to write code from scratch based on a specification – no starter code is provided.
All files should be created inside your lecture6/ workspace folder.
Exercise 1 – Building a Robot Class
Goal
Demonstrate your understanding of class definitions, the __init__
constructor, the self parameter, instance attributes, and class
attributes.
Specification
Create a file lecture6/robot_basics.py that implements the
following. Each class and method must include type hints and a
Google-style docstring.
``Robot`` class with:
__init__(self, name: str, battery: int = 100)Instance attributes:
name,battery,tasks_completed(default0)A class attribute
total_robotsthat tracks how many Robot instances have been created. Increment it in__init__.
``perform_task(self, task_name: str) -> None`` method that:
If
battery >= 10: prints"<name> performing: <task_name>", decreases battery by 10, and incrementstasks_completed.Otherwise: prints
"<name> needs recharging!".
``recharge(self) -> None`` method that sets battery back to 100 and prints
"<name> fully recharged!".In the
if __name__ == "__main__"block:Create two Robot instances.
Have each robot perform several tasks.
Print each robot’s
tasks_completedandbatteryafter the tasks.Print
Robot.total_robots.
if __name__ == '__main__':
# Create two Robot instances
robot1 = Robot("Atlas")
robot2 = Robot("Spot", 50)
# Have them perform several tasks
robot1.perform_task("welding")
robot1.perform_task("painting")
robot1.perform_task("inspection")
robot2.perform_task("delivery")
robot2.perform_task("sorting")
robot2.perform_task("scanning")
robot2.perform_task("lifting")
robot2.perform_task("packing")
robot2.perform_task("cleaning") # battery hits 0 after this
# This one should trigger the recharge warning
robot2.perform_task("assembly")
# Recharge and continue
robot2.recharge()
robot2.perform_task("assembly")
# Print final state
print(f"\n{robot1.name}: tasks={robot1.tasks_completed}, battery={robot1.battery}")
print(f"{robot2.name}: tasks={robot2.tasks_completed}, battery={robot2.battery}")
print(f"Total robots created: {Robot.total_robots}")
Expected output:
Atlas performing: welding
Atlas performing: painting
Atlas performing: inspection
Spot performing: delivery
Spot performing: sorting
Spot performing: scanning
Spot performing: lifting
Spot performing: packing
Spot performing: cleaning
Spot needs recharging!
Spot fully recharged!
Spot performing: assembly
Atlas: tasks=3, battery=70
Spot: tasks=6, battery=90
Total robots created: 2
Deliverables
lecture6/robot_basics.pyThe program must run without errors and produce output matching the expected format above.
Exercise 2 – Dunder Methods for a Robot Class
Goal
Practice implementing dunder methods for string representations,
comparison operators, arithmetic operators, and the __len__
protocol.
Specification
Create a file lecture6/robot_dunders.py that implements the
following. Each class and method must include type hints and a
Google-style docstring.
``Robot`` class with:
__init__(self, name: str, battery: int = 100)Instance attributes:
name,battery,tasks_completed(default0)
String representations:
__str__returns"<name> [<battery>%]"__repr__returns"Robot('<name>', <battery>)"
Comparison operators:
__eq__so two robots are equal if their battery levels are equal (regardless of name). ReturnNotImplementedfor non-Robot types.__gt__so robots can be compared by battery level. ReturnNotImplementedfor non-Robot types.
Arithmetic operator:
__add__so adding two Robots returns a new Robot with name"merged"and the sum of their batteries capped at 100.
Length protocol:
__len__returnstasks_completed.
In the
if __name__ == "__main__"block, test all dunder methods:
if __name__ == "__main__":
scout = Robot("Scout", 60)
hauler = Robot("Hauler", 60)
# __str__: human-readable output
print(scout) # Scout [60%]
# __repr__: developer output, looks like valid Python
print(repr(scout)) # Robot('Scout', 60)
# __eq__: compare by battery level
print(scout == hauler) # True (both have battery 60)
print(scout == Robot("X", 90)) # False (different battery)
# __add__: merge two robots, battery capped at 100
print(scout + hauler) # merged [100%] (60 + 60 = 120, capped to 100)
print(scout + Robot("X", 20)) # merged [80%] (60 + 20 = 80, no cap needed)
# __gt__: compare by battery level
print(scout > Robot("X", 40)) # True (60 > 40)
print(scout > hauler) # False (60 > 60 is False)
# __len__: number of tasks completed
scout.tasks_completed = 3
print(len(scout)) # 3
print(len(hauler)) # 0 (default, no tasks performed yet)
Expected output:
Scout [60%]
Robot('Scout', 60)
True
False
merged [100%]
merged [80%]
True
False
3
0
Deliverables
lecture6/robot_dunders.pyThe program must run without errors and produce output matching the expected format above.
Exercise 3 – Encapsulated Sensor
Goal
Practice encapsulation with non-public attributes, @property
decorators, read-only properties, and setter validation.
Specification
Create a file lecture6/sensor_encapsulated.py that implements the
following. Each class and method must include type hints and a
Google-style docstring.
``Sensor`` class with:
__init__(self, sensor_type: str, range_m: float = 10.0)Non-public attributes:
_sensor_type,_range_m
Read-only property
sensor_typethat cannot be changed after creation. The setter should raiseAttributeError.Property
range_mwith a setter that:Raises
ValueErrorifrange_mis set to a negative number.Raises
TypeErrorifrange_mis notintorfloat.
Methods:
calibrate(offset: float) -> Noneadjusts_range_mby the given offset.read() -> floatreturns_range_mwith simulated noise (e.g., multiply by a random factor between 0.95 and 1.05).
``__str__`` returns
"Sensor(<type>): range=<range_m>m".In the
if __name__ == "__main__"block:
if __name__ == "__main__":
lidar = Sensor("lidar", 50.0)
print(lidar) # Sensor(lidar): range=50.0m
lidar.calibrate(2.5)
print(lidar) # Sensor(lidar): range=52.5m
lidar.calibrate(-5.0)
print(lidar) # Sensor(lidar): range=47.5m
Expected output:
Sensor(lidar): range=50.0m
Sensor(lidar): range=52.5m
Sensor(lidar): range=47.5m
Deliverables
lecture6/sensor_encapsulated.pyThe program must run without errors and produce output matching the expected format above.
Exercise 4 – Robot with Sensor Suite
Goal
Combine classes, dunder methods, and encapsulation into a system where
a Robot manages a collection of Sensor objects. This exercise
ties together all concepts from the lecture.
Specification
Create a file lecture6/robot_with_sensors.py that implements the
following. Every class and method must have type hints and a
Google-style docstring.
``Sensor`` class with:
Non-public attributes:
_sensor_type,_range_m,_accuracyProperties for
range_m(validated: must be positive) andsensor_type(read-only)__str__and__repr____gt__comparing byrange_m__add__that returns a new Sensor with type"fused", summed ranges, and averaged accuracies
``Robot`` class with:
Non-public attributes:
_name,_battery,_sensors(list)Properties for
battery(validated 0–100) andname(read-only)add_sensor(sensor: Sensor) -> Nonemethod__contains__to check if a sensor type is in the robot__iter__to iterate over the robot’s sensors__len__to get number of sensors
In the
if __name__ == "__main__"block:Create a Robot, add multiple sensors.
Iterate over sensors and print each one.
Check membership (e.g.,
"lidar" in robot).Fuse two sensors with
+and print the result.
Expected output:
=== Robot Sensors ===
Scout has 3 sensors:
Sensor(lidar): range=50.0m
Sensor(camera): range=30.0m
Sensor(ultrasonic): range=10.0m
=== Membership ===
Has lidar: True
Has radar: False
=== Sensor Fusion ===
Fused: Sensor(fused): range=80.0m
Deliverables
lecture6/robot_with_sensors.pyThe program must run without errors and produce output matching the expected format above.
All calculations must be computed dynamically (no hard-coded results).
Every class and method must include type hints and a Google-style docstring.