20130110

We looked briefly at the history of programming languages, and discussed reasons why people create new programming languages, such as
    - new hardware capabilities (for example, multi-core processors)
    - new specialized applications (for example, webpage design)
    - new ideas about "the best" way to write programs (for example, object-oriented programming)

A typical pattern is that when a new language is created, it is deliberately designed to be simple, but as years go by more and more features get added,
until eventually the language is bloated and complicated and people are tired of it ... and then a new language gets invented to get back to simplicity.

Python was invented in 1990 by Guido van Rossum.  So far it has stayed fairly close to his goal of combining lots of power with simple syntax.

Python is an imperative programming language, meaning that Python programs are sets of explicit instructions.  It is also a procedural language, meaning that we
divide our Python programs into self-contained pieces called procedures (often called functions) - we will talk about this next week.

When a computer program is executed, after each instruction is completed the computer needs to know which instruction to perform next.  Python, like a great
many other languages, uses three basic methods for controlling the flow of execution:

Sequence:
    By default, the next instruction to be executed is the one directly following the current instruction.

Selection:
    Using selection, we can choose which of two (or in some languages, which of many) instructions to execute next.  We use some kind of test to decide which
instruction to choose.  This is usually done with an "if" statement, which in Python looks like this:
            if  x > 3:
                print "x is greater than 3"
            else:
                print "x is not greater than 3"

Note that in this example, x must be given a value before the if statement is reached.  After the if statement completes, execution continues with whatever comes next (unless the if statement
is at the bottom of a loop - see Repetition below)

Another example of an if statement, in context:
            x = input("Please enter a number : ")
            if x < 10:
                print "that is less than 10"
            else:
                print "that is not less than 10"
            print "Now the if statement is done"


Note that we can have more than one instruction inside the branches of the if statement:

            x = input("Please enter a number : ")
            if x > 5:
                print "that is greater than 5"
                y = x * 10
                print "10 times your number is ", y
            else:
                print "that is not greater than 5"
                y = x + 2
                print "2 plus your number is ",y
            print "The if statement is complete - both branches continue here"


We can have if statements inside if statements:

            x = input("Please enter a number : ")
            if x > 5:
                print "that is greater than 5"
                y = x * 10
                print "10 times your number is ", y
            else:
                print "that is not greater than 5"
                y = x + 2
                print "2 plus your number is ",y
                if y < 0:
                    print "which is negative"
                else:
                    print "which is not negative"
                print "The nested if statement is complete"
            print "The if statement is complete - both branches continue here"


If you are familiar with languages such as Java or C, the code samples given here may look strange to you because the instructions for each
branch of the if statements do not have "{" and "}" around them.  Python uses vertical alignment to define blocks of code.  The three lines
                print "that is greater than 5"
                y = x * 10
                print "10 times your number is ", y

are all intented exactly the same amount, so they are recognized as being part of the same block of code.  This makes it very easy to read a Python program
and understand where the blocks of code begin and end.  Many Java and C programmers indent their blocks of code anyway - Python makes this habit a rule.

Repetition
    The third control structure is repetition, which means doing a block of instructions over and over.  Python, like many other languages, gives us two ways to do this:  the "for" loop
and the "while"  loop.  In both forms of repetition, when we reach the bottom of the block of instructions we go back to the top and determine whether or not to execute the block of code
again.

For loops are used when we want to execute a block of code for a specific set of values or for a predetermined number of iterations.  For example:

            for x in [2,5,7,9, 22]:
                print x


To execute a loop for a predetermined number of iterations, other languages sometimes use something like
            for x = 1 to 10:
but Python does it differently: we usually use a range object to create a list of the appropriate values of x.  First, let's look at a range object.

            print range(10)

This creates a range object and prints it.  The output is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - the square brackets indicate that this is a list of values. 
You may wonder why the values start at 0 instead of 1 ... the reasons are historical
and will make a bit more sense later in the course ... but only a bit.  I would have been happier if the values did start at 1.  We can force the range object to start at 1 like
this:

            print range(1,11)

The output from this is [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].  Notice that the last value in the range object is always 1 less than the second (or only) value we give it.  We can now
use a range object to create the same result as the "for x = 1 to 10:" that  other languages might use.

            for x in range(1,11):
                print x

Note that for loops can contain any number of statements.

            for num in range(1,101):
                square = num*num
                print num, square


A loop can contain any type of statement, including if statements and loops.  For example

            for value in range(1,76):
                number = value * 3
                if number < 100:
                    print "small"
                else:
                    print "large"
            print "Now the for loop is finished"

The indentation shows that the final print statement is not inside the for loop.  The if statement is inside the loop.  When it completes execution we are at the bottom of the loop - we
do not carry on with the next statement - we go back to the top of the loop to see if the loop needs to execute again.  Only when we are done with the loop do we move on to the final
print statement.