Functions
Planning, problem decomposition, code reuse, and variable scope.
Area of A Circle
Problem Description
The steps below will walk you through the solution of the following problem.
\[\cdot\]Write a program that reads the following information regarding a circle:
- The center: Two integers representing the \(x\) and \(y\) coordinates of the circle center.
- A point: Two integers representing the \(x\) and \(y\) coordinates for a point on the perimeter of the circle.
Your program must output the area of the circle.
Remember that the area of the circle is \(\pi r^2\), and the distance between two points \((x_1, y_1)\) and \((x_2, y_2)\) can be computed using the formula:
\[\sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}\] \[\cdot\]
Step 1: Program Plan
We will begin by laying out the steps for solving the problem as comments in out program
# (1) Read the coordinates of c (the center point)
# (2) Read the coordiantes of p (a point on the perimeter)
# (3) Compute the distance between c and p to find the radius
# (4) Compute the area using the formula: Pi*r^2
# (5) Print c, p, and the area
Breaking down a long program into steps before writing code is important. It makes the problem easier and reduces the chances of making mistakes.
Step 2: Implementation
Next, we will fill out the code for the above steps.
import math
# (1) Read the coordinates of c (the center point)
print("Reading the circle center.")
cx = int(input("Enter x: "))
cy = int(input("Enter y: "))
# (2) Read the coordiantes of p (a point on the perimeter)
print("Reading a point on the perimeter.")
px = int(input("Enter x: "))
py = int(input("Enter y: "))
# (3) Compute the distance between c and p to find the radius
xDiff = (cx - px) ** 2
yDiff = (cy - py) ** 2
r = math.sqrt(xDiff + yDiff)
# (4) Compute the area
a = math.pi * r ** 2
# (5) Print c, p, and the area
print("Center: (", cx, ", ", cy, ")")
print("Point: (", px, ",", py, ")")
print("Area = ", a)
Step 3: Expansion
Let’s assume that we want to modify the program so that it reads information for two circles instead of one.
The code below is an example for how the code can look like.
Step 4: Refactoring
The above code (for two circles) clearly has a lot of duplicate code. It is long and not nice to read. We can use functions to improve (refactor) our code.
Instead of rewriting the same code twice, we will define a function that does the work for a single circle, and then call this function twice.
import math
def circle_area():
print("Reading the center point.")
cx = int(input("Enter x: "))
cy = int(input("Enter y: "))
print("Reading a point on the perimeter.")
px = int(input("Enter x: "))
py = int(input("Enter y: "))
xDiff = (cx - px) ** 2
yDiff = (cy - py) ** 2
r = math.sqrt(xDiff + yDiff)
area = math.pi * r ** 2
print("Center: (", cx, ", ", cy, ")")
print("Point: (", px, ",", py, ")")
print("Area 1 = ", area)
print("---- CIRCLE 1 ----")
circle_area()
print("---- CIRCLE 2 ----")
circle_area()
Further Improvements
We refactored our code because we needed to do the same thing for two circles and found that the code would be too long and repetitive. However, instead of being reactive to changes in our code, we can proactively think about whether we can break down our code further into smaller pieces that can be reused.
The distance computation between two points is an operation that is not only for computing the area of a circle. This is something that we might need in other applications. Therefore, we can put it in a separate function.
import math
def distance(x1, y1, x2, y2):
xDiff = (x1 - x2) ** 2
yDiff = (y1 - y2) ** 2
return math.sqrt(xDiff + yDiff)
def circle_area():
print("Reading the center point.")
cx = int(input("Enter x: "))
cy = int(input("Enter y: "))
print("Reading a point on the perimeter.")
px = int(input("Enter x: "))
py = int(input("Enter y: "))
r = distance(cx, cy, px, py)
area = math.pi * r ** 2
print("Center: (", cx, ", ", cy, ")")
print("Point: (", px, ",", py, ")")
print("Area 1 = ", area)
print("---- CIRCLE 1 ----")
circle_area()
print("---- CIRCLE 2 ----")
circle_area()
Tracing Function Calls
To understand how programs that involve functions get executed, copy and paste th code below into PythonTutor and click on Visualize. Keep clicking Next to trace the execution of the code step by step and see what happens in memory.
Note the following:
- The flow of execution. The code in the functions is not executed until the function is called. Execution starts from the first line outside any function definition.
- Memory Frames. For each function call, a frame is reserved in memory for the function call. This frame holds the memory needed for the function and is destroyed when the function ends.
Local Variables
Exmaple 1
What is the output of the following code?
def fun():
a = 2
b = 4
result = a**2 * b**2
fun()
print(a, b, result)
This program will crash.
The variables a, b and result were all defined inside the function. Therefore, they are unknown outside the function. These are called local variables, which get created when the function is called, and then get destroyed when the function completes.
You can trace the execution with PythonTutor to see what happens.
Example 2
What is the output of the following code?
import math
def fun(a, b):
a = a ** 2
b = b ** 2
return math.sqrt(a + b)
a = 3
b = 4
result = fun(a, b)
print(a, b, result)
Note the following four different variables in the program:
- The
aandbthat are local to the function. These are created when the function is called and are destroyed when the function ends. - The
aandbthat are defined in the global frame (after the function).
Try tracing the program using PythonTutor to understand what happens:
- The program starts at
a = 3and thenb = 4. - Next,
funis called and two new variables are created. A newaholding a copy of3and a newbholding a copy of4. These variables are local to the function. - Next, the values of local variables
aandbchange to9and16(without affecting the otheraandb). - When the function ends, the result of
math.sqrt(9 + 16)is returned, and the local variables infunare destroyed. - The
aandbin the global frame still hold the original values3and4.