EE1021 Programming for Engineers · Lecture 3 · 2026–2027
returnmath module, and a simple custom moduleraw_voltage_1 = 4.92
calibrated_1 = raw_voltage_1 + 0.05
print("Calibrated:", calibrated_1)
raw_voltage_2 = 5.08
calibrated_2 = raw_voltage_2 + 0.05
print("Calibrated:", calibrated_2)Identify the repeated calculation. What information changes each time?
The calibration rule repeats; only the raw voltage changes. A function lets us name the rule and reuse it.
The function separates the rule from the values used with it.
def calibrate_voltage(raw_voltage):
"""Return a calibrated voltage."""
calibrated = raw_voltage + 0.05
return calibrated| Part | Example | Job |
|---|---|---|
| keyword | def |
begins a function definition |
| name | calibrate_voltage |
identifies the function |
| parameter | raw_voltage |
receives data from the caller |
| docstring | """...""" |
explains the function’s purpose |
| body | indented lines | performs the work |
| return value | calibrated |
sends a result back |
After Python reads the definition, nothing has been calibrated yet.
The call enters the body, binds raw_voltage to 4.92, and produces 4.97.
| Term | In the example |
|---|---|
| parameters | length, width in the definition |
| arguments | 5, 3 in the call |
| returned result | 15, assigned to area |
Arguments are matched to parameters from left to right unless names are used explicitly.
def scale_reading(reading, factor):
return reading * factor
a = scale_reading(4, 2)
b = scale_reading(a, 0.5)
print(a, b)Predict:
reading and factor in each call?Check: first call: 4 and 2; second call: 8 and 0.5; output: 8 4.0.
return Sends Data to the Callerdef celsius_to_fahrenheit(celsius):
fahrenheit = celsius * 9 / 5 + 32
return fahrenheit
converted = celsius_to_fahrenheit(25)
print("Fahrenheit:", converted)The call expression celsius_to_fahrenheit(25) becomes the returned value 77.0.
Returned values can be:
return and print Have Different JobsReturn a value
answer becomes 10.
return also ends the current function call; code after the executed return does not run.
| Moment | caller reading |
local reading |
adjusted |
|---|---|---|---|
| before call | 1.5 | — | — |
| function starts | 1.5 | 1.5 | — |
| local update | 1.5 | 1.7 | — |
| after return | 1.5 | gone | 1.7 |
The parameter is a local name. Rebinding it does not rebind the caller’s variable.
def increase(count):
count = count + 1
print("inside:", count)
return count
count = 3
new_count = increase(count)
print("outside:", count, new_count)Predict both printed lines before running the program.
Check: inside: 4, then outside: 3 4. The two names belong to different scopes.
def voltage_status(voltage):
"""Return a status for a 5 V supply."""
if voltage < 0:
return "Invalid"
if voltage < 4.75:
return "Low"
if voltage <= 5.25:
return "Normal"
return "High"Each call follows one path and executes one return.
The caller receives the string "Normal".
Predict the returned status for each call.
| Call | Your prediction |
|---|---|
voltage_status(-0.1) |
|
voltage_status(4.74) |
|
voltage_status(4.75) |
|
voltage_status(5.25) |
|
voltage_status(5.26) |
Check: Invalid (below 0) · Low (just below 4.75) · Normal (exactly 4.75: 4.75 < 4.75 is false) · Normal (exactly 5.25: 5.25 <= 5.25 is true) · High (just above 5.25).
Test each edge and one step either side: < versus <= mistakes hide there. Boundary tests check the specification, not just the syntax.
def sum_multiples(limit, divisor):
"""Return the sum of multiples up to and including limit."""
total = 0
for value in range(divisor, limit + 1, divisor):
total += value
return total
result = sum_multiples(12, 3)
print(result)Trace the accumulator: 0 → 3 → 9 → 18 → 30.
The function packages the Lecture 2 accumulate pattern behind a descriptive name.
raw = 4.72
calibrated = calibrate_voltage(raw, 0.05)
status = voltage_status(calibrated)
print(calibrated, status)calibrate_voltage() returns 4.77.voltage_status().Each function has one job; the main code shows the overall sequence.
def calibrate_voltage(raw_voltage, offset=0.05):
return raw_voltage + offset
standard = calibrate_voltage(4.92)
custom = calibrate_voltage(4.92, 0.10)standard uses the default offset and becomes 4.97.custom overrides the default and becomes 5.02.Use a default only when one value is genuinely the normal case.
import math
angle_radians = math.pi / 4
component = math.sqrt(2) * math.sin(angle_radians)
print(component)import math makes the module available.math.pi, math.sqrt, and math.sin come from its namespace.Modules let us reuse reliable code without copying its implementation.
sensor_tools.py
Keep both files in the same folder for this Lecture 3 example.
A program must process one raw voltage reading.
0.05 V.Low, Normal, or High.Before coding, decide:
One good design is calibrate_voltage(raw, offset=0.05) and voltage_status(voltage) in sensor_tools.py, called from main.py.
return sends a result to the caller.print() displays information but returns None.