What will we cover?
The 3rd of our fundamental building blocks is branching or conditional statements. These are simply terms to describe the ability of our programs to execute one of several possible sequences of code (branches) depending on some condition.
Back in the early days of Assembler programming the simplest branch was a JUMP instruction where the program literally jumped to a specified memory address, usually if the result of the previous instruction was zero. Amazingly complex programs were written with virtually no other form of condition possible - vindicating Dijkstra's statement about the minimum requirements for programming. When high level languages came along, a new version of the JUMP instruction appeared called GOTO. In fact QBASIC, which can still be obtained from www.qbasic.net still provides GOTO and, if you happen to have QBASIC installed, you can try it out by typing the following bit of code:
10 PRINT "Starting at line 10" 20 J = 5 30 IF J < 10 GOTO 50 40 PRINT "This line is not printed" 50 STOP
The most intuitively obvious conditional statement is the if, then, else construct. It follows the logic of English in that if some boolean condition (see below for more about this aspect of things) is true then a block of statements is executed, otherwise (or else) a different block is executed.
The GOTO example above looks like this in Python:
import sys # only to let us exit print( "Starting here" ) j = 5 if j > 10: print( "This is never printed" ) else: sys.exit()
Hopefully that is easier to read and understand than the previous GOTO example. Of course we can put any test condition we like after the if, so long as it evaluates to True or False, i.e. a boolean value. Try changing the > to a < and see what happens. Also notice the colon (:) at the end of both the if and else lines. As with loops the colon tells Python that a block of code is coming up, and the indentation tells it when the block starts and stops.
VBScript looks quite similar:
<script type="text/vbscript"> MsgBox "Starting Here" DIM J J = 5 If J > 10 Then MsgBox "This is never printed" Else MsgBox "End of Program" End If </script>
It's very nearly identical, isn't it? The main differences are that the word Then is required for the first block and we use End If to indicate the end of the complete if/else construct. (This use of an end marker is a common VBScript idiom, you may recall that we similarly had to use Loop to finish a VBScript Do While loop?)
You might remember that in the Raw Materials section we mentioned a Boolean type of data. We said it had only two values: True or False. We very rarely create a Boolean variable but we often create temporary Boolean values using expressions. An expression is a combination of variables and/or values combined by operators to produce a resultant value. In the following example:
if x < 5: print( x )
x < 5 is the expression and the result will be True if x is less than 5 and False if x is greater than or equal to 5.
Expressions can be arbitrarily complex provided they evaluate to a single final value. In the case of a branch that value must be either True or False. However, the definition of these two values varies from language to language. In many languages False is the same as 0 or a non-existent value (often called NULL, Nil or None). Thus an empty list or string evaluates to false in a Boolean context. Python works this way and this means we can use a while loop to process a list until the list is empty, using something like:
while aList: # do something here
Or we can use an if statement to test whether a list is empty without resorting to the len() function like this:
if aList: # do something here
Finally, we can combine Boolean expressions using Boolean operators which can often cut down the number of if statements we need to write.
Consider this example:
if value > maximum: print( "Value is out of range!" ) else if value < minimum: print( "Value is out of range!" )
Notice that the block of code executed is identical. We can save some work, both for us and for the computer, by combining both of the tests into a single test like this:
if (value < minimum) or (value > maximum): print( "Value is out of range!" )
Notice we combined both tests using a boolean or operator. This is still a single expression because Python evaluates the combined set of tests to a single result. You can think of it as evaluating the first set of parentheses, then the second set of parentheses and finally combines the two calculated values to form the final single value, either True or False. (In practice Python uses a slightly more efficient technique known as short-circuit evaluation which we discuss in the Functional Programming topic)
Very often if we think carefully about the tests we need to carry out in our natural language then we will find ourselves using conjunctions like 'and', 'or' and 'not'. If so there's a very good chance we can write a single combined test rather than many separate ones.
You can go on to chain these if/then/else statements together by nesting them one inside the other. Here is an example in Python:
# Assume price created previously... price = int(input("What price? ")) if price == 100: print( "I'll take it!" ) else: if price > 500: print( "No way Jose!" ) else: if price > 200: print( "How about throwing in a free mouse mat?" ) else: print( "price is an unexpected value!" )
Note 1:we used == (that's a double = sign) to test for equality in the first if statement, whereas we use = to assign values to variables. Using = when you mean to use == is one of the more common mistakes in programming Python, fortunately Python warns you that it's a syntax error, but you might need to look closely to spot the problem.
Note 2:A subtle point to notice is that we perform the greater-than tests from the highest value down to the lowest. If we did it the other way round the first test, which would be price > 200 would always be true and we would never progress to the > 500 test. Similarly if using a sequence of less-than tests you must start at the lowest value and work up. This is another very easy trap to fall into.
<script type="text/vbscript"> DIM Price price = InputBox("What's the price?") price = CInt(price) If price = 100 Then MsgBox "I'll take it!" Else If price > 500 Then MsgBox "No way Jose!" Else If price > 200 Then MsgBox "How about throwing in a free mouse mat too?" Else MsgBox "price is an unexpected value!" End If End If End If </script>
The only things to note here are that there is an End If statement to match every If statement and that we used the VBScript conversion function CInt to convert from the input string value to an integer.
One snag with chaining, or nesting if/else statements is that the indentation causes the code to spread across the page very quickly. A sequence of nested if/else/if/else... is such a common construction that many languages provide a special type of branch for it.
OK, Don't panic! I admit I've been a bit naughty and introduced a few new elements but there's nothing here to worry about. It is really just a slight extension to what you already know. The HTML form at the bottom has two text input fields to capture the length and breadth. The third input field is a new one, it is a drop down list of values and we have attached an onChange attribute that calls a function. All the fields have associated labels. It will look like this:
The first few lines simply create some local variables and convert the form input strings to integers where needed. The bold section is the bit we are really interested in. It selects the appropriate action based on the shape value, notice, by the way, that the parentheses around shape are required. Each block of code within the case structure is not marked using curly braces, as you might expect, but is instead terminated by a break statement. The entire set of case statements for the switch is, however, bound together as a block by a single set of curly braces.
Finally, note the last condition is default which is simply a catch-all for anything not caught in the preceding Case statements. Try it above, it should work provided you fill in the length/breadth before picking a shape!
Why not see if you can extend the example to cover circles as well? Remember to add a new option to the HTML form drop-down as well as a new case to the switch.
VBScript has a case construct too:
<script type="text/vbscript"> Dim shape, length, breadth, SQUARE, RECTANGLE, TRIANGLE SQUARE = 0 RECTANGLE = 1 TRIANGLE = 2 shape = CInt(InputBox("Square(0),Rectangle(1) or Triangle(2)?")) length = CDbl(InputBox("Length?")) breadth = CDbl(InputBox("Breadth?")) Select Case shape Case SQUARE area = length * length MsgBox "Area = " & area Case RECTANGLE area = length * breadth MsgBox "Area = " & area Case TRIANGLE area = length * breadth / 2 MsgBox "Area = " & area Case Else MsgBox "Shape not recognized" End Select </script>
One other feature worth pointing out is the use of Symbolic Constants instead of numbers. That is the uppercase variables SQUARE, RECTANGLE and TRIANGLE are there simply to make the code easier to read. The uppercase names are simply a convention to indicate that they are constant values rather than conventional variables, but VBScript allows any variable name you like.
Python does not provide an explicit case construct but rather compromises by providing a slightly more compact if/else-if/else format:
menu = """ Pick a shape(1-3): 1) Square 2) Rectangle 3) Triangle """ shape = int(input(menu)) if shape == 1: length = float(input("Length: ")) print( "Area of square = ", length ** 2 ) elif shape == 2: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of rectangle = ", length * width ) elif shape == 3: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of triangle = ", length * width/2 ) else: print( "Not a valid shape, try again" )
VBScript also provides a slightly more cumbersome version of this technique with ElseIf...Then which is used in exactly the same way as the Python elif but is less commonly seen since Select Case is easier to use.
This section covers a specific use of branching that I really wanted to discuss back in the Loops topic but couldn't because we hadn't covered if statements at that point. So now we take a short reversion to the topic of loops and see how branching can solve a common looping problem.
There are times when you want to exit a loop before it finishes. To do this most languages provide a mechanism to break the loop execution. In Python this is the break keyword. It can be used in either a for or while loop. Typical uses are where you are searching a list for some value and once you find it you don't need to process any more. Another common case is when you find that your data is corrupted or you hit some kind of error condition (we talk about how to identify errors in a later topic).
One of the most common uses, especially in Python where it has become an accepted idiom (or recognised as a standard practice), is when reading input using a while loop. Meantime here is an example of using break to exit when we find the first zero value in a list of numbers:
nums = [1,4,7,3,0,5,8] for num in nums: print( num ) if num == 0: break # exit the loop immediately print("We finished the loop")
You can see how we test for the exit condition in an if statement and then use break to jump out of the loop.
There is a close relative to break called continue. It is much less commonly used than break and its effect is to exit the body of the loop but, rather than ending the loop completely, it just jumps back to the start of the loop and commences the next iteration. While this can be useful if, for example, you only want to process certain kinds of data. But, you can achieve the same effect with an if condition within your block.
So far many of our examples have been pretty abstract. To conclude let's take a look at an example that uses nearly everything we've learned about so far to introduce a common programming technique, namely displaying menus for controlling user input.
Here is the code, followed by a brief discussion:
menu = """ Pick a shape(1-3): 1) Square 2) Rectangle 3) Triangle 4) Quit """ shape = int(input(menu)) while shape != 4: if shape == 1: length = float(input("Length: ")) print( "Area of square = ", length ** 2 ) elif shape == 2: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of rectangle = ", length * width ) elif shape == 3: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of triangle = ", length * width / 2 ) else: print( "Not a valid shape, try again" ) shape = int(input(menu))
We've added just three lines (in bold) to the previous Python example but in so doing have significantly enhanced the usability of our program. By adding a 'Quit' option to the menu, plus a while loop we have provided the capability for the user to keep on calculating sizes of different shapes until she has all the information she needs. There is no need to rerun the program manually each time. The only other line we added was to repeat the input(menu) shape selection so that the user gets the chance to change the shape and, ultimately, to quit.
What the program does is create the illusion to the user that the program knows what they want to do and does it correctly, acting differently depending on what they input. In essence the user appears to be in control, whereas in fact, the programmer is in control since he has anticipated all the valid inputs and how the program will react. The intelligence on display is that of the programmer, not the machine - computers after all are stupid!
You see how easily we can extend our program just by adding a few lines and combining sequences (the blocks that calculate the area), loops (the while loop) and conditionals (the if/elif structure). Dijkstra's three building blocks of programming. Having covered all three you can, in theory, now go out and program anything, but there are a few more techniques we can learn to make things a bit easier, so don't rush off just yet.
There is one other feature of this program I'd like to pick up on. Notice that we had to repeat the input() line, once before the loop and once inside. Repeating identical code like that is a bad practice because if we ever need to change it we have to remember to change both lines - and that's error prone. There is a trick that we can use based on the break feature that we discussed in the loop topic. The trick involved making the while loop into an infinite loop, that is one which loops forever. Then we test for our exit condition and use break to leave it. It looks like this:
menu = """ Pick a shape(1-3): 1) Square 2) Rectangle 3) Triangle 4) Quit """ while True: shape = int(input(menu)) if shape == 4: break if shape == 1: length = float(input("Length: ")) print( "Area of square = ", length ** 2 ) elif shape == 2: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of rectangle = ", length * width ) elif shape == 3: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of triangle = ", length * width / 2 ) else: print( "Not a valid shape, try again" )
This maxim of minimizing repetition is given a name in programming circles: the DRY principle. For Don't Repeat Yourself!
One form of branching that is very common is where we want to assign a different value to a variable depending on some condition. This is very easily done using a standard if/else condition, like so:
if someCondition: value = 'foo' else: value = 'bar'
However, this is so common that some languages provide a shortcut that is called a conditional expression structure. In Python this looks like:
value = 'foo' if someCondition else 'bar'
Notice the strange syntax in the parentheses? Basically it does the same as the Python version but just uses a more concise set of symbols. Basically it says if the expression before the question mark is true then return the value following the question mark, otherwise return the value after the colon. Notice also that I used parentheses in this example. These aren't required but they often make it more obvious what is going on and I recommend them when using conditional expressions, even in Python.
These kinds of stylistic shortcuts can be convenient but many programmers find them a bit clumsy and prefer not to use them. My personal advice is to use them where it makes sense, usually in simple cases, but avoid them if it starts to make the code look overly complex.
We mentioned in the looping topic that modifying a collection from inside a loop was a difficult thing to do, but never got round to explaining how to do it! The reason is, we had to wait for branching to be explained first. So here is the solution:
If we need to modify the elements of a collection in place we can use a while loop to make the changes as we iterate over it. We can do this because in a while construct we have explicit control over the index, unlike the situation in a for loop where the index is automatically updated. Let's see how to delete all zeros from a list:
myList = [1,2,3,0,4,5,0] index = 0 while index < len(myList): if myList[index] == 0: del(myList[index]) else: index += 1 print( myList )
The thing to note here is that we do not increment the
index if we remove an item, we rely on the deletion moving
everything up so that the old index value now points at the next
item in the collection. We use an if/else branch to
control when we increment the index. It's very easy to make a
mistake doing this kind of thing so test your code carefully.
There is another set of Python functions which are specifically
designed for manipulating list contents and we look at them in
the Functional Programming topic in
the advanced section of the tutorial.
Things to Remember