Random Imports

In 1970, the British Empire lay in ruins, and foreign nationals frequented the streets – many of them Hungarians…

Hungarian: Ya! See-gar-ets! Ya! Uh…My hovercraft is full of eels.

In our last tutorial, we met the concept of functions.  It turns out that functions (and another concept called classes, which we haven’t got to yet) are the workhorse of Python.  Almost everything you will end up doing with Python will involve the use of functions.  The good news is that most of what you do will rely on functions written by other people.  Python includes a mechanism for sharing functions with other people, but also with yourself – so if you write a function for one program today, you can use it with a different program tomorrow (the multiply() function we wrote earlier might be useful in many different sorts of programs for example).  That mechanism is called the import statement.  If you’re unfamiliar with this English word ‘import’ see this definition.

The import statement imports programs which have been saved [into another file – the file is called a module,  but we haven’t done saving files yet] into the current program.  For the time being we will only be importing modules which other people have written.  However, later, when we get to saving programs we may also be importing our own.

You have already used the import statement in the WhyPy tute:

>>> import this
[stuff omitted]

It told us about the Zen of Python.  What is happening here is that there is a file called ‘this.py’ (and is hidden away in /usr/lib/python2.5/this.py on the computer I am typing this on, but it may be somewhere else on yours).  When you import this, Python loads and runs the contents of that file as if the contents of the file were executed at the place where the import statement is – with some caveats (see below).  The this.py file contains two for loops and a print statement at the end of it (if you are brave and able, find a copy of the file on your system and read it).  When the module is imported Python actually acts on these statements as if you’d typed them in, which is why you get the printout on import.

When there is another function defined in the imported program, it is given a name as a part of the module imported.  So if the function multiply() is defined in a file called myModule.py then import myModule (note no ‘.py’) would create a function in your program which is called myModule.multiply().  To the  computer this means “look for a function called multiply() in the file myModule.py”. As I mentioned earlier we’re going to look at importing other people’s stuff first.  Importing our own stuff will need to wait.

Python comes with a heap of functions built in.  That is, they are available when you run the Python interpreter, without having to explicitly import anything further.  The range() and int() functions are examples – they are available whenever you run Python.  However, a Python installation also comes with other modules which are available for loading, but which are not loaded automatically (loading everything every time would use up time and memory on the computer, and if the module’s functions aren’t being used, that would be wasted effort).  The random module is an example.

>>> random()
Traceback (most recent call last):
 File "<stdin>", line 1, in ?
NameError: name 'random' is not defined
>>> import random
>>> random()
Traceback (most recent call last):
 File "<stdin>", line 1, in ?
TypeError: 'module' object is not callable

Here I have tried to use a function called random() – but Python doesn’t know what I’m talking about.  However, after I import the module called random it gives me a different response (it says that it knows about something called ‘random‘, but it isn’t callable – that is, it can’t be treated as a function).  The name of the module here is ‘random‘.  It also has a function within it called ‘random()‘.  So the way we call it is by putting the module name and the function name together, separated by a dot:

>>> random.random()
0.17113600109807192
>>> random.random()
0.82195215747538508

What random.random() does is to give you a random (technically ‘pseudo-random’) number between zero and one, including zero, but not including one.  Randomness can be very important in programs which rely on variability.  You may not want randomness when you multiply numbers together, but you might want it in a game where aliens appear at random locations on the screen.

Guessing Game

Here’s a quick guessing game, using a function definition and the random() function from the random module (ie random.random()):

>>> import random
>>> def guessGame():
...   answer = int(random.random()*10)+1
...   while True:
...      spam = raw_input('What is your guess (type a number): ')
...      guess = int(spam)
...      if guess > answer:
...         print 'No, the answer is less than ',guess
...      if guess < answer:
...         print 'No, the answer is greater than ',guess
...      if guess == answer:
...         print 'Yes, you guessed correctly! The answer is ',answer
...         return
...
>>> guessGame( )
What is your guess (type a number): 3
No, the answer is less than  3
What is your guess (type a number): 2
Yes, you guessed correctly! The answer is  2
>>> guessGame( )
What is your guess (type a number): 4
No, the answer is greater than  4
What is your guess (type a number): 6
Yes, you guessed correctly! The answer is  6

Each time you run it, the answer should be different (well, one in ten times it will be the same as the last answer).

Homework:

[This will be a bit tedious.  When we know how to save files it will become a little easier]

Change it to a guessing game for numbers from 1 to 100 (or 1000 etc) by changing the 10 to a different number.

Extra points: make the number range dependent upon a value passed into the function – for example, guessGame(17) would choose a number from 1 to 17. In order to do this you should look at the function tutorial – the function’s definition needs to be changed so that it has an argument in the brackets.  Give the argument a name, and then use the name of the argument where 10 is above.

