“Why is learning programming so difficult?”
Like many readers, I too found programming challenging and I am
still
learning! After teaching programming for the past seven years, I noticed
that only a minority of my students felt confident enough to program
independently after two years of instruction. Upon realising this, I knew I
had to change my pedagogy.
I believe Scott Portnoff is correct; students do need to memorise some
key programming constructs e.g. if statements, while loops and for loops.
This will decrease cognitive load and enable students to practise more
fluently. Portnoff’s work was my starting point for this book. As a student
of b-boy and hip-hop culture, I came across Joseph Schloss’s book
Foundation
where he writes about a
musical
canon that exists for b-boys.
To add to this theory, Jonathan Sacks argues that a
literary
canon is
essential to a culture. In linking these three ideas together, I thought
about creating a canon for programmers. Perhaps there is a set of
programs which represent algorithms that every computer science
student should familiarise themselves with?
I started to compile a list of programs based on my experience as a
teacher and examiner. Many of the shorter programs are worth repeating
until they are committed to memory and I admit that learning some of the
longer programs by heart is both challenging and futile. Therefore, to
help you develop fluency, I have also written some challenges based on
3
this canon. These challenges should help you understand these
programs by applying them.
Sue Sentance suggested in her introduction to programming courses,
that we should introduce students to subroutines in their very first
program. Richard Pawson goes one step further in edition 07 of the
Hello
World
magazine; here Pawson puts forward a case for teaching using the
functional programming (FP) paradigm from the outset. He makes a
strong case for using functions which return values rather than
containing inputs and outputs. This seems counterintuitive due to the
perceived complexity of FP syntax, however there are three key
arguments for using functions- unit testing of individual functions, code
reusability and a separation of concerns. I would therefore encourage
readers to write with functions from the very beginning. This seems
daunting at first, however repetition will lead to fluency.
Despite the irrefutable advantages of FP, I have to be pragmatic and will
include procedures (subroutines which do not return values) and also
programs which do not use subroutines at all. Whilst, I recognise this
might be a step away from the FP paradigm; students are likely to
encounter simple structured algorithms up to at least GCSE level. Not
including examples of both structured and FP paradigms would be doing
our students a disservice. For some algorithms, the exclusion of
functions also reduces complexity and cognitive load therefore providing
a shallower learning curve.
In order to keep programs as short as possible and to improve
readability, comments are not generally provided in the programs.
Instead, a more detailed explanation is explained below each program. In
lessons, I have found it useful to go through one or two algorithms at the
front of the book with my students and then go to the associated
challenge at the back. Alternatively, students may choose to work
through the book independently in class or at home.
This book will hopefully help you to practise and develop fluency in your
programming.
Learning programming is similar to learning a musical
instrument.
Both involve practise and making lots of mistakes. Both
also require perseverance to develop fluency. Keep going!
4
A program which takes two numbers as inputs and outputs the
smallest number.
When you first started programming, you may have produced a
program to ouput a lower number without using subroutines.
You may even be asked to write simple programs like this in your
exams. However, good programmers write code which can be
reused and tested in isolation (known as unit testing). Therefore,
using a subroutine (also known as a subprogram) to create a
procedure would produce a “better” program that is modular:
Whilst the use of a procedure in the second program allows you to
call the subprogram multiple times in the main program, it does not
allow for full code re-use...
1
2
3
4
5
6
7
8
9
num1 = int(input("Enter the first number: "))
num2 = int(input("Enter the second number: "))
if num1 <= num2:
lowest = num1
else:
lowest = num2
print("The lowest number is " + str(lowest))
1
2
3
4
5
6
7
8
9
10
11
12
13
def lower_num(num1,num2):
if num1 <= num2:
lowest = num1
else:
lowest = num2
print("The lowest number is " + str(lowest))
first_num = int(input("Enter the first number: "))
second_num = int(input("Enter the second number: "))
lower_num(first_num,second_num)
5
...What happens if you wanted to use this lowest number later in
the program? In this case, it makes sense to use a function. The
key differentiator is that functions return values whereas
procedures do not.
The function
lower_num
is defined on lines 1-5. We have to
define functions before we can call (use) them.
Usage of the function is demonstrated on lines 8-13. We still
take two numbers as integer inputs on Lines 8-9.
Line 11 calls the function
lower_num
with two arguments: the
contents of
first_num
and
second_num variables
.
These arguments are passed into the parameters
num1
and
num2
respectively¹. The result is stored in the variable
lowest
.
As the returned value is an integer, it is cast to a string on line
13 using str(lowest) so that it can be concatenated (the
technical name for joining text) with the meaningful output
message.
¹ Arguments and parameters should have different names even if they seem to serve the
same purpose. In this case both num1 and first_num store the first number. However, the
argument stored in the variable
first_num
has global scope, it can be accessed and
changed anywhere in the program. The parameter
num1
has local scope, it is a local
variable which can only be accessed in the subroutine.
1
2
3
4
5
6
7
8
9
10
11
12
13
def lower_num(num1,num2):
if num1 <= num2:
return num1
else:
return num2
first_num = int(input("Enter the first number: "))
second_num = int(input("Enter the second number: "))
lowest = lower_num(first_num,second_num)
print("The lowest number is " + str(lowest))
6
A subprogram which outputs a username based on a student’s
first name, surname and year of enrolment.
E.g. Connor Pearce 2019 should return 19CPearce.
The procedure
user_name
is defined on lines 1-4.
Line 2: Strings can be sliced, with the first index being 0. In this
case for the year, we start at 2 and stop at 4 (exclusive). This
means we would slice year[2] and year[3] i.e. the last two digits
of the
year
. These are concatenated with the first letter from
the
forename
and the entire
last_name
.
Lines 7-9: This shows how the procedure might be used. First
the user’s details are taken as string inputs .
Then the procedure is called on line 11 with the user’s details
as arguments.
The output is shown below:
1
2
3
4
5
6
7
8
9
10
11
def user_name(forename, last_name, year):
username_out = year[2:4] + forename[0] + last_name
print("Your user name is " + username_out)
first_name = input("Enter your first name: ")
surname = input("Enter your surname: ")
joined = input("Enter the year you joined the school: ")
user_name(first_name,surname,joined)
Enter your first name: Connor
Enter your surname: Pearce
Enter the year you joined the school: 2019
Your username is 19CPearce
7
If you wanted to use this
user_name
procedure later to generate
an email address, this would not be possible without duplication of
code, it is therefore wise to rewrite this subprogram as a function.
This is shown below:
Here we introduce a programming convention of placing your main
program in a main function. The main function should be the only
function which contains inputs and ouputs in the entire program.
From this main function you should call other functions, passing
arguments into parameters. This process is known as parameter
passing.
The main function above spans lines 7-13. Lines 16-17 ensure that
your main function will be the first function to be run when the
program is executed.
__name__
==
'__main__'
by default.
However, if the program is imported, the
__name__
value
becomes the module name, so you can selectively run or test
functions. This is yet another advantage of using the functional
programming paradigm.
def user_name(forename, last_name, year):
username_out = year[2:4] + forename[0] + last_name
return username_out
def main():
first_name = input("Enter your first name: ")
surname = input("Enter your surname: ")
year = input("Enter the year you joined the school: ")
gen_user_name = user_name(first_name, surname, year)
print("Your user name is " + gen_user_name)
if __name__ == '__main__':
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
8
A subprogram which calculates the area of a circle.
The example below is a function as it returns a value.
Line 1: As the value of Pi
Dostları ilə paylaş: |