Chapter 3: Operators, Expressions, and Program Flow
+++++++++++++++++++++++++++++++++++++++++++++++++++
The focus of this chapter is to go in depth on each of the ways we can evaluate code, and write meaningful blocks of conditional logic. We’ll cover the details of many operators that can be used in Python expressions. This chapter will also cover some topics that have already been discussed in more meaningful detail such as the looping constructs, and some basic program flow.
We will begin by discussing details of expressions. If you'll remember from chapter 1, an expression is a piece of code that evaluates to produce a value.We have already seen some expressions in use while reading through the previous chapters. Here we will focus more on the internals of operators used to create expressions, and also different types of expressions that we can use. This chapter will go into further detail on how we can define blocks of code for looping and conditionals.
Types of Expressions
--------------------
An expression in Python is a piece of code that produces a result or value. Most often, we think of expressions that are used to perform mathematical operations within our code. However, there are a multitude of expressions used for other purposes as well. In Chapter 2, we covered the details of String manipulation, sequence and dictionary operations, and touched upon working with sets. All of the operations performed on these objects are forms of expressions in Python. Other examples of expressions could be pieces of code that call methods or functions, and also working with lists using slicing and indexing..
This chapter will go into detail on how you write and evaluate mathematical expressions, and boolean expressions, and lastly we'll discuss augmented assignment operations that combine two or more operations into one.
Mathematical Operations
-----------------------
The Python language contains all of your basic mathematical operations. This section will briefly touch upon each operator and how it functions. You will also learn about a few built-in functions which can be used to assist in your mathematical expressions. Finally, you’ll see how to use conditionals in the Python language and learn order of evaluation.
Assuming that this is not the first programming language you are learning, there is no doubt that you are at least somewhat familiar with performing mathematical operations within your programs. Python is no different than the rest when it comes to mathematics, as with most programming languages, performing mathematical computations and working with numeric expressions is straightforward.
========== ============= ================================
Operator Description
========== ============= ================================
+ Addition
- Subtraction
* Multiplication
/ Division
// Truncating Division
% Modulo (Remainder of Division)
** Power Operator
~var Unary Invert
+var Unary Plus
-var Unary Minus
========== ============= ================================
Table 3-1: Numeric Operators
Most of the operators in the table above are easily understood. However, division, truncating division, modulo, power, and unary operators could use some explanation. Truncating division will automatically truncate a division result into an integer and rounding down. Modulo will return the truncated remainder of a division operation. The power operator does just what you’d expect as it returns the result of the number to the left of the operator multiplied by itself n times, where n represents the number to the right of the operator.
Division itself is an interesting subject as it's current implementation is somewhat controversial in some rare situations. Division works just as one may expect in most cases. The problem 10/5 = 2 definitely holds true. However, in it's current implementation, division rounds numbers in such a way that sometimes yields unexpected results. There is a new means of division available in Jython 2.5 by importing from __future__. In a standard division for 2.5 and previous releases, the quotient returned is the floor (nearest integer after rounding down) of the quotient when arguments are ints or longs. However, a reasonable approximation of the division is returned if the arguments are floats or complex. Often times this solution is not what was expected as the quotient should be the reasonable approximation or “true division” in any case. When we import *division* from the __future__ module then we alter the return value of division by causing true division when using the / operator, and floor division only when using the // operator. In an effort to not break backward compatibility, the developers have placed the repaired division implementation in a module known as __future__. The __future__ module actually contains code that is meant to be included as a part of the standard language in some future revision. In order to use the new repaired version of division, it is important that you always import from __future__ prior to working with division. Take a look at the following piece of code.
# Works as expected
>>> 14/2
7
>>> 10/5
2
>>> 27/3
9
# Now divide some numbers that should result in decimals
# Here we would expect 1.5
>>> 3/2
1
# The following should give us 1.4
>>> 7/5
1
# In the following case, we'd expect 2.3333
>>> 14/6
2
As you can see, when we'd expect to see a decimal value we are actually receiving an integer value. The developers of this original division implementation have acknowledged this issue and repaired it using the new __future__ implementation.
# We first import division from __future__
from __future__ import division
# We then work with division as usual and see the expected results
>>> 14/2
7.0
>>> 10/5
2.0
>>> 27/3
9.0
>>> 3/2
1.5
>>> 7/5
1.4
>>> 14/6
2.3333333333333335
It is important to note that the Jython implementation differs somewhat from CPython in that Java provides extra rounding in some cases. The differences are in display of the rounding only as both Jython and CPython use the same IEEE float for storage. Let's take a look at one such case.
::
# CPython 2.5 Rounding
>>> 5.1/1
5.0999999999999996
# Jython 2.5
>>> 5.1/1
5.1
Unary operators can be used to evaluate positive or negative numbers. The unary plus operator multiplies a number by positive 1, and a unary minus operators multiplies a number by negative 1. This can be used to obtain the additive inverse of a number. The unary invert works by yielding the bitwise inversion of it's plain or long integer argument. The bitwise inversion of a number x would be evaluated as -(x+1). So if we wanted to find the unary invert of 5, we'd evaluate -(5+1) and the outcome would be -6. Unary inverts only work on integers (not with floats or decimals).The following set of examples will help to clarify these topics.
::
# Performing basic mathematical computations
# Basic mathematical computations
>>> 10 - 6
4
>>> 9 * 7
63
# Division without importing from __future__
>>> 9 / 3
3
>>> 10 / 3
3
>>> 10 // 3
3
>>> 3.14 / 2
1.57
>>> 3.14 // 2
1.0
>>> 36 / 5
7
# Division after importing from __future__
>>> from __future__ import division
>>> 9/3
3.0
>>> 10/3
3.3333333333333335
>>> 10//3
3
>>> 3.14/2
1.57
>>> 3.14//2
1.0
>>> 36/5
7.2
# Modulo returns the remainder
>>> 36 % 5
1
# Using powers, in this case 5 to the power of 2
>>> 5**2
25
# 100 to the power of 2
>>> 100**2
10000
# Unary minus
>>> -10 + 5
-5
>>> +5 - 5
0
As stated at the beginning of the section, there are a number of built-in mathematical functions that are at your disposal.
================= =============================================================== ================
Function Description
================= =============================================================== ================
abs(var) Absolute value
pow(x, y) Can be used in place of ** operator
pow(x,y,modulo) Ternary power-modulo (x **y) % modulo
round(var[, n]) Returns a value rounded to the nearest 10-n or (10**-n)
divmod(x, y) Returns a tuple of the quotient and the remainder of division
================= =============================================================== ================
Table 3-2: Mathematical Built-in functions
::
# The following code provides some examples for using mathematical built-ins
# Absolute value of 9
>>> abs(9)
9
# Absolute value of -9
>>> abs(-9)
9
# Divide 8 by 4 and return quotient, remainder tuple
>>> divmod(8,4)
(2, 0)
# Do the same, but this time returning a remainder (modulo)
>>> divmod(8,3)
(2, 2)
# Obtain 8 to the power of 2
>>> pow(8,2)
64
# Obtain 8 to the power of 2 % 3 ((8 **2) % 3)
>>> pow(8,2,3)
1
# Perform rounding
>>> round(5.67,1)
5.7
>>> round(5.67)
6.0
Comparison operators can be used for comparison of two or more different expressions or variables. Bitwise operators are used to combine two or more expressions together, usually for comparison purposes. As with the mathematical operators described above, these operators have no significant difference to that of Java.
========== ============= =======================
Operator Description
========== ============= =======================
> Greater than
< Less than
>= Greater than or equal
<= Less than or equal
!= Not equal
== Equal
& Bitwise and
| Bitwise or
^ Bitwise xor
~ Bitwise negation
========== ============= =======================
Table 3-3: Bitwise and Conditional Operators
::
# Simple comparisons
>>> 8 > 10
False
>>> 256 < 725
True
>>> 10 == 10
True
# Use comparisons in an expression
>>> x = 2*8
>>> y = 2
>>> while x != y:
... print 'Doing some work...'
... y = y + 2
...
Doing some work...
Doing some work...
Doing some work...
Doing some work...
Doing some work...
Doing some work...
Doing some work...
# Combining comparisons
>>> 3<2<3
False
>>> 3<4<8
True
# Use the bitwise 'and' & operator
>>> x = 4
>>> y = 8
>>> z = 10
>>> if (xz):
... print 'Both expressions are true'
... else:
... print 'At least one expression is not true'
...
At least one expression is not true
>>> y = 12
>>> if (xz):
... print 'Both expressions are true'
... else:
... print 'At least one expression is not true'
...
Both expressions are true
The shift operators can be used as a shorthand notation for multiplying or dividing a number by 2 zero or more times. More specifically, the left shift operator (<<) will multiply a number by two n times, n being the number that is to the right of the shift operator. The right shift operator will divide a number by two n times, n being the number to the right of the shift operator. The __future__division import does not make a difference in the outcome of such operations.
::
# Shift left, in this case 3*2 *1
>>> 3<<1
6
# Equivalent of 3*2*2
>>> 3<<2
12
# Equivalent of 3*2*2*2*2*2
>>> 3<<5
96
# Shift right
# Equivalent of 3/2
>>> 3>>1
1
# Equivalent of 9/2
>>> 9>>1
4
# Equivalent of 10/2
>>> 10>>1
5
# Equivalent of 10/2/2
>>> 10>>2
2
====== === =======================================================================
====== === =======================================================================
x<>n Shift right (The equivalent of dividing the number x by 2, n times)
====== === =======================================================================
Table 3-4 – Shift Operators
Augmented Assignment
--------------------
Augmented assignment operators are those that combine two or more operations into one. While augmented assignment can assist in coding concisely, some say that too many such operators can make code more difficult to read.
>>> x = 5
>>> x
5
# Add one to the value of x and then assign that value to x
>>> x+=1
>>> x
6
# Multiply the value of x by 5 and then assign that value to x
>>> x*=5
>>> x
30
========== ============ ============
Operator Equivalent
========== ============ ============
+= a = a + b
-= a = a – b
*= a = a * b
/= a = a / b
%= a = a % b
//= a = a // b
**= a = a** b
&= a = a & b
|= a = a | b
^= a = a ^ b
>>= a = a >> b
<<= a = a << b
========== ============ ============
Table 3-5: Augmented Assignment Operators
Boolean Expressions
-------------------
Evaluating two or more values or expressions also uses a similar syntax to that of other languages, and the logic is quite the same. Note that in Python, *True* and *False* are very similar to constants in the Java language. *True* actually represents the number *1*, and *False* represents the number *0*. One could just as easily code using 0 and 1 to represent the boolean values, but for readability and maintenance the *True* and *False* “constants” are preferred. Java developers, make sure that you capitalize the first letter of these two words as you will receive an ugly *NameError* if you do not.
Boolean properties are not limited to working with int and bool values, but they also work with other values and objects. For instance, simply passing any non-empty object into a boolean expression will evaluate to *True*. This is a good way to determine whether a string contains anything.
============= ======= =================================================================
Conditional Logic
============= ======= =================================================================
and In an *x and y* evaluation, both x and y must evaluate to True
or In an *x or y* evaluation, if x is false then y is evaluated.
not In a *not x* evaluation, if *not x, *we mean the opposite of x
============= ======= =================================================================
Table 3-6: Boolean Conditionals
As with all programming languages, there is an order of operations for deciding what operators are evaluated first. For instance, if we have an expression a + b *c, then which operation would take place first? All operations are evaluated from left to the right with the exception of the power (**) operator. The order of operations for Python is shown below with those operators that receive the highest precedence shown first, and those with the lowest shown last.
============================================ ====== === ========================= === ================================================== =======================
Operator Precedence from Highest to Lowest Name
============================================ ====== === ========================= === ================================================== =======================
+var, -var, ~var Unary Operations
** Power Operations
*, /, //, % Multiplication, Division, Floor Division, Modulo
+, - Addition, Subtraction
<<, >> Left and Right Shift
& Bitwise And
^ Bitwise Exclusive Or
| Bitwise Or
<, >, <=. >= , <> Comparison Operators
==, !=, is, is not, in, not in Equality and Membership
and, or, not Boolean Conditionals
============================================ ====== === ========================= === ================================================== =======================
Table 3-7: Python Order of Operations
An important note is that when working with boolean conditionals, '*and'* and '*or'* evaluate to the left. Let's take a look at a few examples.
Conversions
-----------
There are a number of conversion functions built into the language in order to help conversion of one data type to another. While every data type in Jython is actually a class object, these conversion functions will really convert one class type into another. For the most part, the built-in conversion functions are easy to remember because they are primarily named after the type to which you are trying to convert.
======================= =================================================================================================================================================================================================
Function Description
======================= =================================================================================================================================================================================================
chr(value) Converts integer to a character
complex(real [,imag]) Produces a complex number
dict(sequence) Produces a dictionary from a given sequence of (key,value) tuples
eval(string) Evaluates a string to return an object…useful for mathematical computations. *Note: This function should be used with extreme caution as it can pose a security hazard if not used properly.*
float(value) Converts number to float
frozenset(set) Converts a set into a frozen set
hex(value) Converts an integer into a hex string
int(value [, base]) Converts to an integer using a base if a string is given
list(sequence) Converts a given sequence into a list
long(value [, base]) Converts to a long using a base if a string is given
oct(value) Converts string representation of integer to octal
ord(value) Converts a character into it’s integer value
repr(value) Converts object into an expression string. Same as enclosing expression in reverse quotes ( `x + y`). Returns a string containing a printable and evaluable representation of the object.
set(sequence) Converts a sequence into a set
str(value) Converts an object into a string Returns a string containing a printable representation of the value, but not an evaluable string.
tuple(sequence) Converts a given sequence to a tuple
unichr(value) Converts integer to a Unicode character
======================= =================================================================================================================================================================================================
Table 3-8: Conversion Functions
::
# Return the character representation of the integers
>>> chr(4)
'\x04'
>>> chr(10)
'\n'
# Convert intger to float
>>> float(10)
10.0
>>> float(8)
8.0
# Convert character to it's integer value
>>> ord('A')
65
>>> ord('C')
67
>>> ord('z')
122
# Use repr() with any object
>>> repr(3.14)
'3.14'
>>> x = 40 * 5
>>> y = 2**8
>>> repr((x, y, ('one','two','three')))
"(200, 256, ('one', 'two', 'three'))"
The following is an example of using the *eval()* functionality as it is perhaps the one conversion function for which an example helps to understand. Again, please note that using the *eval*() function can be dangerous and impose a security threat if used incorrectly. If using the *eval*() function to accept text from a user, standard security precautions should be set into place to ensure that the string being evaluated is not going to compromise security.
::
# Suppose keyboard input contains an expression in string format (x * y)
>>> x = 5
>>> y = 12
>>> keyboardInput = 'x * y'
# We should provide some security checks on the keyboard input here to
::
# for this chapter, but it is good to note that comparisons on the keyboard
::
# evaluation.
::
60
Using Expressions to control Program Flow
-----------------------------------------
. As you’ve learned in previous references in this book, the statements that make up programs in Python are structured with attention to spacing, order, and technique. Each section of code must be consistently spaced as to set each control structure apart from others. One of the great advantages to Python's syntax is that the consistent spacing allows for delimiters such as the curly braces {} to go away. For instance, in Java one must use curly braces around a *for* loop to signify a start and an end point.Simply spacing a *for *loop in Python correctly takes place of the braces. Convention and good practice adhere to using four spaces of indentation per statement throughout the entire program. For more information on convention, please see PEP 8, Style Guide for Python Code (http://www.python.org/dev/peps/pep-0008/). Follow this convention along with some control flow and you’re sure to develop some easily maintainable software.
if-elif-else Statement
~~~~~~~~~~~~~~~~~~~~~~
The standard Python if-elif-else conditional statement is used in order to evaluate expressions and branch program logic based upon the outcome. An if-elif-else statement can consist of any expressions we’ve discussed previously. The objective is to write and compare expressions in order to evaluate to a *True* or *False* outcome. As shown in Chapter 1, the logic for an *if-elif-else* statement follows one path if an expression evaluates to *True*, or a different path if it evaluates to *False.*
You can chain as many *if-else* expressions together as needed. The combining *if-else* keyword is *elif*, which is used for every expression in between the first and the last expressions within a conditional statement.
::
The *elif* portion of the statement helps to ensure better readability of program logic. Too many if statements nested within each other can lead to programs that are difficult to maintain. The initial *if* expression is evaluated, and if it evaluates to *False*, the next *elif* expression is evaluated, and if it evaluates to *False* then the process continues. If any of the *if* or *elif* expressions evaluate to *True* then the statements within that portion of the *if* statement are processed. Eventually if all of the expressions evaluate to *False* then the final *else* expression is evaluated.
These next examples show a few ways for making use of a standard *if-elif-else* statement. Note that any expression can be evaluated in an *if-elif-else* construct. These are only some simplistic examples, but the logic inside the expressions could become as complex as needed.
::
# terminal symbols are left out of this example so that you can see the concise indentation
pi =3.14
x = 2.7 * 1.45
if x == pi:
print ‘The number is pi’
elif x > pi:
print ‘The number is greater than pi’
else:
print ‘The number is less than pi’
Empty lists or strings will evaluate to *False* as well, making it easy to use them for comparison purposes in an *if-elif-else* statement.
# Use an if-statement to determine whether a list is empty
# Suppose mylist is going to be a list of names
>>> mylist = []
>>> if mylist:
... for person in mylist:
... print person
... else:
... print 'The list is empty'
...
The list is empty
while Loop
~~~~~~~~~~
::
Another construct that we touched upon in Chapter 1 was the loop. Every programming language provides looping implementations, and Python is no different. To recap, the Python language provides two main types of loops known as the *while* and the *for* loop. The *while* loop logic follows the same semantics as the *while* loop in Java. The while loop evaluates a given expression and continues to loop through it's defined ta until the results of the expression no longer hold true and evaluate to False. Most while loops contain a comparison expression such as x <= y or the like, in this case the expression would evaluate to False when x becomes greater than y. The loop will continue processing until the expression evaluates to *False*. At this time the looping ends and that would be it for the Java implementationPython on the other hand allows an *else* clause which is executed when the loop is completed.
::
::
>>> x = 0
>>> y = 10
>>> while x <= y:
... print 'The current value of x is: %d' % (x)
... x += 1
... else:
... print 'Processing Complete...'
...
The current value of x is: 0
The current value of x is: 1
The current value of x is: 2
The current value of x is: 3
The current value of x is: 4
The current value of x is: 5
The current value of x is: 6
The current value of x is: 7
The current value of x is: 8
The current value of x is: 9
The current value of x is: 10
Processing Complete...
This *else* clause can come in handy while performing intensive processing so that we can inform the user of the completion of such tasks. It can also be handy when debugging code, or when some sort of cleanup is required after the loop completes
>>> total = 0
>>> x = 0
>>> y = 20
>>> while x <= y:
... total += x
... x += 1
... else:
... print total
... total = 0
...
210
continue Statement
~~~~~~~~~~~~~~~~~~
The *continue* statement is to be used when you are within a looping construct, and you have the requirement to tell Python to *continue* processing past the rest of the statements in the current loop. Once the Python interpreter sees a *continue* statement, it ends the current iteration of the loop and goes on to continue processing the next iteration. The *continue* statement can be used with any *for *or *while* loop.
::
# Iterate over range and print out only the positive numbers
>>> for x in range(1,11):
... if x % 2 != 0:
... continue
... else:
... print x
...
2
4
6
8
10
::
In the example above, the x variable decreased by one each time the loop iterates. On the final pass, as the x is equal to 0 we do not display a message. Why is this example useful? It’s not really…only to give you an understanding of the context in which the *continue* statement would be used.
break Statement
~~~~~~~~~~~~~~~
Much like the *continue *statement, the *break* statement can be used inside of a loop. We use the *break *statement in order to stop the loop completely so that a program can move onto its next task. This differs from continue because the continue statement only stops the current iteration of the loop and moves onto the next iteration. Let’s check it out:
::
::
>>> x = 10
>>> while x >=0:
... if x == 0:
... print 'x is now equal to zero!'
... break
... if x % 2 == 0:
... print x
... x -= 1
...
10
8
6
4
2
x is now equal to zero!
If we are working with a break statement that resides within a loop that is contained in another loop (nested loop construct), then only the inner loop will be terminated.
For Loop
~~~~~~~~
The *for* loop can be used on any iterable object. It will simply iterate through the object and perform some processing during each pass. Both the *break* and *continue* statements can also be used within the *for* loop. The *for* statement in Python also differs from the same statement in Java because in Python we also have the *else* clause with this construct. Once again, the *else* clause is executed when the *for* loop processes to completion without any *break* intervention or raised exceptions. Also, if you are familiar with pre-Java 5 *for* loops then you will love the Python syntax. In Java 5, the syntax of the *for* statement was adjusted a bit to make it more in line with syntactically easy languages such as Python.
::
for(x = 0; x <= myList.size(); x++){
// processing statements iterating through myList
System.out.println(“The current index is: “ + x);
}
::
x = 0
for value in myList:
# processing statements using value as the current item in myList
print ‘The current index is %i’ % (x)
x += 1
As you can see, the Python syntax is a little easier to understand, but it doesn’t really save too many keystrokes at this point. We still have to manage the index (x in this case) by ourselves by incrementing it with each iteration of the loop. However, Python does provide a built-in function that can save us some keystrokes and provides a similar functionality to that of Java with the automatically incrementing index on the *for* loop. The *enumerate(sequence)* function does just that. It will provide an index for our use and automatically manage it for us.
>>> myList = ['jython','java','python','jruby','groovy']
>>> for index, value in enumerate(myList):
... print index, value
...
0 jython
1 java
2 python
3 jruby
4 groovy
If we do not require the use of an index, it can be removed and the syntax can be cleaned up a bit.
>>> myList = ['jython', 'java', 'python', 'jruby', 'groovy']
>>> for item in myList:
... print item
...
jython
java
python
jruby
groovy
Now we have covered the program flow for conditionals and looping constructs in the Python language. . However, good programming practice will tell you to keep it as simple as possible or the logic will become too hard to follow. In practicing proper coding techniques, it is also good to know that lists, dictionaries, and other containers can be iterated over just like other objects. Iteration over containers using the *for* loop is a very useful strategy. Here is an example of iterating over a dictionary object.
# Define a dictionary and then iterate over it to print each value
>>> my_dict = {'Jython':'Java', 'CPython':'C', 'IronPython':'.NET', 'PyPy':'Python'}
>>> for key in my_dict:
... print key
...
Jython
IronPython
CPython
PyPy
It is useful to know that we can also obtain the values of a dictionary object via each iteration by calling my_dict.values().
Example Code
------------
Let’s take a look at an example program that uses some of the program flow which was discussed in this chapter. The example program simply makes use of an external text file to manage a list of players on a sports team. You will see how to follow proper program structure and use spacing effectively in this example. You will also see file utilization in action, along with utiliation of the *raw_input() *function.
# import os module
import os
# Create empty dictionary
player_dict = {}
# Create an empty string
enter_player = ''
# Enter a loop to enter inforation from keyboard
while enter_player.upper() != 'X':
print 'Sports Team Administration App'
# If the file exists, then allow us to manage it, otherwise force creation.
if os.path.isfile('players.txt'):
enter_player = raw_input("Would you like to create a team or manage an existing team?\n (Enter 'C' for create, 'M' for manage, 'X' to exit) ")
else:
# Force creation of file if it does not yet exist.
enter_player = 'C'
# Check to determine which action to take. C = create, M = manage, X = Exit and Save
if enter_player.upper() == 'C':
# Enter a player for the team
print 'Enter a list of players on our team along with their position'
enter_cont = 'Y'
# While continuing to enter new player's, perform the following
while enter_cont.upper() == 'Y':
# Capture keyboard entry into name variable
name = raw_input('Enter players first name: ')
# Capture keyboard entry into position variable
position = raw_input('Enter players position: ')
# Assign position to a dictionary key of the player name
player_dict[name] = position
enter_cont = raw_input("Enter another player? (Press 'N' to exit or 'Y' to continue)")
else:
enter_player = 'X'
# Manage player.txt entries
elif enter_player.upper() == 'M':
# Read values from the external file into a dictionary object
print
print 'Manage the Team'
# Open file and assign to playerfile
playerfile = open('players.txt','r')
# Use the for-loop to iterate over the entries in the file
for player in playerfile:
# Split entries into key/value pairs and add to list
playerList = player.split(':')
# Build dictionary using list values from file
player_dict[playerList[0]] = playerList[1]
# Close the file
playerfile.close()
print 'Team Listing'
print '++++++++++++'
# Iterate over dictionary values and print key/value pairs
for i, player in enumerate(player_dict):
print 'Player %s Name: %s -- Position: %s' %(i, player, player_dict[player])
else:
# Save the external file and close resources
if player_dict:
print 'Saving Team Data...'
# Open the file
playerfile = open('players.txt','w')
# Write each dictionary element to the file
for player in player_dict:
playerfile.write('%s:%s\n' % (player.strip(),player_dict[player].strip()))
# Close file
playerfile.close()
This example is packed full of concepts that have been discussed throughout the first three chapters of the book. As stated previously, the concept is to create and manage a list of sport players and their relative positions. The example starts by entering a *while()* loop that runs the program until the user enters the exit command. Next, the program checks to see if the 'players.txt' file exists. If it does, then the program prompts the user to enter a code to determine the next action to be taken. However, if the file does not exist then the user is forced to create at least one player/position pair in the file. Continuing on, the program allows the user to enter as many player/position pairs as needed, or exit the program at any time. If the user chooses to manage the player/position list, the program simply opens the 'players.txt' file, uses a *for() *loop to iterate over each entry within the file. A dictionary is populated with the current player in each iteration of the loop. Once the loop has completed, the file is closed and the dictionary is iterated and printed. Exiting the program forces the *else()* clause to be invoked, which iterates over each player in the dictionary and writes them to the file.
Unfortunately, this program is quite simplistic and some features could not be implemented without knowledge of functions (Chapter 4) or classes (Chapter 6). A good practice would be to revisit this program once those topics have been covered and simplify as well as add additional functionality.
Summary
-------
All programs are constructed out of statements and expressions. In this chapter we covered details of creating expressions and using them. Expressions can be composed of any number of mathematical operators and comparisons. In this chapter we discussed the basics of using mathematical operators in our programs. The __future__ division topic introduced us to using features from the __future__. We then delved into comparisons and comparison operators.
We ended this short chapter by discussing proper program flow and properly learned about the *if* statement as well as how to construct different types of loops in Python. In the next chapter you will learn how to write functions, and the use of many built-in functions will be discussed.
::