Explanation:

The function first initialises an answer by randomly choosing a number between zero and one, multiplying it by 10 (giving a number between 0 * 10 and 1 * 10 – but not including 1*10).  It uses the int() function we met earlier to convert it from a decimal (like 3.4) to an integer (like 3).  This gives a number between 0 and 9 (because random() won’t return the number 1),  so we add one to make the answer between 1 and 10.    Then the program falls into a continuous loop which keeps asking you for a guess.  If the guess is wrong, it tells you whether you need to guess higher or lower.  If you’re right it congratulates you then exits the function through the return statement.

Do you notice that you run the function by putting the name of the function with no arguments-> guessGame().  Did you also notice that you can keep on running the function without having to retype it, just by typing guessGame()?  Functions save you a lot of effort in this way.

To show you that the import really has an effect, we can delete the [reference to the] imported module (using del, which I haven’t told you about yet) and show that guessGame() no longer works without it, then re-import it:

>>> del random
>>> guessGame( )
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "<stdin>", line 2, in guessGame
NameError: global name 'random' is not defined
>>> import random
>>> guessGame( )
What is your guess (type a number):

A final Note

On a final note, you might, reasonably, ask how I knew that there was a module called random which was available to import.  Unfortunately, there isn’t an easy way to know, other than reading through the Python docs, seeing it mentioned in a book or Googling what you want.   We’ll cover some useful imports in some other tutes.

Functions (or The Right Place for an Argument)

I have a secret to tell you.   I have been cutting some corners in some of the earlier tutorials.  Wherever you saw these -> () I was sneaking a function in under your nose, without actually telling you about them.

Here is a sample function:

>>> def justContradiction(argument):
...     return 'Yes I did'
...
>>> justContradiction("You did not")
'Yes I did'
>>> justContradiction("didn't")
'Yes I did'
>>>



justContradiction Function takes one argument

What is happening here is:

  • def is a Python statement.  It says to the program that you are def-ining a function;
  • the function’s name (in this case) is justContradiction – not entirely inapt, as it indulges in the automatic gainsay of whatever argument is put to it (try justContradiction(5));
  • the function named justContradiction expects to receive one input (called an argument);
  • the function is called by putting the name of the function and putting a single argument in brackets immediately after the name of the function (other functions may take a different number of arguments);
  • when the function is invoked by a call (the lines which start with justContradiction…) Python actually goes to the function and works through it.  When (and if) it encounters a return statement, Python leaves the function and comes back to where it left off and passes the value returned back as well.  As we are in interactive mode, the Python interpreter prints it, much as it would printed the value of toy0 in the Lists example.  If the function’s code block ends without a return statement, the program still continues where it left off, but no value is returned.

This function is a little boring because it is unresponsive to the argument put to it (not unlike Mr Vibrating).  Functions get more interesting though when they do something with the arguments they are called with.  (For your reference, the functions I sneaked in earlier were range(), raw_input() and int()).

Here is a function which transforms  squares into circles:

>>> def f(shape):
...    if shape =='square':
...         return 'circle'
...    return shape
...
>>> f('box')
'box'
>>> f('circle')
'circle'
>>> f('square')
'circle'

So, as above, we have defined a function (called f).  This function receives an argument and, when it does ,it calls that argument shape, although any valid variable name would do.   It checks to see if what was passed to it was the string ‘square’.  If so, it returns ‘circle’.  If not, it returns what was passed (return shape).  Functions are not fussy about the arguments passed to them, although they will get stroppy if you pass in the wrong number of arguments (ie you put more arguments in the brackets than are there in the definition of the function).

>>> f(9)
9
>>> f()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 1 argument (0 given)
>>> f('square','circle')
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 1 argument (2 given)

Functions can be defined to take any number of arguments, but they must be separated by commas.  Also, you can make some arguments optional by supplying a default value for them:

>>> def multiply(a,b=1):
...    return a*b
...
>>> multiply(2)
2
>>> multiply(2,3)
6
>>> multiply(2,3,4)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: multiply() takes at most 2 arguments (3 given)

Here, we’ve defined a function called multiply() (I am including brackets here to emphasize that it is a function).  It takes 1 or 2 arguments. If no second argument is supplied it is assumed to be 1 (b=1) – you probably wouldn’t want  multiply to do this in the wild though.  In the example multiply(2,3), when multiply() is called the first argument in the calling part of the program (2) is assigned to the first named variable in the definition (a) and 3 is assigned to b (later, when b is omitted, the value of a is returned).  The two numbers are multiplied together (a*b) and immediately returned to the calling part of the program.  Moreover, a function call can play the role of any other value:

>>> a = multiply(2,3)
>>> a
6
>>>

Here it is an assignment  (2*3 is assigned to the variable a – this is a different a from the one in the function, this aspect of functions won’t be covered in this tute, but if you’re curious search for “python local variables” ).  But you really can treat the function call as any other object:

