5.5. Fruitful functions

5.5.1. Adding new functions

In one of the previous sections, you made the program for calculating the slope factor (s.py). It should be similar to the version for s.py given in the table below.

import math

# program to calculate the s factor in the USLE 

slope = input("Enter the slope in degrees ")
print("The slope you entered is", slope, "degrees.")
slopeFloat=float(slope)

# slope in radians
slopeRadians = (slopeFloat/360) * 2.0 * math.pi
print("This corresponds to a slope of ", slopeRadians, "in radians.")

# slope in m/m
slopeFraction = math.tan(slopeRadians)
print("This corresponds to a slope of ", slopeFraction, "(m/m)")

# slope factor
S = 0.065 + 0.045 * slopeFraction + 0.0065 * slopeFraction**2.0

print("The slope factor is", S)

In many cases it is convenient to define functions for often used calculations in a program. For instance, the statement

slopeRadians = (slopeFloat / 360.0) * 2.0 * math.pi

Can be replaced by,

slopeRadians=degreesToRadians(slopeFloat)

while providing a definition of the function degreesToRadians:

def degreesToRadians(angleInDegrees):
     angleInRadians = (angleInDegrees / 360.0) * 2.0 * math.pi
     return angleInRadians

The word def indicates a function definition. Note the : at the end of the first line of the function definition. Here, the function has an ‘input’, which is called the argument of the function. It is angleInDegrees. Everything below the first line of the function definition is called the body of the function, indented from the left margin by one or two spaces. The statements in the body define what the function does. The last statement, a return statement, defines the return value of the function. In our example, the return value of the function will be assigned to slopeRadians. The function body in this example contains only two statements, but you may use more (not too many as this will make the code hard to read). For instance, an alternative way of defining the function would be:

def degreesToRadians(angleInDegrees):
    angleInDegreesDivided = angleInDegrees / 360.0
    angleInRadians = angleInDegreesDivided * 2.0 * math.pi
    return angleInRadians

Now it will be clear why we use a return statement: angleInRadians needs to be returned. Not angleInDegreesDivided!

Open s.py (either your own version or the one in the table below) and save it as s_function.py. Make the changes suggested above. Put the function definition at the top of the script, one line below import math. Save the script and execute it to check it. It should generate the same result as the original one!

Now, let’s do a test: save s_function.py as test.py and move the function definition to the bottom of the script. Save test.py and execute it. Why do you think it doesn’t work?

The next step is to make a function calculating the slope factor. Open s_function.py and save it as s_twofu.py. Modify the script by defining a second function (define it below the degreesToRadians function definition) named sFactor having one argument, the slope in degrees given as a float, with the slope factor as the return value. You could use this as the first line of the function definition:

def sFactor(slopeInDegrees):

Note that most statements which were in the s_function.py script need to be moved to the body of the sFactor function. Calculate S now by calling (at the bottom of the script) the function sFactor. Be sure the script runs before answering the next question.


Question Where should the sFactor function definition be provided?

  1. Certainly below the definition of the degreesToRadians function.

  2. Certainly above the definition of the degreesToRadians function.

  3. Certainly inside the definition of the degreesToRadians function.

  4. Either above or below the definition of the degreesToRadians function.

Correct answers: d.

Feedback: As long as all the function definitions needed to execute a line are above that line, it makes no difference in what order they are given. In general, function definitions are not given inside other function definitions.

import math

# program to enter the slope in degrees 

def degreesToRadians(angleInDegrees):
    angleInRadians = (angleInDegrees / 360.0) * 2.0 * math.pi
    return angleInRadians

def sFactor(slopeInDegrees):
    # slope in radians
    slopeRadians = degreesToRadians(slopeInDegrees)
    print("This corresponds to a slope of", slopeRadians, "in radians.")
    
    # slope in m/m
    slopeFraction = math.tan(slopeRadians)
    print("This corresponds to a slope of", slopeFraction, "(m/m)")
    
    # slope factor
    S = 0.065 + 0.045 * slopeFraction + 0.0065 * slopeFraction**2.0
  
    return S

slope = input("Enter the slope in degrees ")
print("The slope you entered is", slope, "degrees.")

# slope factor
S = sFactor(float(slope)) 

print("The slope factor is", S)


Imagine field data are collected of the topographical slope to estimate soil erosion for individual arable fields. On each arable field, slope is measured two times, at randomly chosen locations on the arable field. It is assumed that the average slope factor of an individual field (S f) can be estimated by:

S f = (S 1 + S 2) / 2.0

with S 1, S 2, the slope factors calculated from the first and second slope measurements on the field, respectively. Open s_twofu.py and save it as s_two_in.py. Using the equation given above, modify the script such that it can be used to calculate the average slope factor (Sf) of a field:

  • asks the user to enter the first slope of the field

  • asks the user to enter the second slope of the field

  • prints Sf

You will find that you can use the same function sFactor twice. Test the script before answering the next question.


Question On a field, the slope is measured two times, resulting in a slope of 11.0 and 13.0 degrees. What is the average slope factor?

  1. 0.013

  2. 0.091

  3. 0.075

  4. 0.021

Correct answers: c.

Feedback:

import math

# program to enter two slopes in degrees and calculate average slope
# factor

def degreesToRadians(angleInDegrees):
    angleInRadians = (angleInDegrees / 360.0) * 2.0 * math.pi
    return angleInRadians

def sFactor(slopeInDegrees):
    # slope in radians
    slopeRadians=degreesToRadians(slopeInDegrees)
    
    # slope in m/m
    slopeFraction=math.tan(slopeRadians)
    
    # slope factor
    S = 0.065 + 0.045 * slopeFraction + 0.0065 * slopeFraction**2.0
  
    return S

slopeOne = input("Enter the first slope in degrees ")
print("The first slope you entered is", slopeOne, "degrees.")

slopeTwo = input ("Enter the second slope in degrees ")
print("The second slope you entered is", slopeTwo, "degrees.")

# average slope factor of the field
Sf = (sFactor(float(slopeOne)) + sFactor(float(slopeTwo))) / 2.0

print("The average slope factor of the field is", Sf)