Making this Code Your Own
June 2, 2011 7 Comments
Shopkeeper No, I’m afraid not actually guv, we’re fresh out of parrots. I’ll tell you what though … I’ll lop its back legs off, make good, strip the fur, stick a couple of wings on and staple on a beak of your own choice. (taking small box and rattling it) No problem. Lovely parrot.
While I’ve been giving you coding examples, I’ve assumed that generalising from them will be self evident. I understand that that it is not. In this tutorial we will look at ways of approaching the code with a view to giving you some guidance on how to make this code your own.
The first step is to be able to break the code down into logical units, and then to break those units into subunits. The second step, once you have broken the code down, is to understand what each of the parts of the code is doing. If you don’t know what the pieces are doing, it’s hard to change what they’re doing! The final thing is this:
try, try, try
take notice of what happens when you try, try, try. Python tries to explain why things didn’t work like you thought they would. Often you’ve just mistyped something.
Remember this: there is no reason why you can’t be a good programmer, even at a young age.
Remember this also: in all of these tutes there is code which I don’t get right the first time, or have to retype for some reason.
Let’s take an example:
>>> for i in range(10): ... print i ... 0 1 2 3 4 5 6 7 8 9
This code has two lines, and two parts. The first part (for i in range (10)) creates a loop. The second part (print i) does something each time the loop executes. Next I break the first part down and ask what range() does. If you don’t know, use help (in my console this gets “paged”, if this happens to you, press ‘q’ when you’re finished reading it):
>>> help(range) Help on built-in function range in module __builtin__: range(...) range([start,] stop[, step]) -> list of integers Return a list containing an arithmetic progression of integers. range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0. When step is given, it specifies the increment (or decrement). For example, range(4) returns [0, 1, 2, 3]. The end point is omitted! These are exactly the valid indices for a list of 4 elements.
Based on the help file, range() gives us a list (of integers). Range tute is here.
Next, I confirm that I understand what it does by trying a concrete example:
>>> print range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
What the for statement does is makes the variable i point to each of these elements in turn (see the print out above). So, how could we change this? Well, we could either change how the code is looping, or what it is doing in the loop. Let’s change what it is doing:
>>> for i in range(10): ... print 10-i ... 10 9 8 7 6 5 4 3 2 1
Now, instead of counting up, the loop counts down. Let’s change the loop to be a multiplication table:
>>> for i in range(10): ... print "7 x ",i," = ",7*i ... 7 x 0 = 0 7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63
Note: We need to use a comma (,) here in the print statement because i is a number and “7 x ” (etc) is a string.
Exercise: what would we need to change to make this give the times table for 7×1 through to 7×12?
In order to start at 1, we need to add 1 to i. Further for it to run to 12, we need to increase the range by 2:
>>> for i in range(10+2): ... print "7 x ",i+1," = ",7*(i+1) # increase each i and put brackets in otherwise you'll get 1+ 7 x i ... 7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63 7 x 10 = 70 7 x 11 = 77 7 x 12 = 84
Exercise: How would you change this to print out the times table for all numbers from 1 through 12?
>>> for i in range(12): ... for j in range(12): ... print i+1,"x",j+1," = ",(i+1)*(j+1) # note the brackets ... print # just to make it more readable - try it without the print statement [output omitted]
What I’ve done here is create two loops, one runs inside the other. The print out will show you how i and j change in each loop. See how it looks if you swap i and j in the first two lines:
>>> for j in range(12): ... for i in range(12): ... print i+1,"x",j+1," = ",(i+1)*(j+1) ... print ... [output omitted]
You can see that there’s an issue here with the length of the output. So, let’s print two tables each time through the loop, and loop half as many times:
>>> for i in range(6): ... for j in range(12): ... print i+1,"x",j+1," = ",(i+1)*(j+1),'\t\t',i+7,"x",j+1," = ",(i+7)*(j+1) ... print
Now, I think that that middle of the loop looks cumbersome. How about we simplify it by making a function:
>>> def xByy(x,y): ... ''' given two numbers x and y, return a string ... representing their product. So, for example ... for 3 and 4, this function returns a string: ... "3 x 4 = 12" ... ''' ... return str(x)+" x "+str(y)+" = "+str(x*y) # x and y are numbers so they need to be converted to strings first - str() ...
Test the function to see it works as you think it should:
>>> print xByy(3,4) 3 x 4 = 12
(3×4 is 12 isn’t it?) Note, help works even on this newly created function – Try help(xByy)
Now we can “refactor” the code we had earlier:
>>> for i in range(6): ... for j in range(12): ... print xByy(i+1,j+1)+'\t\t'+xByy(i+7,j+1) # So, i+1 becomes x and j+1 is y, then i+7 and j+1 ... print
We could change it again to print more of the tables on a line:
>>> for i in range(4): ... for j in range(12): ... print xByy(i+1,j+1)+'\t\t'+xByy(i+5,j+1)+'\t\t'+xByy(i+9,j+1)# Adding another column ... print
And so on. The other thing we could do is recognise that range() is a list just like any other, so we could equally see what would happen if we used another list:
>>> names = ["John","Eric", "Terry","Graham","Terry","Michael","Carol","Connie","Ian"] >>> for n in names: ... print n ... John Eric Terry Graham Terry Michael Carol Connie Ian
Realising this you could mix things up a little:
>>> import random >>> r = random.randint # You haven't seen this before, it is me cheating a little to save on typing. >>> nouns = ["apple","toy car","pumpernickel","dinner","pillow","homework","little finger","house","pencil","letterbox","hamster"] >>> verbs = ["ate","played","smelled","lost","forgot","dropped","hid","erased","infuriated","planted","ripped up","tripped over","dusted","talked to"] >>> v = len(verbs)-1 >>> n = len(nouns)-1 >>> for i in range(10): ... print "I was very taken aback when Mrs Pepperpot "+verbs[r(0,v)]+" my "+nouns[r(0,n)]+"." ... I was very taken aback when Mrs Pepperpot infuriated my letterbox. I was very taken aback when Mrs Pepperpot smelled my pumpernickel. I was very taken aback when Mrs Pepperpot forgot my pencil. I was very taken aback when Mrs Pepperpot smelled my toy car. I was very taken aback when Mrs Pepperpot tripped over my house. I was very taken aback when Mrs Pepperpot played my toy car. I was very taken aback when Mrs Pepperpot lost my house. I was very taken aback when Mrs Pepperpot forgot my pillow. I was very taken aback when Mrs Pepperpot dropped my pumpernickel. I was very taken aback when Mrs Pepperpot erased my house.
Exercise: What is going on here? Why have I assigned, v = len(verbs)-1? etc?
Note: r(0,v) is shorthand for random.randint(0,v)
You can run this with a different list of verbs and nouns, just make sure, after you assign or change the verbs/nouns list that you reassign the values of v and n.
Exercise: change this code so that you have a list of feelings one of which is inserted at random – I was very x….
Final note: Syntax Errors
Often things will fail because you have a syntax error, which is computer speak for “you have made a typo”. It is usually just a case of working through what you did to find the mistake.
TypeError: ‘list’ object is not callable – this probably means you’ve used round brackets () when you were supposed to use square ones 
NameError: name ‘some_text’ is not defined – this probably means you are missing inverted commas around something which is meant to be a string “some_text”
TypeError: cannot concatenate ‘str’ and ‘int’ objects – you’ve tried to add a string and a number. Convert the number to a string using str().
We’ve played around here with some basic building blocks of the language and found we can do some interesting stuff. We have been able to vary things by breaking the parts of the program down into pieces, understanding what the pieces do, and, based on that understanding, changing them.