>>> multiply(multiply(2,3),4)
24

Here multiply is called twice.  First, the computer works out what multiply(2,3) is (hint: it’s 6).  Then it works out multiply(6,4).  Just so you don’t get complacent:

>>> multiply('Yes I did ',4)
'Yes I did Yes I did Yes I did Yes I did '
>>>

Functions have many functions (errr… so to speak).  Some ways functions can be used include:

  • to avoid having to retype the same section of code over and over;
  • to create logical units of code;
  • to give a meaningful name to certain parts of code;
  • ease of updating.  If you have cut and paste code at different parts of your program and want to change how it operates, you need to hunt down everywhere in your program where you put the code.  However, if the code is in a function any changes you make are automatically updated everywhere because all calls go through the function’s code.

Homework:

Change this siblingAge function so that if you type in your age as an argument, it returns the age of one of your siblings (or, if you have none, of an imaginary sibling who happens to be 2 years younger than you):

>>> def siblingAge(myAge):
...     return myAge-0
...
>>> siblingAge(8)
8

Use it to find how old the sibling will be when you are 15, 30 and 47.

Each time you change it you need to retype the def statement line, then the return line.   The arrow keys should allow recall of lines you have typed earlier.

Lists

You might recall earlier we talked about two ‘types’ of data in a program – ‘strings’ and ‘numbers’.   We learnt that you can tell something is a string because it has quotation marks around it.  In this tutorial we are going to meet a new type called lists.   You can’t program a computer game without knowing about lists.  You can tell something is a list because it has square brackets around it -> [].  The truth is I’ve snuck a list in before, so this is not a first meeting.  Do you remember?

In the for/range tutorial we used range(5).   It gave this output:

>>> range(5)
[0, 1, 2, 3, 4]

The object [0, 1, 2, 3, 4] is a list.

To adopt the analogy we used for variables, lists are like a big bucket holding a heap of smaller buckets, although the smaller buckets don’t have names, they just have numbers.  Lists are a very powerful way of allowing you to handle a heap of things in a consistent and general way without having to deal with each of them specifically.

For example, imagine you have two toys.   Let’s say toy0 is an action figure, and toy1 is a scooter.  When you want to store these you would do an assignment like this:

>>> toy0='action figure'
>>> toy1='scooter'
>>>

This stores the toys, but it does so in a way which is difficult to deal with in a program.  We will see why in a moment.   After you have made these assignments you do some other things in the program and you get to a point where you want to do different things depending on what toys you have.  You’d have to code something like this:

>>> toy0='action figure'
>>> toy1='scooter'

#do a heap of other stuff, which we’re not detailing here!

>>> if toy0 == 'scooter' or toy1 == 'scooter':
...    print 'We can scoot!'
...
We can scoot!

So after doing stuff in the program we come to a decision point with the if statement.   In order to code the  decision point we need to know ahead of time what the names of the individual variables holding the toys are.  Then you can get the computer to check each of the variables to see if either of them is a scooter.  If it is, then it tells us we can scoot.

Your scooter is a little old and you were getting a little bit big for it, so you swap it with your friend at school for a pair of binoculars, so toy1 needs to change:

>>> toy1 = 'pair of binoculars'
>>> print toy0+', '+ toy1
action figure, pair of binoculars

Then, long lost Auntie Annona sends you a late birthday present – a new scooter.  You can’t put in in the toy1 bucket because you’re already storing your binoculars there.  Instead you store it in a new variable toy2 (since there was already something in toy0 and toy1 that you wanted to keep), not where it originally was.   So

>>> toy2 = 'scooter'
>>> print 'my toys are: '+toy0+', '+toy1+', '+toy2+'.'
my toys are: action figure, pair of binoculars, scooter.
>>>

However, since you’ve stored it in a new place your program won’t work properly anymore:

>>> if toy0 == 'scooter' or toy1 == 'scooter':
...    print 'We can scoot!'
...
>>>

Despite having a scooter (and therefore you are scoot-enabled), the program fails to tell you so because it is looking in the wrong place to find it.  The problem here is you won’t know when you write the program how your toys will change over time, so you can’t write the program to anticipate the different changes of toys which may occur – unless, that is, you do the rest of this tute and learn about lists.

Toys as  a List

Let’s implement the same program as a list:

>>> mytoys = ['action figure','scooter']
>>> mytoys[0]
'action figure'
>>> mytoys[1]
'scooter'
>>>

Instead of storing the toys in different variables, a list stores them in different places within the same (list) object.  The first place in a list is (somewhat misleadingly) called number 0.  The second place is number 1, the third number 2 and so on.   Don’t ask why, just accept it.  It’s like some people saying the week starts on a Sunday, and others saying it starts on a Monday.  Here, mytoys[0] (note the square brackets) says ‘show me slot zero of the list called mytoys‘.

