| Creating a function | Revisiting the Payroll | Functions to validate Input | Summary |
| Practice | Exercise | Assignment Part 5 |
On completion of this section you will be familiar with
Listing 1
|
1 |
#C2Interactive Payroll
Programme |
|
2 |
strName=input("Enter employee's full
name: ") |
|
3 |
floatHours=float(input("Enter value for
hours: ")) |
|
4 |
floatRate=float(input("Enter value for
rate: ")) |
|
5 |
floatGross=floatHours * floatRate |
|
6 |
floatTax=floatGross *
0.25 |
|
7 |
floatNet=floatGross-floatTax |
|
8 |
print("Gross is
" + str(floatGross)) |
|
9 |
print("Tax is
" + str(floatTax)) |
|
10 |
print("Net is
" + str(floatNet)) |
Listing 1 above is a reprint of one of the first programmes
we wrote. It is a very simple programme
that is very easy to follow since the individual lines of the input, processing
and output followed each other in a very logical sequence from top to bottom. There
is hardly any need for comments or documentation due to its simplicity.
Of course this programme was so simple that it was of no use in real
life. In order to make it more useful we added an if..else
construct in order to calculate the tax. After that we added a if..else..elif
construct in order to calculate the superannuation. Finally, in order to
validate the hours and rate we added two While
loop, one for each value. Recall that the if.. else construct was added to
handle the complexity of the tax calculation, the if..elif..else to handle the even more complex superannuation
contribution and the while loop to
handle the validation of the data going into the variable floatHours. Adding these extra
functionalities added to the complexity of the programme and made it difficult
to read and interpret.
Our aim here is to restore the original simplicity of the programme. To do this we shall separate the processing
from the main programme so that the main programme will retain the simplicity
of Listing 1 above. The processing we
are separating include the calculation of the gross,
the tax, the superannuation and the net.
Those are three separate processings which we
shall divide up among four separate functions which we shall name calculateGross(), calculateTax(),
calculateSuper() and calculateNet(). We shall also create
another function that will display the calculated values for the gross, tax,
superannuation contribution and the net pay. We shall call this function showData().
As well as making our programme easier to read, functions have another
benefit. Suppose that there was a group of lines of programme code that were
required to be used in different parts of the programme, we can simply write
out the lines of code separately for each part of the programme where they are
required. This has two drawbacks:
·
Firstly the
more often we retype the lines of code the more likely we are to make a mistake
in one of them. This would cause inconsistency in the application.
·
If the
routine needs to be altered then we have to make the same alteration wherever
the routine occurs. This has the inherent danger that we may miss out one of
the instances of the routine.
The other alternative is to write the group of lines together only once
and then to call that group whenever we need to use them. This has the
following advantages:
Listing 2
|
1 |
def calculateTax(gross): |
|
2 |
if
gross<500: |
|
3 |
tax=gross * 0.25 |
|
4 |
else: |
|
5 |
tax=125 + (gross-500) * 0.33 |
|
6 |
return tax |
Listing 2 above shows how a function is created.
In line 1 the function is defined using the keyword def. This is followed by the name of the function
– calculateTax,
in this case. The name of the function
is followed by and opening and closing bracket and between those you can have
as many parameters as you wish.
What is a parameter? A parameter
is a variable that holds a value that has been passed to the function by the
main programme, or by another function.
In our case, once our programme has calculated the value of the gross,
it calls the function calculateTax() and passes the
value of the gross to it. This value
will be stored in the parameter gross.
To finish off the description of the first line of code we must point
out the colon at the end of the line.
This colon specifies that lines 2 – 6 are subservient to line 1 or, in
other words, are the body of the function.
Lines 2 – 5 consist of an if..else construct. This construct tests the value of the
parameter and if it is less than 500 the value of the local variable tax is calculated in line 3, otherwise
the value of tax is calculated at
line5.
Line 6 has something new for us – the keyword return. In our case this is followed by the variable tax. Before describing this keyword we must first
look at the concept of local variables.
The variable tax has been
created inside the function calculateGross() and is therefore only visible inside
the body of the function. This type of a
variable is referred to as a local variable.
Since the variable tax is
local to the function calculateGross() it cannot
be seen by the main programme and if we need to get the value stored variable
back to the main programme we have to use the keyword return to do so.
Once we start examining the main programme we shall show you exactly how
this is done.
A revisit to the Payroll
Listing 3
|
1 |
#CC8 Functions.py |
|
2 |
|
|
3 |
#function for
calculating gross |
|
4 |
def calculateGross(hours,
rate): |
|
5 |
gross=hours*rate |
|
6 |
return gross |
|
7 |
|
|
8 |
#function for
calculating tax |
|
9 |
def calculateTax(gross): |
|
10 |
if gross<500: |
|
11 |
tax=gross * 0.25 |
|
12 |
else: |
|
13 |
tax=125 +
(gross-500) * 0.33 |
|
14 |
return tax |
|
15 |
|
|
16 |
#function for
calculating superannuation |
|
17 |
def calculateSuper(gross,supercode): |
|
18 |
if supercode ==
0: |
|
19 |
superAmt =
0 |
|
20 |
elif supercode == 1: |
|
21 |
superAmt=gross*0.05 |
|
22 |
elif supercode == 2: |
|
23 |
superAmt=gross*0.1 |
|
24 |
elif supercode == 3: |
|
25 |
superAmt=gross*0.15 |
|
26 |
elif supercode == 4: |
|
27 |
superAmt=gross
* 0.2 |
|
28 |
else: |
|
29 |
superAmt =
-1 |
|
30 |
return superAmt |
|
31 |
|
|
32 |
#function for
calculating the net |
|
33 |
def calculateNet(gross,
tax, super): |
|
34 |
net=gross - tax - super |
|
35 |
return net |
|
36 |
|
|
37 |
#function for displaying
results |
|
38 |
def showData(gross, tax, super, net): |
|
39 |
print("Gross: " + str(gross)) |
|
40 |
print("Tax: " + str(tax)) |
|
41 |
print("Super: " + str(super)) |
|
42 |
print("Net: " + str(net)) |
|
43 |
|
|
44 |
#Main body of programme |
|
45 |
|
|
46 |
#input section |
|
47 |
strName = input("Enter employee's full
name: ") |
|
48 |
floatHours = float(input("Enter value for
hours: ")) |
|
49 |
floatRate = float(input("Enter value for
rate: ")) |
|
50 |
intSuperCode = int(input("Enter
value for super code: ")) |
|
51 |
|
|
52 |
#processing section |
|
53 |
floatGross = calculateGross(floatHours, floatRate) |
|
54 |
floatTax = calculateTax(floatGross) |
|
55 |
floatSuper = calculateSuper(floatGross, intSuperCode) |
|
56 |
floatNet = calculateNet(floatGross,floatTax,floatSuper) |
|
57 |
|
|
58 |
#output section |
|
59 |
showData(floatGross,floatTax,floatSuper,floatNet) |
In Listing 3 above lines 1 – 43 is the area where the programme’s functions are stored. Even though the code for the functions is at the start of the programme the same functions are not executed immediately. This is because the first line of each function defines it to be a function and Python will not run functions unless they are called from somewhere else. For this reason we have to get down as far as line 47 before we meet the first line that will be executed. This line and the three that follow it allow the user to enter values for the employee’s name, the hours worked, the hourly rate and the super code. These lines have not changed since the previous version of the programme and therefore there is no need to discuss them.
The processing section spans lines 53 – 56. In order to explain it let us assume that the user entered 20, 30 and 2 for the hours, the rate and the super code and that therefore these values are stored in the variables floatHours, floatRate and intSuperCode.
At line 53 the function calculateGross(floatHours, floatRate) is called This means that control will pass up to line 4 and the values 20 and 30 that were stored in the variables floatHours and floatRate are copied into the parameters hours and rate at line 4.
Once this copying is done, execution of the function begins at line 5. Here the values of hours and rate, i.e. 20 and 30, are multiplied and the result stored in the local variable gross. Thus the variable gross has 600 stored in it.
We must get this value back to the main programme. This occurs at line 6 with the code return gross. This causes programme control to return back to line 53 and to carry the value of the local variable gross with it. On returning to line 53 the value of gross, i.e. 600 is stored in the variable floatGross.
At line 54 the function calculateTax(floatGross) is called. This causes programme control to pass to line 9 and also causes the value stored in the variable floatGross, i.e. 600 to be copied to the parameter gross.
Once execution starts the condition at line 10 will be false since 600 is not less than 500 and therefore control will pass to line 13 where tax is calculated as 125 + (600-500) * 0.33 = 125 + 33 = 158.
Line 14 returns this value back to the variable floatTax in line 54.
Once line 54 completes processing, programme control passes to line 55, where the superannuation is calculated. To calculate the superannuation we need to know the gross pay and the superannuation code. Therefore the function calculateSuper(floatGross, intSuperCode) is called. This passes programme control to line 17, where the values 600 and 2 are copied into the parameters gross and supercode. In the body of the function lines 18 and 20 test the value of supercode for zero and 1 respectively and therefore return a false value. Line 22, however, tests it for a value of 2. This, of course, is true and therefore line 23 is executed where the super amount is calculated as 10% of the gross, which in this case is 60.
Once line 23 has been executed, programme control jumps out of the if..elif..else construct and goes to line 30, where it meets the return statement. This returns the value of superAmt, i.e. 60, back to line 55 where it is stored in the variable floatSuper. Once this is complete control passes to line 56.
The value of the net is calculated at line 56. To do this we simply subtract the tax and superannuation from the gross. To do this the function calculateNet(floatGross, floatTax, floatNet) is called and thus control passes to line 33, where the values 600, 158 and 60 are copied into the parameters gross, tax and super.
At line 34 the value of the net is calculated as 600 – 158 – 60 = 382, which is then stored in the local variable net.
At lien 35 the keyword return returns the programme control and this value back to line 56 where it is stored in the variable floatNet.
By now the processing is complete and control passes to line 59 which is the first and only line of the output section. Here the function showData(floatGross, floatTax, floatSuper, floatNet) is called. Control passes to line 38 where the values 600, 158, 60 and 382 are copied into the variables gross, tax, super and net. Lines 39 – 42 displays those values along with the appropriate labels.
Notice that there is no return keyword in function showData(). This is because the function does not perform any calculations and that its sole purpose is to present the calculated data to the user. A sample output containing the values discussed here is shown in Figure 1 below.

Figure 1
Before finishing this section let us take a look at the main body of the programme, i.e. lines 46 – 59. We have managed to restore the original simplicity of our original programme:
· In the input section the requests for data follow each other in logical sequence
· In the processing section the function names give a clear indication what the functions actually do, making this section self-documenting
Listing 4
|
1 |
#CC8 Functions.py |
|
2 |
|
|
3 |
#function for validating
a floating point number |
|
4 |
def validateFloat(base,
top, prompt): |
|
5 |
floatValue=float(input(prompt)) |
|
6 |
while (floatValue<float(base)
or floatValue>float(top)): |
|
7 |
print("Value must be in the
range "+str(base) + " to " +str(top)) |
|
8 |
floatValue=float(input(prompt)) |
|
9 |
return floatValue |
|
10 |
|
|
11 |
#function for validating
an integer |
|
12 |
def validateInt(base,
top, prompt): |
|
13 |
intValue=int(input(prompt)) |
|
14 |
while (intValue<int(base) or intValue>int(top)): |
|
15 |
print("Value must be in the
range "+str(base) + " to " +str(top)) |
|
16 |
intValue=int(input(prompt)) |
|
17 |
return intValue |
Listing 4 above shows two functions for validating input data. Both functions are identical in structure and logic. The only difference between them is that the first one validates floating point numbers while the second one validates integers. They could be added to the code in Listing 3 so that the hours, hourly rate and superannuation code could be validated as being within allowed ranges. An example of a call to one of the functions could be:
floatHours = validateFloat(5, 60, “Enter value for hours worked”)
In this case programme control would pass to line 4 of Listing 4 where the values 5, 60 and “Enter values for hours worked” are copied into the parameters base, top and prompt.
Line 5 simply prompts the user to enter a value. The prompt would appear as follows on the console:
Enter value for hours worked
:
This value entered by the user will then be stored in the local variable floatValue.
Line 6, the control line of the while loop tests the new value for being less than the parameter base or greater than the parameter top, or, in our case, being less than 5 or greater than 60. If either of those conditions is true then the body of the loop is entered.
At line 7 an error message is created by adding together the text item “Values must be in the range ”, a string version of the parameter base, the text item “ to ” and a string version of the parameter top. In our case the error message would be:
Value must be in the range 5 to 60
A line 8 the user is again prompted to enter another value and then programme control passes back to line 6.
As with all example, of the while loop this process repeats itself until the user enters a value within the range base to top or 5 – 60 in our case.
Go to topFunctions are used both to avoid repetition of code within a programme
and also in order to make the logic of the programme easier to follow. Data is
passed by the calling routine to a function using parameters. The data passed
and the arguments must match each other in type. There are two types of
functions, those that return a value and those that don’t. The functions must
be declared with the keyword def. This is followed by the name of the function. This name is followed by a pair of
brackets. Between those brackets are the
function’s arguments. A function may
have as many arguments as are necessary.
After a function’s closing brackets you must have a colon to indicate
that the following group of indented lines belong to
the function’s body.
Copy Listing 3 into a .py file and run
it. Check that it is working
satisfactorily.
Once this is running to your satisfaction copy the
code in Listing 4 and paste it into the same .py
file. It does not matter where in the .py file you paste this code as long as it is not in the
middle of the programme body or in the middle of another function. Now alter
the line for inputting the value of hours as follows:
floatHours = validateFloat(5, 60, “Enter value for hours
worked”)
Alter the lines for inputting the rate and superannuation code in the same
manner, but remember to call the function validateInt() to validate the super code.
Once the code is running satisfactorily experiment with different lower
and upper values for hours rate and super code and
check that the altered programme applies those new limits.
Modify the
code you have created for Assignment Part 4 as follows:
Although a major reorganization of the programme has occurred here there
has been no change in the actual processing.
The test data for this part will be exactly the same as that for Part 5.