EE1021 Lecture 7 Worksheet — Classes, Objects, and Methods
Instructions
- Predict object state before running code.
- Keep the supplied public class and method names unchanged.
- Store persistent instance state on
self. - Do not request user input or print inside reusable methods.
- Test at least two instances to detect accidental shared state.
- Complete the eight core tasks before the optional extension.
1. Identify the OOP Vocabulary
Given:
class Sensor:
def add_reading(self, value):
self.readings.append(value)
t1 = Sensor()
t1.readings = []
t1.add_reading(23.5)Identify the class, instance, data attribute, method, receiver object, and argument.
2. Convert Requirements into a Class Contract
A sensor has an identifier, measurement unit, and reading history. It can add a reading, report its latest reading, calculate its average, and produce a readable description.
In Python the constructor is the __init__ method; it runs automatically when an object is created.
List:
- constructor parameters;
- instance attributes;
- state-changing methods;
- query methods;
- special methods;
- empty-data behavior.
3. Initialize Independent State
Implement:
class Sensor:
def __init__(self, sensor_id, unit):
...Raise ValueError when either text argument is empty. Create a new readings list for every object.
Verify:
t1 = Sensor("T1", "C")
p1 = Sensor("P1", "kPa")
assert t1.readings is not p1.readings4. Trace self
Predict the final state without running:
t1.add_reading(20.0)
p1.add_reading(100.0)
t1.add_reading(22.0)For each call, identify which object becomes self and which list changes.
5. Implement Commands and Queries
Implement:
add_reading(value)
reading_count()
latest()
average()add_reading raises TypeError("reading must be numeric") for a nonnumeric value. latest and average raise ValueError("sensor has no readings") when empty.
Classify each method as state-changing or state-reporting.
6. Implement Status Boundaries
Implement:
status(low, high)Use the latest reading:
- below
low→"low"; - above
high→"high"; - otherwise →
"normal".
Raise ValueError("low must not exceed high") when low > high. Test values below, at, between, and above the boundaries.
7. Implement __str__
Return this exact format:
T1: 2 readings (C)
Explain why printing inside __str__ would violate its contract.
8. Engineering Mini-Problem: Resistor
Implement:
class Resistor:
"""Represent one resistor with a positive resistance."""Contract:
- constructor receives
labelandresistance_ohm; - nonpositive resistance raises
ValueError; current(voltage)returnsvoltage / resistance_ohm;power(voltage)returnsvoltage**2 / resistance_ohm;__str__returns"R1: 220 ohm"forResistor("R1", 220).
Create two resistors and verify that their state and calculations are independent.
Optional Extension: Load Sensor Data
Read sensor_test_data.txt, create one Sensor per identifier, and add each parsed reading to the correct object. Use a dictionary that maps sensor IDs to Sensor objects.
Do not add inheritance or class variables; those begin in Lecture 8.
Submission Checklist
- OOP vocabulary is used accurately.
- Constructor data is stored on
self. - Mutable state is independent for every instance.
- Commands change state and queries return values.
__str__returns rather than prints.- Empty and invalid inputs follow documented contracts.
- Two-instance and boundary tests pass.
- The
Resistorclass is complete.