We can implement the same code as above and get the same sort of outcome:

>>> if mytoys[0] == 'scooter' or mytoys[1] == 'scooter':
...    print 'We can scoot!'
...
We can scoot!
>>>

Notice how toy0 and toy1 (separate variables) are now mytoys[0] and mytoys[1] (list items). When we swap the scooter for binoculars we can do it like this:

>>> mytoys[1]='pair of binoculars'
>>> mytoys[1]
'pair of binoculars'
>>>

Now, when we get the new scooter from long lost Auntie Annona, we can use one of the clever things about lists: we can just add something to the end of it – we don’t need to add another variable or name it.  In particular, above, in order to call our new variable toy2, we needed to know that the previous one was called toy1.  This is not necessary for lists:

>>> mytoys = mytoys + [‘scooter’]
>>> print ‘my toys are: ‘+mytoys[0]+’, ‘+mytoys[1]+’, ‘+mytoys[2]+’.’
my toys are: action figure, pair of binoculars, scooter.
>>>

Note: we are adding [‘scooter’] (that is, a list [] containing a single item ‘scooter’) not ‘scooter’ (a string) – adding ‘scooter’ will give a type exception (try it and see).

Unfortunately, our conditional still fails with the list:

>>> if mytoys[0] == 'scooter' or mytoys[1] == 'scooter':
...    print 'We can scoot!'
...
>>>

However, if fails because we haven’t been using any list-Fu (ie any special list skills – probably because we haven’t learnt any yet) not because there’s something wrong with lists.  Let’s revisit the earlier code.

One of the really powerful things about lists is you can leave it up to the computer to remember how many things are stored in the list.   So, while I’ve explicitly referenced mytoys[0] and mytoys[1] here,  I could just have easily said simply mytoys and the computer will work out what is in the list:

>>> mytoys = ['action figure','scooter']

>>> mytoys
['action figure', 'scooter']

This turns out to be very important.   Pay attention to the square brackets here, it says this is a list.  Each of the items in the list is separated by a comma ( , <- ie this thing).

Next, lists have a concept of containment.  You can ask the computer to just check whether something is in the list or not, without caring where in the list it is.  So we can rewrite the code like this:

>>> if 'scooter' in mytoys:
...    print 'We can scoot!'
...
We can scoot!
>>>

Wow! Did you see that?  This way of programming means it doesn’t matter how many items are in the list, or where in the list your toy is, this piece of code will always work to find whether it is in the list.

When we swap the scooter for the binoculars we could use our special list skills to do it without knowing where in the list the scooter was, but we won’t for now (try >>> help(list) and the remove method if you’re interested).

>>> mytoys[1]='pair of binoculars'
>>> mytoys[1]
'pair of binoculars'
>>>

Now add the new scooter again:

>>> mytoys = mytoys + ['scooter']
>>> mytoys
['action figure', 'pair of binoculars', 'scooter']
>>>

See how we can print the whole list out without knowing how many entries it has.  Up above we needed to know ahead of time that the variables were called toy0, toy1 and toy2 to print them all out.

Now test whether we can scoot:

>>> if 'scooter' in mytoys:
...    print 'We can scoot!'
...
We can scoot!
>>>

W00t! We can scoot!  This would still work if you received a heap of presents and then got your scooter, so that scooter was at the end of (or hidden in the middle of) a very long list.

Lists (and their use as iterators – something we will look at later) are super important in practically all graphical games. If you can imagine writing something like a space invaders game, you would keep all of the aliens in a list.  As they are shot, you would remove them from the list and as more arrived, you would add them.

Homework

Make up some of your own lists and test whether particular items are in them or not.  Build a list by putting square brackets around a list of entries separated by commas.  If the entries are not numbers, put inverted commas around them to make them strings.  When testing whether a string is in or out, remember to put it in quotes:

>>> numberList = [1,2,3,5,45,345,6]
>>> 345 in numberList
True
>>> 7 in numberList

False
>>> stringList = ['a','this is a string','ho hum','baloney']
>>> 'baloney' in stringList
True
>>> baloney in stringList
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
NameError: name 'baloney' is not defined
>>> 'palaver' in stringList
False

Also try printing your list and printing specific entries:

>>> numberList
[1, 2, 3, 5, 45, 345, 6]
>>> numberList[0]
1
>>> numberList[4]
45
>>> stringList[2]
'ho hum'

WhyPy?

The Zen of Python

>>> import this

(Don’t read it, do it)

What is Python?

Python is a computer programming language. It is named after the comedy act Monty Python (not after the snake of the same name).  It was created by a mathematician called Guido van Rossum.   Python is called a “scripting language” because what is typed by the programmer can be run directly by the computer.  Unlike some other programming languages, Python programs do not need to be “compiled” before they work (actually they do, but the computer does it without you noticing).

Why Python

Ultimately, the reason these tutes are on Python is because Python rocks!!, and it rocks in so many ways:

For a start, the Python language is extremely, sublimely beautiful.  When I say beautiful, I don’t mean in a La Gioconda sort of sense – although it’s code indentation convention does make it visually attractive.  Rather, I mean it in a Galois Theory sort of sense.  That is, it has a beautiful simplicity and consistency from which comes a deep power (don’t expect to understand the Galois Theory reference until you’ve made it to college – I think it is no co-incidence that Guido van Rossum was a mathematician).  As you learn more about how Python does what it does you will constantly think how clever its creators were.

It’s a scripting language – in practical terms this means it is easier for children to understand and implement.

Python uses visual cues (ie indentation) to mark different parts of code.  Other languages use markers like () and {} to mark different parts of code.  This can lead to much difficulty when trying to match any given closing } back to its initiating {.  Particularly where there are multiple levels of code within one another.  In other words, Python programs (including your own) are typically easier to read and understand.

Python is dynamically typed.  In practical terms, this means you don’t need to understand very much about how computers store and manipulate data in order to program in Python.  Other languages make you understand the difference between (say) a string and a number (or between different sorts of numbers) in order to simply define a variable before you even try to store anything in one.   You’d be asleep before we got anywhere in these tutes.

Python is cross platform.  Programs you write in Python can be run on computers running different sorts of hardware or different sorts of operating system without any changes.  Other languages typically involve non-trivial rework.  The language itself is also available on many different architectures and operating systems.

Python is free software.  This means not only can you download a copy for free, but you can look at the source code to see what is going on.   Some people believe that free software is also more ethical than non-free software.

Python has extensions like PyGame.  These mean we can do some fun stuff in the not-too-distant future.

Python has an established community and online documentation if you need it.  So I’m not your only source of knowledge.

There are many other reasons Why Python.   These are just a few.

Some Foundations: Variables and stuff

In some of the earlier tutorials I’ve been using variables without actually explaining what they are.  Strict Python-Zen: within Python there are no variables everything is an object*.   On the assumption that that is too abstract for you, I will explain it a different way, through the use of containers (like trays and buckets) which, if I’m lucky, will preserve at least a little bit of the Python-Zen.

Variables allow you to be flexible.  They are a way of storing something in the computer, much like having a bucket for putting your Lego in.  If you need to go do some chores and just drop your toys, you might not be able to find them again later – or if your parents clean up the toys might get thrown out in the course of garbage collection.   If, instead, you get a plastic bucket out and put them in there, you can rest safe in the knowledge that they’ll be there later after you finish your chores.  Variables are a bit similar.  They’re somewhere that you can put data that the program is using and label it for future reference.  Just like a bucket with the word “My Toys” on the side, you know that, assuming you put it in there earlier, your toys  will be in there next time you look.

Indeed, the name you put on the outside of the bucket doesn’t really affect what you put in it.  You could have the words “toy cars” on a bucket and yet put all your trading cards in there instead.   The point is that the bucket is a safe place to keep your toys.  Variables are a safe place to keep the program’s data.

When you do something like this:

a = 1

It is like putting 1 into a bucket marked a.   You can call variables almost anything – their name can’t contain spaces and can’t start with a number.  There are different conventions used to name things which really should have spaces in them, typically by capitalising a letter:

>>> 2a = 1
 File "<stdin>", line 1
 2a = 1
 ^
SyntaxError: invalid syntax
>>> a b = 1
 File "<stdin>", line 1
 a b = 1
 ^
SyntaxError: invalid syntax
>>> myToys = 1
>>> myToys
1
>>> mytoys = 2
>>> mytoys
2
>>> myToys
1
>>>

There are a couple of things happening here that I want you to notice.  First up are some examples of names which don’t work.  These are 2a (starts with a number) and a b (has a space).   Second I’ve shown another variable name which has a capital in the middle of it (myToys).  Do you see how the middle capital helps you to betterUnderstandWhereTheWordsAreSupposedToBeSplit?  – that is hard to read, but not as hard as betterunderstandwherethewordsaresupposedtobesplit.  I’ve also shown you another variable name with no capitals in it (mytoys).  Can you see that myToys and mytoys are different buckets?  If you put something in the myToys bucket, you won’t find it in the mytoys bucket and vice versa.  Variable names are said to be “case senstive”, because whether you use upper case or lower case matters.

Also, you can’t give variables names which are the same as words in the Python language:

>>> for = 1
 File "<stdin>", line 1
 for = 1
 ^
SyntaxError: invalid syntax
>>> if = 1
 File "<stdin>", line 1
 if = 1
 ^
SyntaxError: invalid syntax
>>> while = 1
 File "<stdin>", line 1
 while = 1
 ^
SyntaxError: invalid syntax
>>>

With buckets you can put different toys in them at different times.   A bucket marked “Cars” might have cars in, or equally it might have some other collection of stuff in it.  The bucket itself doesn’t have a character.  It just holds things.  So, you can put different ‘types’ into a bucket without causing any ruckus:

>>> a = 1
>>> a
1
>>> a = 'hi there'
>>> a
'hi there'
>>>

In this example, we first put a number (1) into a.  Then we put a string (‘hi there’) into it.  In some programming languages this causes a problem, but it doesn’t bother Python.

Finally, I should demonstrate to you that the variable stores the data:

>>> a = 'This is some data.  Will it still be here at the end of the program?'
>>> for i in range(5):
...    print 'doing stuff, time number ',i
...
doing stuff, time number  0
doing stuff, time number  1
doing stuff, time number  2
doing stuff, time number  3
doing stuff, time number  4
>>> a
'This is some data.  Will it still be here at the end of the program?'

The program first put data into a, then did some stuff, then saw that the data was still there, just as we’d expected.  Buckets and other containers play a vital role in keeping your room, the living room, the dining room, the kitchen, the bathroom, the library, the sun room, the garage, the front yard, the back yard, the attic, the space in our bedroom that you sometimes seem to think is yours, that area beside the stairs, and the family room clean of your toys (which seem to have a life of their own in the way they spread themselves around the floor).   So too, variables are extremely useful and play a fundamental role in all Python programs other than the most most basic.

* In Python, variables are actually references to objects.  They are an index telling the computer where in storage to find an object.   This is why you can change the ‘type’ of the thing being ‘held’ by a variable because it’s not really holding anything, it’s just pointing somewhere, and you can change what it’s pointing at.

While

The structure of a while statement is:

while <condition>:
    <do stuff>

The program answers the question: is the condition true or false? If it is true, it does stuff in the <do stuff> section.  When it is finished it goes back up to the top and repeats the process again and again until the condition is false:

>>> a = 10
>>> while a > 0:
...    a = a-1
...    print a
...
9
8
7
6
5
4
3
2
1
0

The ordering here is a little odd because I forgot to print a in the first line.  What is printed is the value of a after 1 has been subtracted from it. Note now that the value stored in  a has been changed while the program did that stuff.  It is now 0 (zero, not that letter in the alphabet after n).

>>> a
0

Anything that can be put in the <condition> part of an if statement can also go in while‘s <condition> statement.

>>> while True:
...    b = raw_input('Type stuff here: ')
...    if b == 'quit':
...         break
...    print 'You typed -> '+b
...
Type stuff here: hi
You typed -> hi
Type stuff here: what's this do?
You typed -> what's this do?
Type stuff here: hello? Is someone there?
You typed -> hello? Is someone there?
Type stuff here: quit
>>>

In this example, we’ve used a weird condition- True.  The computer, when asked the question, “Is True true or is it false?” will have to answer “True is true!”.  It will do this every time the condition is encountered.  Therefore this is a loop which would go on for ever.  Or, it would go on forever if we hadn’t used another instruction break.  What break does, is it ‘breaks’ out of the loop created by while and continues its execution at the next line following the <do stuff> block.  You should be able to see this because it didn’t print out “You typed -> quit” when I typed quit.  That code was skipped.  Break will also work to break out of a loop for the for command.

>>> for a in range(20):
...          print a
...          if a == 10:
...               break
...
0
1
2
3
4
5
6
7
8
9
10

Do you see it broke out of the loop when a was 10?

You can give set up an initial condition before starting the while loop and update it within the loop:

>>> a = 5
>>> while a < 100:
...    print a
...    a = a+10
...
5
15
25
35
45
55
65
75
85
95

But you need to be careful that the loop doesn’t go on forever!  If the program is not responsive try Ctrl-C to stop it:

>>> while True:
...     pass
...

^CTraceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyboardInterrupt

if it wasn’t for the range…

So, let’s combine some of what we’ve learnt from the past few tutorials.  Let’s say we wanted to print all the even numbers from 0 to 20.  We know how to get these numbers by using range(21), but this gives us all the numbers from 0 to 20.  We just want the even ones.

Even numbers are those which have a remainder of 0 when you divide them by two.  Python has  a special operator (called %) which does just this:

>>> 1%4
1
>>> 2%4
2
>>> 3%4
3
>>> 4%4
0
>>> 5%4
1

So for example: 1%4 means “what is the remainder when you divide 1 by 4” (it’s 1).   To test whether a number is even we can see whether this remainder is 0 when the number is divided by 2:

>>> 1%2
1
>>> 2%2
0
>>> 3%2
1
>>> 4%2
0

One is odd, two is even etc.

So to print the even numbers from 0 to 20 we:

get the numbers from 0 to 20 from  a range statement

we use a “for” loop to run over each of the numbers in that range

for each of those numbers we test to see if it is even – and if it is

print the number:

>>> for i in range(21):
...   if i%2 == 0:
...      print i
...
0
2
4
6
8
10
12
14
16
18
20

Please notice that there are three levels of indentation here.  That’s significant because each indicates a code block which relates to the previous statement.

Now try to print out the numbers divisible by 10 between 0 and 100.

And then try to print out the numbers in the sequence 5, 15, 25… up to 95.  This is harder, but you can do it with what’s on this page.

Later we’ll learn that you can do much of this with just range() alone, but that’s for another day.

If only

Sometimes life presents you with challenges.   Some are large and some are small.  How you decide to deal with them has consequences.  Those consequences flow from your decision.  If I eat all my lollies now, I won’t have any after dinner.   If I annoy my friend Ben he won’t invite me over anymore.  If I don’t keep my hands to myself I don’t get the DS.  If I don’t let the dog out when I get up, I don’t get to play computer games. When these conditions are coupled with consequences, they can guide our lives.  Programs are the same.  Not exactly the same, but similar.

Within a program you can direct its flow by using “if”.  The if statement has a particular structure which needs to be followed (called its “syntax”).  The structure of if is as follows:

if :

Don’t worry about the stuff in angle brackets <> at the moment.  The important thing is that the first line starts with “if” and ends with a colon “:”.  No colon and Python will get upset. Further, the code that follows the colon is indented.  That’s important!

>>> time = '5PM'
>>> if time == '5PM':
...    print 'Time to play the computer!!'
...
Time to play the computer!!

So, working through this code… First the string ‘5PM’ is put in the bucket that we’ve called ‘time’.  Then, we’ve compared to see if the time is ‘5PM’.  If it is, then a message is printed (‘Time to play the computer!!!’).

Notice also that we said “time ==”, not “time =”.  That’s because ‘=’ and ‘==’ mean different things to Python.  When you write ‘=’ you are saying to Python, “take the thing on the right and put it in the thing on the left”.  However, when you write ‘==’ you are saying to Python, “these two things are equal – true or false?”

>>> time = '6PM'
>>> if time == '5PM':
...    print 'Time to play the computer!!'
...
>>>

If the condition (in this case: does time equal ‘5pm’) is not true, then the code is not processed.  Here we assigned a different time (actually string)  to time.  When we ran through the condition, Python said “well, that’s false now” so the code didn’t execute.

You can use other sorts of comparisons (like > and <)  in the condition.  They won’t work well in the examples above because time is a string (type), not actually a representation of time.   So if things like this work:

>>> time = '6PM'
>>> if time > '5PM':
...    print 'Time to play the computer!!'
...
Time to play the computer!!

it’s only because of blind luck.  This really won’t work:

>>> time = '6AM'
>>> if time > '5PM':
...    print 'Time to play the computer!!'
...
Time to play the computer!!

In this case, it’s a failure because the message printed when it shouldn’t have (6AM is not later than 5PM, but it printed anyway).  It’s doing this because Python is comparing them as if they were strings (which they are) not as if they were times.  Python is able to compare them as times, but that’s not something we’ll cover here.

We can compare things in lots of ways:

a< b – a is less than b: true or false?

>>> a,b = 1,2
>>> if a < b:
...   print "a is less than b"
...
a is less than b

Did you notice the sneaky way we did two assignments there?  Instead of a=1 and b=2 we said a,b = 1,2.  You can do this too.  Also pay attention to the fact that both a and b are integers, not strings – they have no quotation marks.

a> b – a is greater (or more) than b: true or false?

>>> if a > b:
...   print "a is greater than b"
...

Nothing printed because a is 1, which is less than b, which is 2.

not – this means “not” so if you have another comparison you can negate it:

not a > b  – it is not the case that a is greater than b: true or false? (think it through, it does make sense)

>>> if not a > b:
...   print "it is not true that a is greater than b"
...
it is not true that a is greater than b

a != b the ! (sometimes called a “shriek!” or a “bang!”) here means “not” (strangely this is just “!=”, not “!==” which given what we said about Python and “==” above would make more sense, but also take more typing.  Perhaps Python is just a bit schizophrenic?).   The translation of this is: a is not equal to b: true or false?

>>> if a != b:
...    print "They are not equal"
...
They are not equal

a <= b – a is less than or equal to b: true or false? The other way around (=<) won’t work:

>>> if a <= b: ...   print "a is less than or equal to b" ... a is less than or equal to b >>> if a =< b:
 File "", line 1
 if a =< b:
 ^
SyntaxError: invalid syntax

a >= b – a is greater than or equal to b: true or false?

You can also connect a number of conditions together using “and” and “or”:

>>> if a==1 and b== 2:
...    print 'a equals 1 AND b equals 2'
...
a equals 1 AND b equals 2

>>> if a == 1 or b ==5:
...    print "a equals 1 or b equals 5 (or both)"
...
a equals 1 or b equals 5 (or both)

Try some different combinations.

You can even let Python do some calculations before it compares things:

>>> if 5-1 == 3+1:
...   print "four equals four"
...
four equals four

In fact, Python’s methods of evaluating the conditions you pass it are more many and varied than this.  We may meet them later.  But for the time being note this:

>>> if 1:
...   print "1 is true!"
...
1 is true!
>>> if 0:
...   print "But 0 isn't"
...

Ponder it.

Interacting with raw_input

Python also has a feature which lets you interact with the outside world to get input.  The raw_input() function waits for the user to type some input and press return.  It then gets whatever was typed.

>>> raw_input()
some input
'some input'

It’s not obvious what is going on here.  When you hit return at the end of the first line, a blank line appears.  You type what you want into the line and when you hit enter Python gets the line and (in this case, because we’re in an interactive window) prints what it got.  Do it yourself to see, because the text doesn’t show how it happens.

We might have instead assigned the input to a placeholder:

>>> a = raw_input()
some more input, where is it all going?
>>> # note it hasn't printed anything?
...
>>> a
'some more input, where is it all going?'

In a program this allows us to get information into the program, which might come in handy for maths (aka ‘math’) homework:

>>> a=raw_input()
45
>>> b=raw_input()
23
>>> a+b
'4523'

Ooops!  The input that Python is getting is returned to us as strings.  And strings have a funny form of plus called concatenation.  We can use what we learned earlier to push this input into numbers:

>>> int(a)+int(b)
68

That’s what we were looking for (notice that there are no quotes around 68, because it’s a number now).

We are working in the interactive shell at the moment so the context of what is going on is clear.  However, when running a python program “in the wild” there won’t be that context.  You can add some information for the user if you put a message inside the raw_input brackets.  The message must be a string – so it must have quotes or it must be a variable which holds something which has quotes:

>>> a=raw_input('Enter your number here: ')
Enter your number here: 34

Can you see the string has been reproduced in front of the place you type?  This is called a ‘prompt’ because it prompts you to enter something.

Range and For

>>> range(5)
[0, 1, 2, 3, 4]
>>> for i in range(5):
...   print i
...
0
1
2
3
4
>>>

Strings are not numbers

>>> a='5'
>>> a+1
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
>>> a=5
>>> a+1
6
>>>

Notice that when the number is in quotes ‘5’ it’s not a number anymore (it’s called  a string).   When it doesn’t have quotes it’s treated as a number which can be added.

In fact, the issue isn’t that you can add numbers, but not strings, it’s that ‘5’  and 5 are different ‘types’.  ‘5’ is a string but 5 (no quotes) is an integer.  The two ‘types’ don’t mix. But you can still ‘add’ two strings together:

>>> a='5'
>>> a+'1'
'51'
>>>

Note here though that ‘1’ is not a number, it’s a string (because it has quotation marks around it).  Note also that it’s a sort of addition, but not as we’re used to it.   It’s called ‘concatenation’ which sort of means sticking together end to end.

Try it with some other strings:

>>> a = 'hello'
>>> b = 'there'
>>> a+b
'hellothere'
>>> # hmmmm. maybe I need to add a space?
...
>>> a+' '+b
'hello there'

If you have a string, but want to have a number, Python has a way of trying to push it into a number, called int(). You put the string in the brackets and int will give you a number back if it can.  Sometimes it can’t.

>>> int('5')
5
>>> int('hi there')
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'hi there'
>>>

So, if you ever know you’ve got a number trapped inside a string, you can sometimes still get it out if you remember the int() function.

>>> a = '5'
>>> a+1
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
>>> int(a)+1
6
>>> a
'5'
>>>

See, in this example, that a is still a string, but we’ve managed to push its number out of it.

This is very important as you will often receive numbers hidden in strings and will need to convert them before you can do anything with  them.

Hello world!

(Works for both Python 2.7 and Python 3)
Your first program, for reasons lost to the mists of time, must always be a “hello world!”  If you don’t do it, something bad will happen to you (or one of your friends, relatives, distant relatives, acquaintances or some other citizen of your country).  Believe me, it is scary.

So, to avoid such a horrible fate, repeat after me:

>>> print('hello world!')
hello world!
>>>

Phew! We’re done.    You should notice that the print statement here did something – it printed the letters between the ” (inverted commas) and it printed them on the next line.  Try it for yourself, but remember to press the enter key at the end otherwise nothing will happen.

Congratulations, you’re now a programmer (in training).