Building Skills in Programming

How To Write Your Own Software Using Python

Steven F. Lott

Creative Commons License; some rights reserved.

This work is licensed under a Creative Commons License. You are free to copy, distribute, display, and perform the work under the following conditions:

  • Attribution. You must give the original author, Steven F. Lott, credit.

  • Noncommercial. You may not use this work for commercial purposes.

  • No Derivative Works. You may not alter, transform, or build upon this work.

For any reuse or distribution, you must make clear to others the license terms of this work.

12/30/2008


Table of Contents

Preface
Why Read This Book?
What Is This Book About?
Audience
Organization of This Book
Conventions Used in This Book
Acknowledgements
I. Getting Started
1. About Computers
Terminology
What is a Program?
Where Is The Program?
Concepts Exercises
2. About Programs
What Happens When a Program “Runs?
The Python Program and What It Does
What is Programming?
Programs Exercises
So How Do They Create Binary Executables?
Concepts FAQ's
3. Let There Be Python
Teminology
Installation FAQ's
4. Two Minimally-Geeky Problems
About Gambling
The Roulette Problem
The Craps Problem
Directions
Problem FAQ's
5. Why Python is So Cool
Core Coolness
Coolness FAQ's
II. Using Python
6. Instant Gratification
The Windows Command Prompt
The Mac OS Terminal Tool
The GNU/Linux Terminal Tool
How Do We Stop?
Your First Conversation in Python: miles per gallon
Decimal-Points and Accuracy
More Conversations on Arithmetic
Parenthesis and Precedence
Long-Winded Statements
More About Punctuation
Conversational Python Exercises
Direct Python Interaction FAQ
7. IDLE Time
The Development Environment
Starting and Stopping IDLE
Using IDLE — Python Shell Window
A Conversation Using IDLE
IDLE Exercises
IDLE Interaction FAQ
III. Arithmetic and Expressions
8. Simple Arithmetic
Plain Integers, Also Known As Whole Numbers
Floating-Point Numbers, Also Known As Scientific Notation
Long Integers — Whole Numbers on Steroids
Mixing Numbers, Some More Rules
Complex Numbers — For The Mathematically Inclined
Strings — Anything Not A Number
Octal and Hexadecimal — Counting by 8's or 16's
Expression Exercises
9. Better Arithmetic Through Functions
Say It With Functions
pow and round Definitions
Multiple Steps
Accuracy?
Another Round, Please
Functions are Factories (really!)
Going the Other Way
Most and Least
Basic Function Exercises
10. Extra Functions: math and random
Meaningful Chunks and Modules
The math Module — Trig and Logs
More math Functions
Misuse and Abuse
The random Module — Rolling the Dice
Extra Function Exercises
Function FAQ's
11. Special Ops
Bits and Bytes
Different Bases and Representations
Operators for Bit Manipulation
The Two Specialized Division Operators
Special Ops Exercises
Special Ops FAQ's
12. Peeking Under the Hood
Execution — Two Points of View
Expression Style Notes
One Way To Tackle Fixed Point Math
IV. Programming Essentials
13. Seeing Results
The print Statement
Dressing Up Our Output
Print Exercises
Print FAQ
14. Turning Python Loose With a Script
Making A Script File
Running Scripts in IDLE
Script Exercises
Scripting FAQ
15. Generalizing a Calculation
Putting Name Tags on Results
The Assignment Statement
Assignment Combo Package
Where Exactly Did We Expect To Be?
Assignment Exercises
16. Assignment Bonus Features
Combining Assignment Statements
More About Python Conversations
Variables and Assignment Style Notes
17. Can We Get Your Input?
Getting Raw Input
Getting More Useful Input
Additional Notes and Caveats
Input Function Definitions
The Standard Files
Simple Input Exercises
The del Statement
Input FAQ
V. Some Self-Control
18. Truth and Logic
Truth
Logic
Exercises in Truth
Truth and Logic FAQ
19. Making Decisions
The Comparison Operators: More or Less
More Sophisticated Comparisons
Taking A Short-Cut
Logic and Comparison Exercises
Comparison FAQ
20. Conditional Processing: Only When Necessary
Conditional Processing
The if Statement
Example if Statements
The elif Condition for Alternatives
The else Condition as a Catch-All
The pass Statement — a Do-Nothing
Condition Exercises
21. Iterative Processing: While We Have More To Do
Iterative Processing
Patterns of Iteration
The for Statement
Multi-Dimensional Loop-the-Loop
Simulating All 100 Rolls of the Dice
The while Statement
Counting Sevens
Iteration Exercises
Iteration FAQ
22. Becoming More Controlling
More Iteration Control: break and continue
The assert Statement
Conditions and Loops Style Notes
The Hidden Dangers of else
A Digression On Design
23. Turning Python Loose with More Sophisticated Scripts
Let Python Run It
Giving the Shell a Hint in GNU/Linux or MacOS
Giving the Shell a Hint — Windows Detailing
Double-Clicking Icons
Another Script Example
Additional Flexibility
Script Exercises
VI. Organizing Programs with Function Definitions
24. Function Definitions — Adding New Verbs
What is a Function, Really?
Function Definition: The def and return Statements
Function Design Patterns — Rules of the Game
Function Example
Hacking Out A Solution
Function Exercises
Optional Function Exercises — Recurrence
25. Flexibility, Clarity and a Close Relative
Flexible Definitions with Optional Parameters
Optional Parameter Example
What About the range Function?
Adding Clarity with Keyword Parameters
Optional and Keyword Parameter Exercises
Object Methods — A Cousin of Functions
Functions Style Notes
26. A Few More Tools
Returning Multiple Values
Keeping Track of Variable Names — The Namespace
Talking About Functions Behind Their Backs
More Function Exercises
The global Statement
VII. Getting Our Bearings
27. Our Course
VIII. Basic Collections of Data: Strings, Lists and Tuples
28. Collecting Items in Sequence
Sequence means “In Order
Working With a Sequence
Subspecies of Sequences
Features of a Sequence
Sequence Exercises
Style Notes
29. Sequences of Characters: Strings
What Does Python mean by “String?
Writing a String in Python
String Factory Functions
Operating on String Data
% — The Message Formatting Operator
Built-in Functions for Strings
Comparing Two Strings — Alphabetical Order
Methods Strings Perform
Modules That Help Work With Strings
Some Common Processing Patterns
String Exercises
30. Doubles, Triples, Quadruples: Tuples!
What Does “Tuple” Mean?
How We Write Tuples
The Tuple Factory Function
Operations on Tuples
Built-in Functions for Tuples
Making Comparisons Between Tuples
Statements and Tuples
Translating From Math To Python: Conjugating The Verb “To Sigma
Tuple Exercises
31. Using Lists To Stay Organized
What Does Python Mean by “List?
How We Write Lists
List Factory Functions
Operations We Perform On Lists
Built-in Functions for Lists
Comparing Two Lists
Methods to Transform Lists
Statements and Lists: Review of for and del
From Outlines to Bank Lines — Stacks and Queues
List Exercises
More Advanced List Exercises
32. Common List Design Patterns
The One-Two Punch: Lists of Tuples
List Construction Shortcuts
Sorting a List: Expanding on the Rules
Tables and Matrices — More Multi-Dimensional Loop-the-Loops
List Processing Exercises
Sequence FAQ's
IX. Additional Processing Patterns — Exceptions and Iterations
33. Exceptions and Unusual Events
What Does Python Mean By “Exception”?
How Do We Handle Exceptional Events?
Exception Handling, Minimal Math Version
Exception Handling, Advanced Math Version
Nested Exception Handling
Some Concrete Examples
Designing Exceptions
Raising The White Flag in Exceptional Situations
A More Complete Example
Debugging an Exception Handler
What the Built-in Exceptions Really Mean
Exception Exercises
Style Notes
Exception FAQ's
34. Looping Back To Look At Iteration
The Iteration Contract — What the for Statement Expects
Customizing Iteration
Generator Definition: The def and yield Statements
Putting Generators To Use
Geeky Generator Example: Web Server Logs
Generator Example: Roulette Spins
Generator Exercises
Iterator and Generator FAQ's
X. More Data Collections: Sets, Mappings, Dictionaries and Files
35. Collecting Items in a Set
What does Python mean by "Set"?
How Do We Create a Set?
Operations We Can Perform On A Set
Comparing Sets: Subset and Superset
Method Functions of Sets
Statements and Sets
Built-in Functions For Sets
Example of Using Sets
Set Exercises
Set FAQ's
36. Mappings and Dictionaries
What Does Python Mean by “Dictionary”?
How We Create A Dictionary
Operations We Can Perform On A Dictionary
Comparing Dictionaries — Not A Good Idea
Method Functions That Dictionaries Offer
Statements and Dictionaries
Built-in Functions That Work With Dictionaries
Dictionary Exercises
Mapping FAQ's
37. Defining More Flexible Functions
A List of Extra Positional Values
A Dictionary of Extra Keyword Values
Dictionary Use Under the Hood
Exercises
Advanced Feature FAQ's
38. Files — The Permanent Record
File Objects — Our Connection To The File System
The File Factory
File Statements: Reading and Writing (but no Arithmetic)
Basic File Exercises
File FAQ's
39. Files II — Beyond the Basics
Methods We Use on File Objects
File Processing with the CSV Module
File Processing Case Studies
Additional File-Related Modules
Advanced File Exercises
40. Files III — The Grand Unification
Additional File-Processing Modules
The Grand Unification of Device Types
Files are the Plumbing of a Software Architecture
XI. Data + Processing = Objects
41. Objects: A Retrospective
The Ubiquitous Object
The Built-in Classes — A Review
Data, Processing and Philosophy — What Does It All Mean?
Object and Class Exercises
Class FAQ's
42. Defining New Objects
Class Definition: The class and def Statements
Class Use: Making New Objects
The State of Being — Instance Variables
At The Starting Line — Setting The Initial Values
Operations — Access and Manipulation
Politics: Collaboration and Responsibility
Keeping Organized
Class Definition Exercises
43. Inheritance, Generalization and Specialization
Leveraging the Superclass — Simplification Through Inheritance
Extending a Class Through Inheritance
Inheriting and Extending a Superclass Method
It's All In the Cards — A Case Study
Advanced Class Definition Exercises
More Class FAQ's
44. Additional Classy Topics
What If It's True For All Members Of The Class?
Built-in Functions for Classes
Simplifying Inherited Functions
Some Examples
Style Notes
45. Special Behavior Requires Special Methods
Looking Under The Hood
Basic Special Method Names
Special Attribute Names
Basic Special Method Exercises
Special Methods FAQs
46. Sophisticated Numbers: Fractions and Currency
What Makes Something Numeric?
How The Numeric Operations Work
Rational Numbers — A Case Study
More Sophistication — Currency Calculations
The Official Rules
Numeric Class Definition Exercises
47. Creating New Types of Collections
Collections: The Superclass
How Do I Make An Object Behave Like A Sequence?
Making It Behave Like A Mapping
Collection Class Definition Exercises
Collection FAQ's
XII. Organizing Programs with Modules
48. Module Definitions — Adding New Concepts
Divide and Conquer with Modules
Defining a Module: Creating Python Files
Using A Module: The import Statement
Some Variations On the import Statement
Thinking In Modules, and the Declaration of Dependence
Module Exercises
Dividing and Conquering — The Art Of Design
Style Notes
Module FAQ's
49. Essential Modules
Overview of the Python Library
Always Useful Modules
Internet Data Structure Modules
50. Fixed-Point Numbers — Doing High Finance
The Problem With Numbers
Using Decimal Numbers
Rounding, known as Quantization
Controlling Rounding
Decimal Exercises
51. Time and Date Processing
Concepts: Point in Time and Duration
The datetime Module
Formal Definitions in datetime
The time module
Formal Definitions in time
Date and Time Exercises
Date and Time FAQ
52. Text Processing and Pattern Matching
How Does Pattern Matching Help Us?
How To Create Patterns Using Regular Expressions
Some Examples
Objects We Use For Pattern Matching and Parsing
Some Debugging Hints
Geeky Text Processing Example: Web Server Logs
Text Processing Exercises
Patterns and Regular Expression FAQ's
XIII. Fit and Finish: Complete Programs
53. Wrapping and Packaging Our Solution
Script or Library? The Main Program Switch
The Standard Command-Line Interface
An Example Program
Main Program Exercises
BTW — The exec Statement
54. Architectural Patterns — A Family Tree
Command-Line Interface Variations
GUI and Web Variations
A. Debugging
Bibliography

List of Figures

1.1. Layers of Abstraction
2.1. The Python Abstract Computer
5.1. C Compiler vs. Python
11.1. The Basic Number Line
11.2. Encoding Signs On The Number Line
24.1. Evaluation of a Function
33.1. How Functions Nest
35.1. Union of Sets, S1|S2
35.2. Intersection Of Sets, S1&S2
35.3. Difference of Sets, S1-S2
35.4. Symmetric Difference, S1^S2
35.5. Subset, S1 in S2
38.1. Python File and OS File

List of Examples

1. Python Example
6.1. Our First Dialog: Miles per Gallon
6.2. Using Floating Decimal Point Numbers
14.1. example1.py
15.1. example3.py
15.2. portfolio.py
15.3. craps.py
16.1. line.py
17.1. rawdemo.py
17.2. stock.py
17.3. inputdemo.py
19.1. floatequal.py
20.1. comeoutroll.py
21.1. table.py
21.2. roll100.py
21.3. countsevens.py
22.1. sixodds.py
23.1. Command Line Execution
23.2. example2.py
23.3. example1 Shell Script
23.4. example1.bat Batch File
24.1. functions.py
24.2. function1.py Initial Version
24.3. function1.py Final Version
25.1. badcall.py
26.1. rolldice.py
26.2. rolldice.py — First Version
26.3. rolldice.py — Second Version
29.1. temperature.py
30.1. Sigma Using a Numeric Index
30.2. Sigma Using an Iterator
33.1. windchill1.py
33.2. windchill2.py
33.3. ckyorn.py
34.1. logScanGenerator.py
38.1. addrpage.py
38.2. name_addr.csv
38.3. nameaddr.py
39.1. stockquote.py
39.2. stocksort.py
39.3. portfolio.py
42.1. die.py
42.2. die.py, version 2
42.3. die.py, version 3
43.1. vehicles.py
43.2. dice.py
44.1. wheel.py
48.1. die.py
48.2. Original File
48.3. New Library Module
48.4. New Application Script
53.1. dicesim.py

List of Equations

8.1. Convert °C (Celsius) to °F (Fahrenheit)
8.2. Convert °F (Fahrenheit) to °C (Celsius)
8.3. Mortgage Payment, version 1
8.4. Mortgage, payments due at the end of each period
8.5. Mortgage, payments due at the beginning of each period
8.6. Surface Air Consumption Rate
8.7. Time and Depth from SACR
8.8. Wind Chill, new model
8.9. Wind Chill, old model
8.10. Sail Clew Load
21.1. Development Effort
21.2. Development Cost
21.3. Project Duration
21.4. Staffing
21.5. Definition of e
21.6. Definition of Factorial, n!
30.1. Basic Summation
30.2. Summation with Half-Open Interval
30.3. Summing Elements of an Array, x
30.4. Mean
30.5. Standard Deviation
46.1. Adding Fractions
46.2. Multiplying Fractions

Preface

The Walrus and the Carpenter. 


"The time has come," the Walrus said,
"To talk of many things:
Of shoes — and ships — and sealing-wax —
Of cabbages — and kings —
And why the sea is boiling hot —
and whether pigs have wings."

--Lewis Carroll

Why Read This Book?

You'll need to read this book when you have the following three things happening at the same time:

  • You have a problem to solve that involves data and processing.
  • You know that the common desktop tools (word processors, spread sheets, databases, organizers, graphics) won't really help. You've found that they require too much manual pointing and clicking, or they don't do the right kinds of processing on your data.
  • You're ready to invest some of your own time to learn the Python language to solve your problem.

Or, perhaps you are tinkerer who likes to know how things really work. For many people, a computer is just an appliance. You may not find this satisfactory, and you want to know more. People who tinker with computers are called hackers, and you are about to join their ranks.

Python is what you've been looking for. It is an easy-to-use tool that can do any kind of processing on any kind of data. Seriously: any processing, any data. Programming is the term for setting up a computer to do the processing you define on your data. Once you learn the Python language, you can solve your data processing problem.

Our objective is to get you, a non-programming newbie, up and running. When you're done with this book, you'll be ready to move on to a more advanced Python book. For example, a book about the Python libraries. You can use these libraries can help you build high-quality software with a minimum of work.

What Is This Book About?

This book is about many things. The important topics include the Python, programming, languages, data, processing, and some of the skills that make up the craft of programming. We'll talk about the core intellectual tools of abstraction, algorithms and the formality of computer languages. We'll also touch on math and logic, statistics, and casino games.

Python. Python is a powerful, flexible toolbox and workbench that can help solve your data processing problem. If you need to write customized software that does precisely what you want, and you want that software to be readable, maintainable, adaptable, inexpensive and make best use of your computer, you need Python.

Here's a very important distinction:

  • Python is a program that does data processing.
  • You control the Python program using the Python programming language.

What does this distinction mean? First, there is an opportunity for us to confuse Python (the program) and Python (the language). We'll attempt to be as clear as we can on the things the Python program does when you give it commands in the Python Language. For people very new to computers, this raises questions like “what is a programming language?” and “why can't it just use English?” and “what if I'm not good with languages?” We'll return to these topics in the section called “Concepts FAQ's”. For now, we'll emphasize the point that the Python language is more precise than English, and also easy to read and write.

The other thing that the distinction between program and language means is that we will focus our efforts on learning the language. The data processing we want to perform will be completely defined by a sequence of statements in the Python language. Learning a computer language isn't a lot different from learning a human language, making our job relatively easy. We'll be reading and writing Python in no time.

Programming. When we've written a sequence of Python statements, we can then use that sequence over and over again. We can process different sets of data in a standard, automatic fashion. We've created a program that can automate data processing tasks. It can replace tedious or error-prone pointing and clicking in other software tools. Or it can do new things that other desktop tools can't do at all.

The big picture is this: the combination of the Python program plus our unique sequence of Python language statements has the effect of creating a new application program for our computer. It means that our new program is built on the existing Python program as its foundation. The Python program, in turn, depends on many other libraries and programs on your computer. The whole structure forms a kind of technology stack, with your program on top, controlling the whole assembly.

Languages. We'll look at three facets of a programming language: how you write it, what it means, and the additional practical considerations that make a program useful. We'll use these three concepts to organize our presentation of the language. We need to separate these concepts to assure that there isn't a lot of confusion between the real meaning and the ways we express that meaning.

The sentences “Xander wrote a tone poem for chamber orchestra” and “The chamber orchestra's tone poem was written by Xander” have the same meaning, but express it different ways. They have the same semantics, but different syntax. For example, in one sentence the verb is “wrote”, in the other sentence it is “was written by”: different forms of the verb to write. While they have the same semantics, the first form is written in active voice, and second form is called the passive voice. Pragmatically, the first form is slightly clearer and more easily understood.

The syntax of the Python language is covered here, and in the Python Reference Manual. Python syntax is simple, and very much like English. We'll provide many examples of language syntax. We'll also provide additional tips and hints focused on the newbies and non-programmers. Also, when you install Python, you will also install a Python Tutorial that presents some aspects of the language, so you'll have at least three places to learn syntax.

The semantics of the language specify what a statement really means. We'll define the semantics of each statement by showing what it makes the Python program do to your data. We'll also be able to show where there are alternative syntax choices that have the same meaning. In addition to semantics being covered in this book, you'll be able to read about the meaning of Python statements in the Python Reference Manual, the Python Tutorial, and chapter two of the Python Library Reference.

In this book, we'll try to provide you with plenty of practical advice. In addition to breaking the topic into bite-sized pieces, we'll also present lots of patterns for using Python that you can apply to real-world problems.

Extensions. Part of the Python technology stack are the extensive libraries. These libraries are added onto Python, which has the advantage of keeping the language trim and fit. Software components that you might need for specialized processing are kept separate from the core language. Plus, you can safely ignore the components you don't need.

This means that we actually have two things to learn. First, we'll learn the language. After that, we'll look at a few of the essential libraries. Once we've seen that, we can see how to make our own libraries, and our own application programs.

Audience

Programming and Computer Skills. We're going to focus on programming skills, which means we have to presume that you already have general computer skills. You should fit into one of these populations.

  • You're new to both computers and programming. We've tried to be as detailed as we can be so that you will be able to follow along gain some basic programming skills. Since we can't cover all of the relevant computer skills, you may need some additional support to be successful.
  • You have good computer skills, but you want to learn to program. You are our target crew. Welcome aboard.
  • You have some programming experience, and you want to learn Python. You'll find that most of Part I, “Getting Started” is something you can probably skim through. We've provided some advanced material that you may find interesting.

What skills will you need? How will we build up your new skills?

Skills You'll Need. This book assumes an introductory level of skill with any of the commonly-available computer systems. Python runs on almost any computer; because of this, we call it platform-independent. We won't presume a specific computer or operating system. Some basic skills will be required. If these are a problem, you'll need to brush up on these before going too far in this book.

  • Can you download and install software from the internet? You'll need to do this to get the Python distribution kit from www.python.org. We'll go through this procedure in some detail. However, if you've never downloaded and installed software before, you may need some help with that skill.
  • Do you know how to create text files? We will address doing this using a program called IDLE, the Python Integrated Development Environment. We will also talk about doing this with a garden-variety text editor like Notepad, TEXTPAD or BBEdit. If you don't know how to create folders and files, or if you have trouble finding files you've saved on your computer, you'll need to expand those skills before trying to do any programming.
  • Do you know some basic algebra? Some of the exercises make use of some basic algebra. A few will compute some statistics. We shouldn't get past high-school math, and you probably don't need to brush up too much on this.

How We Help. Newbie programmers with an interest in Python are our primary audience. We provide specific help for you in a number of ways.

  • Programming is an activity that includes the language skills, but also includes design, debugging and testing; we'll help you develop each of these skills.

  • We'll address some of the under-the-hood topics in computers and computing, discussing how things work and why they work that way. Some things that you've probably taken for granted as a user become more important as you grow to be a programmer.
  • We won't go too far into software engineering and design. We need to provide some hints on how software gets written, but this is not a book for computer professionals; it's for computer amateurs with interesting data or processing needs.
  • We cover a few of the most important modules to specifically prevent newbie programmers from struggling or — worse — reinventing the wheel with each project. We can't, however, cover too much in a newbie book. When you're ready for more information on the various libraries, you're also ready for a more advanced Python book.

When you've finished with this book you should be able to do the following.

  • Use the core language constructs: variables, statements, exceptions, functions and classes. There are only twenty statements in the language, so this is an easy undertaking.
  • Use the Python collection classes to work with more than one piece of data at a time.
  • Use a few of the Python extension libraries. We're only going to look at libraries that help us with finishing a polished and complete program.

A Note on Clue Absorption. Learning a programming language involves accumulating many new and closely intertwined concepts. In our experience teaching, coaching and doing programming, there is an upper limit on the “Clue Absorption Rate”. In order to keep below this limit, we've found that it helps to build up the language as ever-expanding layers. We'll start with a very tiny, easy to understand subset of statements; to this we'll add concepts until we've covered the entire Python language and all of the built-in data types.

Our part of the agreement is to do things in small steps. Here's your part: you learn a language by using it. In order for each layer to act as a foundation for the following layers, you have to let it solidify by doing small programming exercises that exemplify the layer's concepts. Learning Python is no different from learning Swedish. You can read about Sweden and Swedish, but you must actually use the language to get it off the page and into your head. We've found that doing a number of exercises is the only way to internalize each language concept. There is no substitute for hands-on use of Python. You'll need to follow the examples and do the exercises. As you can probably tell from this paragraph, we can't emphasize this enough.

The big difference between learning Python and learning Swedish is that you can immediately interact with the Python program, doing real work in the Python language. Interacting in Swedish can more difficult. The point of learning Swedish is to interact with people: for example, buying some kanelbulle (cinnamon buns) for fika (snack). However, unless you live in Sweden, or have friends or neighbors who speak Swedish, this interactive part of learning a human language is difficult. Interacting with Python only requires a working computer, not a trip to Sweden.

Also, your Swedish phrase-book gives you little useful guidance on how to pronounce words like sked (spoon) or sju (seven); words which are notoriously tricky for English-speakers like me. Further, there are some regional accents within Sweden, making it more difficult to learn. Python, however, is a purely written language so you don't have subtleties of pronunciation, you only have spelling and grammar.

Organization of This Book

This book falls into thirteen distinct parts. To manage the clue absorption rate, the parts are organized in a way that builds up the language in layers from simple, central concepts to more advanced features. Each part introduces a few new concepts. Programming exercises are provided to encourage further exploration of each layer.

Some programming languages (like Pascal or Basic) were specifically designed to help teach programming. Most other programming languages (like Python) are designed for doing the practical work of solving information processing problems. One consequence of this is that Python is a tightly integrated whole. Some features of the language will have both simple and advanced semantics. In many cases some simple-looking features will actually depend on some more advanced parts of the language. This forces us to revisit some subjects several times, first for an introduction, then for more in-depth treatment.

Chickens and Eggs. One subtext woven into this book is the two-sided coin labeled “data processing”. The processing side of the coin reflects the imperative-voice verb statements in the Python language. This active sense of “first do this, then do that” is central to programming. On the other side of the coin, we have the data side, which includes numbers, strings of letters, related groups of values, lists of values and relationships between values. Often, when we think of computer data, we think of files. The way we structure our data is also central to programming.

Data and Processing have a chicken-and-egg relationship. We could cover either of these topics first and get to the other second. In this book, we had to choose and we elected to look at processing first, and then, in Getting Our Bearings, switching over to the data side.

The other topics that weave through this book are the design, debugging and testing skills you'll need to grow. We'll develop these skills through hands-on use, so each chapter has five kinds of information.

  • Concepts, including details on how you say it and what it means.
  • Hands-on Examples, showing what happens when you do it.
  • Debugging Tips, showing what to look for when something goes wrong.
  • Exercises, so you can tackle problems on your own. The book doesn't have solutions, since that would reduce the exercises to looking up the answer and typing it in. For help, you can see the author's web site, homepage.mac.com/s_lott/books.
  • Additional material to point you toward a deeper understanding.

Some Big Problems. There are a couple of problems that we'll use throughout this book to show how you use Python. Both problems are related to casino games. We don't embrace gambling; indeed, as you work through these sample problems, you'll see precisely how the casino games are rigged to take your money. We do, however, like casino games because they are moderately complex and not very geeky. Really complex problems require whole books just to discuss the problem and its solution. Simple problems can be solved with a spreadsheet. In the middle are problems that require Python.

We'll provide some of the rules for Roulette in Chapter 4, Two Minimally-Geeky Problems as well as some of the rules for Craps. We'll look at a couple of interesting casino gambling problems in this chapter that will give us a representative problem that we can solve with Python programming.

Getting Started. Part I, “Getting Started” introduces the basics of computers, languages and Python. Chapter 1, About Computers defines the basic concepts we'll be working with. Chapter 2, About Programs will more fully define a program and the art of programming. Chapter 3, Let There Be Python covers installation of Python. Chapter 4, Two Minimally-Geeky Problems gives an overview of two problems we'll use Python to solve. Chapter 5, Why Python is So Cool provides some history and background on Python.

Using Python. Part II, “Using Python” introduces using Python and the IDLE development environment. We'll cover direct use of Python in Chapter 6, Instant Gratification. We'll cover IDLE in Chapter 7, IDLE Time.

Additional sections will add depth to this material as we explore more of the language. Chapter 14, Turning Python Loose With a Script shows how to control Python with a script of statements. Chapter 23, Turning Python Loose with More Sophisticated Scripts will make use of the Python control statements for more sophisticated scripts.

Processing. Part III, “Arithmetic and Expressions” introduces the basic features of the Python language. Chapter 8, Simple Arithmetic includes the basic arithmetic operations and numeric types. Chapter 9, Better Arithmetic Through Functions introduces the most useful built-in functions. Chapter 11, Special Ops covers some additional operators for more specialized purposes. Chapter 12, Peeking Under the Hood has some additional topics that may help you get a better grip on how Python works.

Part IV, “Programming Essentials” introduces the essential programming constructs for input, processing and output. Chapter 13, Seeing Results shows how to do output with the print statement. Chapter 14, Turning Python Loose With a Script shows how to control Python with a script of statements. Chapter 15, Generalizing a Calculation introduces variables and the assignment statement. We'll cover some additional assignment topics in Chapter 16, Assignment Bonus Features, including multiple assignment and how to make best use of the Python shell. Chapter 17, Can We Get Your Input? shows the two simple input functions.

Part V, “Some Self-Control” introduces the various ways to control which statements execute. Chapter 18, Truth and Logic adds truth and conditions to the language. We'll look at comparisons in Chapter 19, Making Decisions. Chapter 20, Conditional Processing: Only When Necessary adds conditional and Chapter 21, Iterative Processing: While We Have More To Do adds iterative processing statements. In Chapter 22, Becoming More Controlling we'll cover some additional topics in control. Chapter 23, Turning Python Loose with More Sophisticated Scripts will make use of these control statements for more sophisticated scripts.

Part VI, “Organizing Programs with Function Definitions” shows how to define functions to organize a program. Chapter 24, Function Definitions — Adding New Verbs introduces the basic function definition and use. From there we'll look at Extra Functions: math and random. Chapter 25, Flexibility, Clarity and a Close Relative adds some useful features to these basic. Chapter 26, A Few More Tools describes concepts like returning multiple values.

After introducing some basic types of collections in the next part, we'll return to the language topics in Part IX, “Additional Processing Patterns — Exceptions and Iterations”. This will add exceptions in Chapter 33, Exceptions and Unusual Events and generators in Chapter 34, Looping Back To Look At Iteration.

Course Change. Programming is all about data and processing. Up to this point, we've focused on processing. From this point forward, we'll focus on data. Since these are two sides of the same coin, there's no absolute separation, it's only a matter of focus. Getting Our Bearings will clarify this relationship between data and processing.

Data. We'll start covering the data side of data processing in Part VIII, “Basic Collections of Data: Strings, Lists and Tuples”, which is an overview of the sequential collections. Chapter 28, Collecting Items in Sequence extends the data types to include various kinds of sequences. These include Chapter 29, Sequences of Characters: Strings, Chapter 30, Doubles, Triples, Quadruples: Tuples! and Chapter 31, Using Lists To Stay Organized. We'll look at some additional topics in Chapter 32, Common List Design Patterns.

We'll revisit some processing elements in Additional Processing Patterns — Exceptions and Iterations. This will include Exceptions and Unusual Events as well as Looping Back To Look At Iteration.

We'll cover more data structures in Part X, “More Data Collections: Sets, Mappings, Dictionaries and Files”. We'll look at the set in Collecting Items in a Set. Mappings and Dictionaries describes mappings and dictionaries. We'll use the map and sequence structure in Defining More Flexible Functions. Chapter 38, Files — The Permanent Record covers the basics of files. Chapter 39, Files II — Beyond the Basics covers several closely related operating system (OS) services. Chapter 40, Files III — The Grand Unification presents some additional material on files and how you can use them from Python programs.

Organization and Structure. Part XI, “Data + Processing = Objects” describes the object-oriented programming features of Python. Objects: A Retrospective reviews objects we've already worked with. Then we can examine the basics of class definitions in Defining New Objects. In Inheritance, Generalization and Specialization we'll introduce a very significant technique for simplifying programs. Additional Classy Topics describes some more tools that help simplify class definition.

We'll take a first look at how we can write classes that look like Python's built-in classes in Special Behavior Requires Special Methods. Sophisticated Numbers: Fractions and Currency shows how we can build very useful kinds of numbers. We can create more sophisticated collections using the techniques in Creating New Types of Collections.

Part XII, “Organizing Programs with Modules” describes modules, which provide a higher-level grouping of class and function definitions. It also summarizes selected extension modules provided with the Python environment. Chapter 48, Module Definitions — Adding New Concepts provides basic semantics and syntax for creating modules. It also covers the organization of the available Python modules. Chapter 49, Essential Modules surveys the modules you're most likely to use. We'll look at how to handle currency in Fixed-Point Numbers — Doing High Finance. Chapter 51, Time and Date Processing defines the time and calendar modules. Chapter 52, Text Processing and Pattern Matching shows how to do string pattern matching and processing with the re module.

Some of the commonly-used modules are covered during earlier chapters. In particular the math and random modules are covered in the section called “The math Module — Trig and Logs” and the string module is covered in Chapter 29, Sequences of Characters: Strings. Chapter 39, Files II — Beyond the Basics touches on os, os.path, glob, and fnmatch.

Fit and Finish. We finish talking about the fit and finish of a completed program in Part XIII, “Fit and Finish: Complete Programs”. The basics of a complete program are covered in Chapter 53, Wrapping and Packaging Our Solution. Many species of programs are described in Chapter 54, Architectural Patterns — A Family Tree.

Conventions Used in This Book

Here is how we'll show Python programs in the rest of the book. The programs will be in separate boxes, in a different font, often with numbered “callouts” to help explain the program. This example is way too advanced to read in detail (it's part of Chapter 36, Mappings and Dictionaries) it just shows what examples look like.

Example 1. Python Example

combo = { }     1
for i in range(1,7):
    for j in range(1,7):
        roll= i+j
        combo.setdefault( roll, 0 )     2
        combo[roll] += 1
for n in range(2,13):
    print "%d %.2f%%" % ( n, combo[n]/36.0 )   3
1

This creates a Python dictionary, a map from key to value. In this case, the key will be a roll, a number from 2 to 12. The value will be a count of the number of times that roll occurred.

2

This assures that the rolled number exists in the dictionary. If it doesn't exist, it will default, and will be assigned frequency count of 0.

3

Print each member of the resulting dictionary.

The output from the above program will be shown as follows:

2 0.03%
3 0.06%
4 0.08%
5 0.11%
6 0.14%
7 0.17%
8 0.14%
9 0.11%
10 0.08%
11 0.06%
12 0.03%

Tool completed successfully

We will use the following type styles for references to a specific Class, method function, attribute, which includes both class variables or instance variables.

Tip

There will be design tips, and warnings, in the material for each exercise. These reflect considerations and lessons learned that aren't typically clear to starting OO designers.

Acknowledgements

I have to thank all of the people at my employer, CTG, for giving me so many decades of opportunities to practice the craft of programming.

Getting Started

Tools and Toys

This part provides some necessary background to help non-programming newbies get ready to write their own programs. If you have good computer skills, this section may be all review. If you are very new to computers, our objective is to build up your skills by providing as complete an introduction as we can. Computing has a lot of obscure words, and we'll need some consistent definitions.

We'll start with the big picture. In About Computers we'll provide a list of concepts that are central to computers, programs and programming. In About Programs we'll narrow our focus to programs and how we create them.

In Let There Be Python we'll describe how to install Python. You'll need to choose just one of ???, ??? or ???. This chapter has the essential first step in starting to build programs: getting our tools organized.

We'll describe two typical problems that Python can help us solve in Two Minimally-Geeky Problems. We'll provide many, many more exercises and problems than just these two. But these are representative of the problems we'll tackle.

We also provide some history and background to help show why Python is so cool. If you are already convinced that Python is your tool of choice, you can skip Why Python is So Cool. If you've heard about Visual Basic, Java or C++ and wonder why Python is better, you might find something helpful in that section. It involves some computer-science jargon; you've been warned.

Chapter 1. About Computers

Penetrating the Fog of Jargon

Our job as a programmer is to write statements in the Python language that will control our computer system. This chapter describes the basic topics of what a computer is and how we set up a computer to perform a task. We need to be perfectly clear on what computing is so that you can be successful in programming a computer to solve your problems.

In Terminology we'll provide a common set of terms, aimed at newbies who will soon become programmers. The computer industry has a lot of marketing hype, which can lead to confusing use of terms. Worse, the computer industry has some terminology that is intended to make computers easier to use, but really only succeeds in muddying the waters.

We'll build on the terminology foundation in What is a Program? and define a program more completely. This is, after all, our goal, and we'll need to have it clearly defined so we can see how we're closing in on it.

Terminology

We want to clearly define some terms that we'll be using throughout the book. We're going to build up our Python understanding from this foundational terminology. In the computer world, many concepts are new, and we'll try to make them familiar. Further, some of the concepts are abstract, forcing us to borrow existing words and extend or modify their meanings. We'll also define them by example as we go forward in exploring Python.

This section is a kind of big-picture road map of computers. We'll refer back to these definitions in the sections which follow.

Computer, Computer System

Okay, this is perhaps silly, but we want to be very clear. We're talking about the whole system of interconnected parts that make up a computer. We're including displays and keyboards and mice. We're drawing a line between our computer and the network that interconnects it to other computers. Inside a computer system there are numerous electronic components, one of which is the processor, which controls most of what a computer does.

It helps to think of two species of computers: your personal computer — desktop or laptop — sometimes called a “client” and shared computers called “servers”. When you are surfing a web site, you are using more than one computer: your personal computer is running the web browser, and one or more server computers are responding to your browser's requests. Most of the internet things you see involve your desktop and a server somewhere else.

We do need to note that the principle of abstraction is being applied here. A number of electronic devices are all computers on which we can do Python programming. Laptops, desktops, iMacs, PowerBooks, clients, servers, Dells and HP's are all examples of this abstraction we're calling a computer system.

Device, Peripheral Device

We have a number of devices that are part of our computers. Most devices are plugged into the computer box and connected by wires, putting them on the periphery of the computer. A few devices are wireless; they connect using Bluetooth, WiFi (IEEE 802.11) or infrared (IR) signals. We call the connection the interface.

The most important devices are hidden within the box, physically adjacent to the central processor. These central items are memory (called random-access memory, RAM) and a disk. The disk, while inside the box, is still considered peripheral because once upon a time, disks were huge and expensive.

The other peripheral devices are the ones we can see: display, keyboard and mouse. After that are other storage devices, including CD's, DVD's, USB drives, cameras, scanners, printers, drawing tablets, etc. Finally we have network connections, which can be Ethernet, wireless or a modem. All devices are controlled by pieces of software called drivers.

Note that we've applied the abstraction principle again. We've lumped a variety of components into abstract categories.

Memory, RAM

The computer's working memory (Random-Access Memory, or RAM) contains two things: our data and the processing instructions (or program) for manipulating that data. Most modern computers are called stored program digital computers. The program is stored in memory along with the data. The data is represented as digits, not mechanical analogies. In contrast, an analog computer uses mechanical analogs for numbers, like spinning gears that make an analog speedometer show the speed, or the strip of metal that changes shape to make an analog meat thermometer show the temperature.

The central processor fetches each instruction from the computer's memory and then executes that instruction. We like to call this the fetch-execute loop that the processor carries out. The processor chip itself is hardware; the instructions in memory are called software. Since the instructions are stored in memory, they can be changed. We take this for granted every time we double click an icon and a program is loaded into memory.

The data on which the processor is working must also be in memory. When we open a document file, we see it read from the disk into memory so we can work on it.

Memory is dynamic: it changes as the software does its work. Memory which doesn't change is called Read-Only Memory (ROM).

Memory is volatile: when we turn the computer off, the contents vanish. When we turn the computer on, the contents of memory are random, and our programs and data must be loaded into memory from some persistent device. The tradeoff for volatility is that memory is blazingly fast.

Memory is accessed “randomly”: any of the 512 million bytes of my computer's memory can be accessed with equal ease. Other kinds of memory have sequential access; for example, magnetic cassette tapes must be accessed sequentially.

For hair-splitters, we recognize that there are special-purpose computing devices which have fixed programs that aren't loaded into memory at the click of a mouse. These devices have their software in read-only memory, and keep only data in working memory. When our program is permanently stored in ROM, we call it firmware instead of software. Most household appliances that have computers with ROM.

Disk, Hard Disk, Hard Drive

We call these disk drives because the memory medium is a spinning magnetizable disk with read-write heads that shuttle across the surface; you can sometimes hear the clicking as the heads move. Individual digits are encoded across the surface of the disk in separate blocks of data. Some people are in the habit of calling them “hard” to distinguish them from the obsolete “floppy” disks that were used in the early days of personal computing.

Disk memory isn't completely random-access because the read-write heads have to move across the surface and the surface is rotating. There are delays while the computer waits for the heads to arrive at the right position. There are also delays while the computer waits for the disk to spin to the proper location under the heads.

Your computer's disk can be imagined as persistent, slow memory: when we turn off the computer, the data remains intact. The tradeoff is that it is agonizingly slow: it reads and writes in milliseconds, close to a million times slower than dynamic memory.

Disk memory is also cheaper than RAM by a factor of at almost 100: we buy 40 gigabytes (40 billion bytes, or 40,000 megabytes) of disk for $100; the cost of 512 megabytes of memory.

Human Interface, Display, Keyboard, Mouse

The human interface to the computer typically consists of three devices: a display, a keyboard and a mouse. Some people use additional devices: a second display, a microphone, speakers or a drawing tablet are common examples. Some people replace the mouse with a trackball. These are often wired to the computer, but wireless devices are also popular.

In the early days of computers — before the invention of the mouse — the displays and keyboards could only handle characters: letters, numbers and punctuation. When we used computers in the early days, we spelled out each command, one line at a time. Now, we have the addition of sophisticated graphical displays and the mouse. When we use computers now, we point and click, using graphical gestures as our commands. Consequently, we have two kinds of human interfaces: the Command-Line Interface (CLI), and the Graphical User Interface (GUI).

A keyboard and a mouse provide inputs to software. They work by interrupting what the computer is doing, providing the character you typed, or the mouse button you pushed. A piece of software called the Operating System has the job of collecting this stream of input and providing it to the application software. A stream of characters is pretty simple. The mouse clicks, however, are more complex events because they involve the screen location as well as the button information, plus any keyboard shift keys.

A display shows you the outputs from software. The display device has to be shared by a number of application programs. Each program has one or more windows where their output is sent. The Operating System has the job of mediating this sharing to assure that one program doesn't disturb another program's window. Generally, each program will use a series of drawing commands to paint the letters or pictures. There are many, many different approaches to assembling the output in a window. We won't touch on this because of the bewildering number of choices.

Historically, display devices used paper; everything was printed. Then they switched to video technology. Currently, displays use liquid crystal technology. Because displays were once almost entirely video, we sometimes summarize the human interface as the Keyboard-Video-Mouse (KVM).

In order to keep things as simple as possible, we're going to focus on the command-line interface. Our programs will read characters from the keyboard, and display characters in an output window. Even though the programs we write won't respond to mouse events, we'll still use the mouse to interact with the operating system and programs like IDLE.

Other Storage, CD, DVD, USB Drive, Camera

These storage devices are slightly different from the internal disk drive or hard drive. The differences are the degree of volatility of the medium. Packaged CD's and DVD's are read-only; we call them CD Read-Only Memory (CD-ROM). When we burn our own CD or DVD, we used to call it creating a Write-Once-Read-Many (WORM) device. Now there are CD-RW devices which can be written (slowly) many times, and read (quickly) many times, making the old WORM acronym outdated.

Where does that leave Universal Serial Bus USB drives (known by a wide variety of trademarked names like Thumb Drive™ or Jump Drive™) and the memory stick in our camera? These are just like the internal disk drive, except they don't involve a spinning magnetized disk. They are slower, have less capacity and are slightly more expensive than a disk.

Scanner, Printer

These are usually USB devices; they are unique in that they send data in one direction only. Scanners send data into our computer; our computer sends data to a printer. These are a kind of storage, but they are focused on human interaction: scanning or printing photos or documents.

The scanner provides a stream of data to an application program. Properly interpreted, this stream of data is a sequence of picture elements (called “pixels”) that show the color of a small section of the document on the scanner. Getting input from the scanner is a complex sequence of operations to reset the apparatus and gather the sequence of pixels.

A printer, similarly, accepts a stream of data. Properly interpreted, this stream of data is a sequence of commands that will draw the appropriate letters and lines in the desired places on the page. Some printers require a sequence of pixels, and the printer uses this to put ink on paper. Other printers use a more sophisticated page description language, which the printer processes to determine the pixels, and then deposits ink on paper. One example of these sophisticated graphic languages is PostScript.

Network, Ethernet, Wireless, WiFi, Dial-up, Modem

A network is built from a number of cooperating technologies. Somewhere, buried under streets and closeted in telecommunications facilities is the global Internet: a collection of computers, wires and software that cooperates to route data. When you have a cable-modem, or use a wireless connection in a coffee shop, or use the Local Area Network (LAN) at school or work, your computer is (indirectly) connected to the Internet. There is a physical link (a wire or an antenna), there are software protocols for organizing the data and sharing the link properly. There are software libraries used by the programs on our computer to surf web pages, exchange email or purchase MP3's.

While there are endless physical differences among network devices, the rules, protocols and software make these various devices almost interchangeable. There is stack of technology that uses the principle of abstraction very heavily to minimize the distinctions among wireless and wired connections. This kind of abstraction assures that a program like a web browser will work precisely the same no matter what the physical link really is. The people who designed the Internet had abstraction very firmly in mind as a way to allow the Internet to expand with new technology and still work consistently.

Operating System

The Operating System (OS) ties all of the computer's devices together to create a usable, integrated computer system. The operating system includes the software called device drivers that make the various devices work consistently. It manages scarce resources like memory and time by assuring that all the programs share those resources. The operating system also manages the various disk drives by imposing some organizing rules on the data; we call the organizing rules and the related software the file system.

The operating system creates the desktop metaphor that we see. It manages the various windows; it directs mouse clicks and keyboard characters to the proper application program. It depicts the file system with a visual metaphor of folders (directories) and documents (files). The desktop is the often shown to you by a program called the “finder” or “explorer”; this program draws the various icons and the dock or task bar.

In addition to managing devices and resources, the OS starts programs. Starting a program means allocating memory, loading the instructions from the disk, allocating processor time to the program, and allocating any other resources in the processor chip.

When we double click an icon, a fair number of things are going on under the hood. Since we'll be writing our own programs, we'll need to look closely at what is really happening.

Finally, we have to note that it is the OS that provides most of the abstractions that make modern computing possible. The idea that a variety of individual types of machines could be summarized by a single abstraction of “storage” allows disk drives, CD-ROM's, DVD-ROM's and thumb drives to peacefully co-exist. It allows us to run out and buy a thumb drive and plug it into our computer and have it immediately available to store the pictures of our trip to Sweden.

Program, Application, Software

A program is started by the operating system to do something useful. We'll look at this in depth in What is a Program? and What Happens When a Program “Runs?. Since we will be writing our own programs, we need to be crystal clear on what programs really are and how they make our computer behave.

There isn't a useful distinction between words like “program”, “command”, “application”, “application program”, “application system”. Some vendors even call their programs “solutions”. We'll try to stick to the word program. A program is rarely a single thing, so we'll try to identify a program with the one file that contains the main part of the program.

File, Document, Data, Database
The data you want to keep is saved to the disk in files. Sometimes these are called documents, to make a metaphorical parallel between a physical paper document and a disk file. Files are collected into directories, sometimes depicted as metaphorical folders. A paper document is placed in a folder the same way a file is placed in a directory. Computer folders, however, can have huge numbers of documents. Computer folders, also, can contain other folders without any practical limit. The document and folder point of view is a handy visual metaphor used to clarify the file and directory structure on our disk.
Boot

Not footwear. Not a synonym for kick, as in "booted out the door." No, boot is used to describe a particular disk as the "boot disk". We call one disk the boot disk because of the way the operating system starts running: it pulls itself up by it's own bootstraps. Consider this quote from James Joyce's Ulysses: "There were others who had forced their way to the top from the lowest rung by the aid of their bootstraps."

The operating system takes control of the computer system in phases. A disk has a boot sector (or boot block) set aside to contain a tiny program that simply loads other programs into memory. This program can either load the expected OS, or it can load a specialized boot selection program (examples include BootCamp, GRUB, or LiLo.) The boot program allows you to control which OS is loaded. Either the boot sector directly loads the OS, or it loads and runs a boot program which loads the OS.

The part of the OS that is loaded into memory is just the kernel. Once the kernel starts running, it loads a few handy programs and starts these programs running. These programs then load the rest of the OS into memory. The device drivers must be added to the kernel. Once all of the device drivers are loaded, and the devices configured, then the user interface components can be loaded and started. At this point, the "desktop" appears.

Note that part of the OS (the kernel) loads other parts of the operating system into memory and starts them running. It pulls itselfs up by it's own bootstraps. They call this bootstrapping, or booting. The kernel will also load our software into memory and start it running. We'll depend heavily on this central feature of an OS.

What is a Program?

In Terminology we provided a kind of road map to computers. Here, we're going to look a little more closely at these things called “programs”.

What — Exactly — is the Point? The essence of a program is the following: a program sets up a computer to do a specific task. We could say that it is a program which applies a general-purpose computer to a specific problem. Sometimes we call them “application programs” because the programs are applied to definite data processing needs.

There is a kind of parallel between a computer system running programs and a television playing a particular TV show. Without the program, the computer is just a pile of inert electronics. Similarly, if there is no TV show, the television just plays noise and hisses.

We're going to focus on two parts of a program: data and processing. We'll be aiming at programs which read and write files of data, much like our ordinary desktop tools open and save files. We aren't excluding game programs or programs that control physical processes. A game's data is the control actions from the player plus the description of the game's levels and environments. The processing that a game does matches the inputs, the current state and the level to determine what happens next. An interactive game, however, is considerably more complex than a program to evaluate a file that has a list of our stocks.

Program Varietals. At this point, we need to make a distinction between some varieties of programs: specifically, a binary executable and a script. A binary executable or binary application is a program that takes direct control computer's processor. We call it binary because it uses the binary codes specific to the processor chip inside the computer. If you haven't encountered “binary” before, see Binary Codes. Most programs that you buy or download fit this description. Most of the office applications you use are binary executables (NeoOffice/J is the notable exception.) A web browser, for example, is a binary executable, as is the python program (named python.exe in Windows.)

Your operating system (for example, Windows or GNU/Linux or MacOS) is a complex collection of binary executables. Primarily, when the computer starts running, a “kernel” of binary software is loaded; this kernel controls everything that goes on in the computer. Once this kernel of software is running, it then loads a number of additional programs that constitute the working operating system with which we interact. These programs don't solve any particular problem, but they enable the computer to be used by non-engineers.

A binary executable's direct control over the processor is beneficial because it gives the best speed and uses the fewest resources. However, the cost of this control is the relative opacity of the coded instructions that control the processor chip. The processor instruction codes are focused on the electronic switching arcana of gates, flip-flops and registers. They are not focused on data processing at a human level. If you want to see how complex and confusing the processor chip can be, go to Intel or AMD's web site and download the technical specifications for one of their processors.

One subtlety that we have to acknowledge is that even the binary applications don't have complete control over the entire computer system. Recall that the computer system loads a kernel of software when it starts. All of the binary applications outside this kernel do parts of their work by using program fragments provided by the kernel. This important design feature of the operating system assures that all of the application programs share resources politely. One of the kernel's two jobs is to coordinate among the application programs. If every binary application simply grabbed resources willy-nilly, one badly behaved program could stop all other programs from working. Imagine the tedium of quitting your browser to make notes in your word processor, then quitting your word processor to go back to your web browser. The other of the kernel's two jobs is to embody the abstraction principle and make a wide variety of processors have a nearly identical set of features.

Layers of Abstraction. Let's take a close look at our metaphor again. We said there is a strong parallel between a computer running a program and a TV playing a particular TV show. We now have two layers of meaning here:

  • The whole computer system running programs — in a very broad sense — is like a TV playing a particular show. This is the most abstract view, combining many concepts together.
  • At a more detailed view, we have a composite concept of computer system plus Operating System. It is this hardware-plus-software device which runs our application programs. Here, our TV metaphor starts to break down because we don't have to get a kernel TV show that allows our TV to watch a specific channel. Our TV is complete by itself. Our computer, however, can't do anything without some software. And we need some kernel of OS software to help us run our desired application software.

Figure 1.1. Layers of Abstraction

Layers of Abstraction

Where Is The Program?

Our programs (and our data) reside in two places. When we're using a program, it must be stored in memory. However, memory is volatile, so when we're not using a program, it must reside on a disk somewhere. Since our disks are organized into file systems, we find these programs residing in files.

When we look at the various files on our computer, we'll see a number of broad categories.

  1. Applications or Programs. These are executable files, they will control the computer-plus-operating system abstract machine. There are two kinds of programs:

    1. Binary Executable programs use the processor chip's binary codes. We use these, but won't be building them.

    2. Script programs use a script language like Python. We'll build these.

  2. Documents. Our OS associates each document with a program. This is a convenient short-cut for us, and allows us to double-click the document and have the proper program start running.

When we use the Finder's Get Info to look at the detailed information for an application icon in MacOS or GNU/Linux, we can see that our application program icons are marked “executable” and the file type will be “application”. In Windows, a binary executable program must have a file name that ends with .exe (or .com, but this is rare).

Starting A Program. Our various operating systems give us several user interface actions that will load a program into memory so that we can start to use it. Since starting a program is the primary purpose of an operating system, there are many ways to accomplish this.

  • Double click an application icon
  • Double click a document icon
  • Single click something in the dock or task bar
  • Click on a run... menu item in the Start... menu
  • Use the Windows Command Prompt; in GNU/Linux or the MacOS it is called a terminal. Through the terminal window we interact with a shell program that allows us to type the name of another program to have that started.

All of these actions are just different ways to get the operating system to locate the binary executable, load it into memory and give it the resources to do its unique task.

All of these choices boil down to two overlapping paths to a starting a binary executable:

  • From the application icon. In this case, we clicked the icon that represents the binary application itself. The OS loaded the binary application and started it. Once started, some programs will open a blank document, some will give you a window that lets you pick what you want to do. Others may have saved a preferences file that identifies what document you last worked with and open that document for you when they start. This varies a great deal, there is no single rule to capture the wide variations in start-up behavior of programs.

  • From a document icon. In this case, we clicked on an icon that represents a document; the document is associated with a specific binary program. The OS uses this association to find and start the appropriate program. The OS also provides the binary program with the name of the document file we clicked so that the program can open the document for you. This provides the easy-to-use experience of clicking on your document and being able to make changes to it.

Concepts Exercises

  1. Inventory Your System. It helps to inventory the various devices and interfaces on your computer system. Start with the central processor (which may hang behind the display on some iMac's), and work your way around your desktop to identify each part.

    Use your word processor to write down all of the computer system parts. You'll need a folder for your Python programming projects. Create that folder; this inventory will be the first file in that folder.

  2. Get Info/Properties. Find your web browser application. You may have a desktop shortcut, or a MacOS dock icon, a Windows start menu icon or a Windows toolbar icon for your browser.

    In Windows, you can ask for the properties of an application icon. If it is a short cut, you can use the Find Target... button to locate the real application file. With MacOS, you can use control-click to get information on a particular icon.

    In the MacOS, you can ask for the information about an application icon. In the MacOS Finder, you can click on an application icon and then use the File->Get Info... to get information on an icon.

  3. Get Info/Properties. Locate a file you made with your favorite word processor. The first exercise in this section was an opportunity to make a new document file.

    In Windows, you can ask for the properties of a document icon. If it is a short cut, you can use the Find Target... button to locate the real application file. With MacOS, you can use control-click to get information on a particular icon. The properties name the application that is associated with this document. In Windows, you can see the Type of File and Opens With information about the file.

    Using MacOS, you can ask for information about a document icon. In the MacOS Finder, you can click on an application icon and then use the File->Get Info... to get information on an icon. The information has a Kind description. The Open With label shows the application that will open this document.

Chapter 2. About Programs

Defining Our Goals

Our job as a programmer is to create programs, which are statements in the Python language. When we run those programs, they will control our computer system to do the data processing we specified. This chapter takes a closer look at what a program is and what is means to “run” a program. This will lead us to the program named python (or python.exe) and how we control it with statements in the Python language.

We'll look closely at what our computer does when it runs a program in What Happens When a Program “Runs?. Based on this, we can look at the Python program in The Python Program and What It Does. Our job, as programmer, is examined in What is Programming?.

We'll provide a little bit of advanced material in So How Do They Create Binary Executables?. This advanced material may not help you learn the Python language. However, for some people, it fills in some necessary background on how the Python program really works. We'll also answer some questions in Concepts FAQ's.

What Happens When a Program “Runs?

In the section called “What is a Program?” we looked at what a program is. Here we'll look at what it means when the operating system runs a program. After this, we can revisit Python, and define what a script program is in the section called “The Python Program and What It Does”.

Computer use is a goal-directed activity. When we're done using our software, we've finished some task and (hopefully) are happy and successful. We can call this a state change. Before we ran our program, we were in one mental state: we were curious about something or needed to get some data processing done. After we ran our program, we were in a different mental state of happy and successful. For example, we got the total value of our stock portfolio from a file of stock purchases.

We like this “state of being” view of how programs work. We can think of many things as state changes. When we clean our office, it goes from a state of messy to a state of clean (or, in my case, less messy). When we order breakfast at the coffee shop we go through a number of state changes: from hungry to waiting for our toast, to eating our toast, to full and ready to start the day.

Let's work backwards to see what had to happen to get us to a happy and successful state of being.

Success! The program has done the desired job, cleaned up, and we are back looking at the operating system interface (the Finder, Explorer or a Terminal prompt). We say that the program has reached a terminating state. Therefore, one goal of programming is to create a program that finishes it's work normally so that the operating system can deallocate the resources and regain control of our computer.

Running. The program is running, doing the job we designed it to do. Perhaps it is controlling a device or computing something. The program is undergoing a number of internal state changes as it moves from its initial or start-up state to its terminating state. Often it reaches terminating state because we clicked the Quit menu item. Another goal of programming, then, is to have the program behave correctly when it is running.

Starting. The operating system loads the program into memory from files on a disk. The operating system may load additional standard modules that the program requires. The operating system also creates a schedule for our program. Most operating systems interleave several activities, and our program is only one of many programs sharing the time and memory of the computer. Once everything is in place we see it start running. Another goal of programming is to have a program that cooperates with the operating system to start in a simple way and follow all the rules for allocating resources.

We'll think about programming from a number of viewpoints. This sequence of activities is one point of view: we see a program go through start-up, processing and termination. This isn't the only viewpoint, we'll look at several others. Sometimes we call this the dynamic view of our program because it reflects the various changes in state.

The Python Program and What It Does

In the section called “What is a Program?” we noted the difference between a binary executable and a script. We defined a binary program as using codes that are specific to our processor chip and operating system. A script, on the other hand, is written in an easy-to-read language like the Python language. It turns out that they are intimately intertwined because the scripts depend on a binary executable.

The Python program, python or python.exe, is described as an interpreter. The Python program's job is to read statements in the Python language and execute those statements. For historical reasons, this process is called “interpreting” the program. You might think that an interpreter should be translating the program into another language; after all, that's what human interpreters do. Software people have bent the meaning of this term, and the process of executing a script is called interpreting.

Ultimately, everything that happens in a computer is the result of the processor executing it's internal binary instructions. In the case of Python, the python program contains a set of binary instructions that will read the Python-language statements we provide and execute those statements.

Looking Under the Hood. This is the real story behind the two kinds of executable programs we run on our computers.

  • A binary executable program uses the processor's instruction and controls the computer directly.
  • A script uses some language to control a binary executable program; the binary executable program controls the computer. The script's control over the computer is indirect.

At this point our TV playing a TV show metaphor (from Chapter 1, About Computers) is starting to look a little shabby. Originally, we said there is a parallel between a computer running a program and a TV playing a particular TV show. With computers, however, we have three layers of meaning.

  • The computer system running programs — in a broad and general sense — is like a TV set playing a TV show.
  • The computer system running the Operating System program can be viewed as a single device. The computer hardware combined with the operating system software makes a new, abstract device. The composite (hardware-plus-software) device runs our application software.
  • The computer system plus the Operating System plus the Python program can be viewed as a single device. This multi-layered device is what runs the application scripts that we write. This isn't very much like TV at all: we never tune to one channel (the operating system) that enables us to watch another channel (Python) that finally lets us watch the video we made with our own video camera.

Software builds up in stacks and layers, based on the principle of abstraction. TV simply switches channels. It looks like computers are so strange that metaphors will only cause more confusion. There aren't many things that are like computer systems where the behavior we see is built up from independent pieces. We can't really talk about them metaphorically, which makes computers a unique intellectual challenge.

Here's a picture that shows the abstract Computer-Plus-Operating system. In one case, it is controlled by a binary executable. In other case, it is controlled by Python, and our Python-language program controls Python.

Figure 2.1. The Python Abstract Computer

The Python Abstract Computer

Bottom Line. When we write Python-language statements, those statements will control the Python program; the Python program controls the OS kernel; the OS kernel controls our computer. These are the most obvious and influential layers of abstraction. It turns out that there are other parts of this technology stack, but we can safely ignore them. The OS makes hardware differences largely invisible; and Python makes many OS differences invisible.

The cost of these layers of indirection is programs that are somewhat slower than those which use the computer's internal codes. The benefit is a huge simplification in how we write and use software: we're freed from having to understand the electro-techno-mumbo-jumbo of our processor chip and can describe our data and processing clearly and succinctly.

Running our Python-language Programs. Remember that the Python program's job is to read statements in the Python language and execute those statements. Our job as a programmer is to write the statements that tell the Python program what to do.

From the operating system's point of view, all of our various Python programs and tools are really just the python program. When you double click the file you created (usually a file with a name that ends in .py) this is what happens under the hood. Let's pretend you're running a program you wrote named roulette.py.

  1. The OS looks up the binary executable associated with the roulette.py file. This is the Python program, python or python.exe.
  2. The OS loads the binary executable Python program, allocates resources and starts it running. It uses the kernel to share these resources politely with all other programs.
  3. The OS provides the file name you double-clicked (roulette.py) to the Python program.
  4. The Python program reads the roulette.py file and executes the Python language statements it finds.
  5. When the statements are finished the Python program has nothing more to do, so it terminates.
  6. The OS releases the resources allocated to the Python program.

Additional Factoids

The Python program was written in the C language and then compiled into a binary executable that is specific for your hardware chip and operating system. That's why the RPM's for Python have names that include “i386” for Intel 80386-compatible chips and “fc3” for Fedora Core 3 GNU/Linux. While a bit beyond our scope, we'll talk about this a little in the section called “So How Do They Create Binary Executables?”.

What is Programming?

While the coffee-shop answer is “programming is how we create programs”, that doesn't help very much. We can identify a number of skills that are part of the broadly-defined craft of programming. We'll stick to two that are foundational: designing Python statements and debugging problems with those statements. Design comes in a number of levels of detail, and we'll work from the smallest level up to larger and more inclusive levels

We take much of our guidance on this from Software Project Management [Royce98]. Royce identifies four stages of software development, with distinct kinds of activities and skills.

  • Inception. We start out by defining the problem and an overview of the solution. The central skills here are observing the problem and writing a clear, simple description of what is wrong and how software will fix it. If we clearly state our problem, then all of the rest of the programming activities are directed at a single goal.

    If we aren't clear on what we're trying to accomplish, we're very likely to go astray at this point. It's more important to clearly define the problem than it is to try and design software. We'll get to the software design in stages. We need the problem defined or we'll never get anywhere.

  • Elaboration. We elaborate our solution into solid description of what we will need to buy, what we will build and what we will download from the open source community. We use design and architecture skills to create a solution to our problem. We need to be sure that our elaborated solution really will solve our problem. We also need to be sure that the cost is appropriate for the value we will create.

    This is rarely shows up as a single good idea for a Python program. Instead, this is often a series of experiments where we imagine something that would solve the problem, and then try to design a more complete solution. It takes a lot of practice to imagine something that can be written as a Python program. We'll guide you through that imagination process a number of times.

  • Construction. This is where we create our Python language statements and put them into module files and script files. Here we are building the solution that we designed during the elaboration stage. We can decompose construction into several things: the Python language skills, testing our programs to make sure they work, and debugging our programs to find out why they don't work.

  • Transition. Our programs have to make the transitions from engineering effort to useful tool. That means they have to be installed on a computer where they can be used. Here is where the problem we started with in inception is actually solved by using the software.

    We know that we've done this phase well when we have a nice file that we can double-click, or run from the Terminal window that does the job we imagined and solves the original problem.

We're going to focus on two skills in this book: creating Python language statements, and debugging problems when we make mistakes. Testing is a rich subject; it would double the size of this book to talk about appropriate testing techniques. The analytical skills for inception and elaboration don't require knowledge of Python, just common sense and clear thinking.

Programs Exercises

  1. Operating System and Platform. To successfully download and install software on your computer, you'll need to know your operating system information. It can also help to know your processor chip information.

    • Windows. You get to the control panels with Start->Settings->Control Panel. One of your control panels is the System control panel. When you double-click this, it shows the operating system and computer information.

    • MacOS. In your Applications folder, you have a Utilities folder. One of these utilities is the System Profiler. Double-click this icon to see a complete description of your Macintosh, including the operating system and processor chip information.

    • GNU/Linux. There are two relevant commands for examining your GNU/Linux architecture: arch and uname. The arch command prints a simple architecture string, like i686 to tell you about the processor chip. The uname -i command shows a similar string for the “platform”, which is the general family for your processor. In my case, it is a “i386”, one of the Intel processors.

  2. Other Applications. What other applications are installed on your computer?

    • Windows. Your Start menu lists a number of programs. This isn't the complete list, since the Windows operating system has a number of additional binary programs tucked away in places where they don't appear on the start menu.

      You get to the control panels with Start->Settings->Control Panel. One of your control panels is the Add/Remove Programs control panel. When you double-click this, it shows many of the application programs that you've installed on your computer.

    • MacOS. In your Applications folder, you have a Utilities folder. One of these utilities is the System Profiler. Double-click this icon to see a complete description of your Macintosh, including the list of application programs.

    • GNU/Linux. There are a number of standard places where GNU/Linux application programs are kept. You can use the ls command to look at directories like /bin, /usr/bin, /usr/local/bin. Notice the common theme to the directory names: bin is short for binary, as in binary executable.

So How Do They Create Binary Executables?

This is a useless digression. It may help you understand how the team that wrote the Python program did it. It can help you demystify programming. It may not help you learn the Python language, so feel free to skip it.

Binary executable files are created by a program called a compiler. A compiler translates statements from some starting language into the processor's native instruction codes. This leads to blazing speed. This approach is typified by the C language. One consequence of this is that we must recompile our C language programs for each different chip set and operating system.

The C language isn't terribly easy to read. The language was designed to be relatively easy for the compiler to read and translate. It reflects an older generation of smaller, slower computers.

The GNU Tools. For the most part, the GNU C Compiler and C language libraries are used to write binary executables like Python. The C language has been around for decades, and has evolved a widely-used style that makes it appropriate for a variety of operating systems and processors. The GNU C compiler has been designed so that it can be tailored for all processors currently used to build computers. Many companies make processors, include Intel, National Semiconductor, IBM, Sun Microsystems, Hewlett-Packard, and AMD. The GNU C Compiler can produce appropriate binary codes for all of these various processor chips.

In addition to the processor (or “chip architecture”), binary executables must also be specific to an operating system. Different operating systems provide different kernel services and use different formats for their binary executable files. Again, the GNU C Compiler can be made to work with a wide variety of operating systems, producing binary executable files with all the unique features for that operating system.

The ubiquity of the GNU C compiler leads to the ubiquity of Python. By depending on the GNU C compiler, the authors of Python assured that the python program can be compiled for any processor chip and any operating system.

Concepts FAQ's

1. What is a programming language?
2. Why can't programming be done in English?
3. What if I'm no good with languages?
4. Why is the terminology so confusing?
1.

What is a programming language?

This is actually a complex question that exposes the very heart of computing. The essence of a computer is the processor chip. This chip is a very complex electronic circuit built up from a number of simpler circuit elements that we'll call “flip-flops”. A flip-flop is either on or off and can be flipped on or off electrically. There are a number of kinds of flip-flops with different electronic connections to flip (or flop) and finding out if the circuit is flipped or flopped. In addition to flip-flops are logic gates to do things like determine if two flip-flops are on at the same time (“and”) or if one of two flip-flops is on (“or”).

The designers of computers will often group the flip-flops into bunches and call them registers. These register specific values or conditions within the processor. For example, one register may contain the memory address of the next instruction to fetch. Another register might have a numeric value on which we are calculating. Another register might be a clock that counts up automatically from zero when the processor is turned on.

A computer's memory, it turns out, is just a collection of billions of flip-flops.

The processor chip does two things: it fetches instructions from memory, and executes those instructions. The fetching part is a relatively simple process of reading data from the memory chips and changing registers to reflect that instruction. The execution part is more complex, and involves changing the state of other flip-flips based on the instruction itself, data in memory and the state of the various processor registers.

The instructions in memory form a kind of “language” for controlling the processor. At this level, the language is very primitive. Since it is narrowly focused on the ways the processor works, it is almost incomprehensible. The language can only express a few simple imperative commands in a simple, but precise form.

The idea that computers are controlled with a kind of language is an example of an abstraction that has immense and far-reaching consequences.

  • It lets us translate from more expressive languages into the machine's native language. We call this kind of translator a compiler.
  • It lets us design more expressive languages that better describe the problems we are trying to solve.
  • It changes our view of computing. We are no longer controlling an electronic chip thingy; we are capturing knowledge about data and processing.
2.

Why can't programming be done in English?

There are a number of reasons why we don't try to do programming in English.

  • English is vague. More precisely, English has many subtle shades of meaning. Try to explain the difference between “huge” and “immense”. Further, English has words borrowed from a number of languages, making it more difficult to assign precise meanings to words.
  • English is wordy. Data processing can be very simple; however, English is a general-purpose language. Because we're only talking about data processing, it helps to have a number of simplifying assumptions and definitions.

Over the years there have been a number of attempts at “natural language” processing, with varying degrees of success. It takes quite a bit of computing horsepower to parse and understand general English-language writing. All of this horsepower would then make the Python program large and slow; a net loss in value.

In order to keep to short, focused statements, we would do well to use only a limited number of words. We would also find it handy to allow only a few of the available English sentence forms. We should also limit ourselves to just one verb tense. By the time we've focused ourselves to a small subset of English, we've created an artificial language with only a small resemblance to English. We might as well do another round of simplification and wind up with a language that looks like Python.

3.

What if I'm no good with languages?

First, we aren't learning a complete natural language like Swedish. We're learning a small, artificial language with only about twenty kinds of statements. Second, we aren't trying to do complex interpersonal exchanges like asking someone which bus will get us to Slottberg in Gamla Stan. Interpersonal interactions are a real struggle because we don't have all day to look up the right words in our phrase book. Python is all done as written exchanges: we have hours to look things up in our various reference books, think about the response from the Python program, and do further research on the Internet.

Also, the Python language lacks subtle shades of meaning. It is a mathematical exercise; the meanings are cut and dried. The meanings may be novel, but the real power of software is that it captures knowledge in a rigorous formal structure.

4.

Why is the terminology so confusing?

One of the biggest sources of confusion is the overuse of the word “system”. Almost everything related to computers seems to be a system. We have computer systems, software systems, operating systems, systems programmers, system architects and network systems. Most of this is just casual misuse of the words. We'll limit “system” to describing the computer hardware system.

Another big source of confusion is overuse of “architecture” and the wandering meaning of “platform”. We'll try to avoid these words because they aren't really going to help us too much in learning Python. However, we have software architectures and hardware architectures. The hardware architecture and the platform are both, in essence, the processor chip and supporting electronics.

Generally, however, the biggest issue is that computers and computing involve a number of very new concepts. These new concepts are often described by using existing words in a new sense. For example, when we talk about computer systems being “clients” or “servers”, we aren't talking about a lawyer's customers or a restaurant's wait staff.

Chapter 3. Let There Be Python

Downloading and Installing

Before we can use Python, we may have to download it and install it on our computer. This chapter will cover a number of installation scenarios.

We'll need to have access to a reasonably modern computer. This can be either a Macintosh with MacOS X, a Windows machine with Windows 98 or higher, or any of the wide variety of GNU/Linux or UNIX machines. The computer doesn't need to be spectacular or huge, just a machine that works reliably. Python does run on really small systems like the Palm OS, but this is an inconvenient platform for software development.

You'll also need a few basic computer skills; if you're new to computing, you might need a couple of “For Dummy's” books to fill in your background. Since we're going to download and install software, you'll need access to the Internet, plus authority to install software on your computer. In an office or academic environment, you might not have permission to install new software; in this case, you'll need to work through the organization that provides your computer to do the installation for you.

This chapter has a number of sections, but you'll only really need to read a little bit of this chapter, depending on your operating system.

  • Windows. You need to work through ???, where we describe downloading Python 2.4 (or newer) and installing it.

  • Mac OS. In Mac OS 10.5 ("Leopard"), Python 2.5 is included. In Mac OS 10.4 ("Tiger") Python 2.3 was included. In still older Mac OS's, you will have to add Python. Additionally, you may want to upgrade your Python to the latest and greatest. We'll look at a Mac OS upgrade in ???.

  • GNU/Linux. In Red Hat or Fedora GNU/Linux, Python is included. Often, the upgrades are automatically done. We'll look at the common variations on the GNU/Linux installation in ???. If you have YUM, see ???. Otherwise, you might be using one of the three scenarios for RPM installations in ???. Additionally, we'll look at the non-RPM installation procedure in ???.

We'll provide some FAQ's in Installation FAQ's.

Once we have Python installed, we can move on to interact with the Python program in the next chapter.

Teminology

There's a distinction between download and install that sometimes escapes newbies.

When you go to www.python.org and download some software, you wind up with a file on your computer. But this file isn't in a location where the operating system can find it.

Generally, software posted on the internet is compressed into a small file. On your computer, it generally exists as a number of files, often in an expanded form which is easier to process, but larger. When you install a piece of software, the installer both uncompresses the files and distributes them to their proper locations.

The installaer can take a number of forms, dependong in your operating system.

  • Windows installers can be .zip, .exe or .msi files. In rare cases, you may have an .exe or .zip file which unpacks an .msi file which you then have to run separately. An .exe file is (hopefully) a "stand-alone .zip executable", not a virus. A .zip file (whether named .zip or .exe) is a compressed archive, which will expand itself into the proper location. An .msi file is more sophisticated; it is a Microsoft Installer, and can do a variety of installation tasks. It will generally display a series of steps, leading you through the installation process.

  • Mac OS X installers are often .dmg files, which contain disk images. When you double-click a .dmg file, a new "disk" appears on your desktop. This can contain files that you simply drag (usually to your Applications folder), or it may contain a .pkg file. If there's a .pkg file, this is a Mac OS Installation package. When you double click the .pkg file, the installer will step through the installation process, telling you what you're installing, where you're installing it, what the licensing terms and conditions are, etc.

  • There are a variety of Linux installers. Details vary with each Linux variant. One very easy-to-use installer is Yum, which handles just about everything for you: download and installation. Another popular installer is RPM, which can handle download and installation together.

<xi:include></xi:include><xi:include></xi:include><xi:include></xi:include><xi:include></xi:include><xi:include></xi:include><xi:include></xi:include>

Installation FAQ's

1. Why are there so many operating systems?
2. Why is GNU/Linux so complex?
1.

Why are there so many operating systems?

This is often asked as “Why not just use Windows?” or, in many Information Technology organizations at big companies, it is paraphrased as “We only use Windows.

There are two parts to the answer. The first part of the answer is that one size does not fit all. Even Microsoft, in their ongoing quest to write a good operating system, release a number of products that use the brand name Windows™, but are very different on the inside. As for the rest of the world, one person's GNU/Linux has too many features, too few features, or is simply the wrong color for another person. Since we can customize it (and hopefully improve on it), why not?

The second part of the answer is that the people who make the computer systems (Apple, Dell, HP, IBM, Sun, etc.) have to provide software to make their computer systems of any value to anyone. A computer without software is like a stereo without CD's, and a TV without TV shows. A computer without software is just a good idea waiting to happen.

In the early days of computing, there was relatively little software, and it was provided by the hardware vendor. IBM grew to be the software giant it is today by bundling a processor and some software to solve business problems. As the industry matured, independent companies produced software. As the marketplace matured, the software become one valuable commodity and the computer to run that software a different commodity.

One lesson that the innovative companies learned was that new hardware had a hidden cost. A new, faster, sleeker processor couldn't run the old software. The software had to be converted to the newest processor's binary instruction codes. This drove up the cost of producing software, and ate away at profit margins from making new processors. To reduce these costs, operating systems, languages and compilers evolved so that, within limits, software could be more easily moved to the latest, coolest processor.

This cycle of innovation never stops. Each new good idea can lead to new processors that aren't compatible enough with old processors or new operating systems that aren't enough like old operating systems.

Python, to an extent, gets us out of this arms race of hardware and operating system improvements. We write our software in Python, which is identical on all processors and all operating systems. We can have large libraries of Python software that are the same everywhere. All we need to install is the base Python program itself. This program acts as a framework that insulates us from the operating system and the underlying processor.

2.

Why is GNU/Linux so complex?

Complexity is in the eye of the beholder. An operating system like Microsoft Windows is well known only to a few engineers in Microsoft. For the rest of us, it is tightly-sealed mystery. The GNU/Linux operating systems, however, are completely exposed to the scrutiny of software developers the world over. While this makes it perfectly transparent, it also means that everybody (and their brother) wants to make customizations, amendments and exceptions to the operating system.

Microsoft (and Apple) have pre-configured the operating system with things they think we need. In GNU/Linux, this is not as common. Even vendors like Red Hat provide alternative packages which are more finely tuned to different needs.

It isn't so much that one OS is more complex than the other. It's more of the nature of what you can adjust and how easily you can adjust it. With GNU/Linux, every knob is exposed, and everyone wants to adjust those knobs. This exposes more of the software installation process to you, the user. For Windows and Mac OS, the knobs are there, but they're tucked away where we can't see them.

Chapter 4. Two Minimally-Geeky Problems

Examples of Things Best Done by Customized Software

There are a couple of problems that we'll use throughout this book to show how you use Python. Both problems are related to casino games. We don't embrace gambling; indeed, as you work through these sample problems, you'll see precisely how the casino games are rigged to take your money. We do, however, like casino games because they are moderately complex and not very geeky. Really complex problems require whole books just to discuss the problem and its solution. Simple problems can be solved with a spreadsheet. In the middle are moderately complex problems that require Python.

While it's pretty safe to assume that you know a little about casino gambling, we'll provide a few definitions in About Gambling just to be sure. From there, we'll define the Roulette problem in The Roulette Problem. We'll look at the Craps problem in The Craps Problem. We'll stake out our overall strategy in Directions. We'll answer some questions in Problem FAQ's.

About Gambling

The casino table games of Craps and Roulette (and a number of similar games) allow the bettor to place a bet (or wager) on an outcome or set of outcomes. Some random device (cards, dice, a wheel, a spinner) is used to make a selection. This selection usually resolves the bets as winners, losers, or a “push” where your money is returned.

In Roulette, each random event defines a complete set of outcomes, and all bets are resolved. You see this in the play at the Roulette table: people place bets, the wheel is spun, all of the bets are resolved. Once the bets are resolved as winners or losers, players are permitted to bet again.

In Craps, each random event does not define a complete set of outcomes. Some bets are not resolved when the dice are thrown; instead, the bets remain. Craps is played as a series dice throws that are part of a round or turn. The turn can be as short as a single throw of the dice, or it can be indefinitely long. It is unlikely (about a 1% chance) for a turn to take more than seven throws of the dice, but not impossible.

Generally, the person throwing the dice, the “shooter”, holds the dice as long as they win their round. When they lose, the dice move to a new shooter. These nuances of casino play has no impact on the actual game, so we'll ignore details like these.

Odds. If the outcome you bet on is likely, your payout is rather small. If the outcome you bet on is rare, your payout may be huge. They call this the odds of winning. When the odds are small, the event is pretty likely. For example, almost half the Roulette wheel has numbers colored red. Betting on red, then, is pretty safe. Since it's about half the numbers, the payout is 1:1. If you bet $10, you could win an additional $10.

Contrast red (or black) with the number zero, which is just one of the thirty eight bins on the wheel. Since zero is so rare, it pays off at 35:1. If you bet $10 on zero, and it comes up, you could win $350. They call these long odds or a long shot.

The Roulette Problem

Here's the short form of the question: “How well does the Martingale betting system work for Roulette?”. After we define any unknown jargon in this question, we'll see that it is not terribly complex and it will lead us to some related questions. All of these questions can be answered with simple Python programs.

Roulette. In Roulette players make bets and wheel is spun to determine which bets win and which bets lose. The Roulette table has a number of positions on which you can place bets by stacking up chips. The Roulette wheel is a collection of numbered bins. When the wheel is spun, a small ball is dropped into it, and the ball will eventually come to rest in one of the bins. The bin selected by the ball determines which of the betting positions are winners and which are losers. Each position has a payout ratio that determines how much you win based on how much you bet.

There are over a hundred possible bets on the Roulette table, and a wide variety of payout ratios. We'll define a few of them, and focus on just six of the available bets.

  • The 38 individual numbers. The numbers go from one to thirty-six, colored red and black. Additionally, there are zero and double-zero, colored green. The numbers all pay off at 35:1.

  • Groups of numbers. You can place bets between pairs of numbers, groups of three, four or six numbers. You can also place a bet on zero, double zero, one, two and three as a combination of five numbers. If any of the numbers wins, your bet is a winner. The more numbers in your combination, the lower the payoff odds.

  • The Columns. The numbers form three columns of 12 values. If any of the numbers in the columns wins, the column as a whole pays off at 2:1. Zero and double zero are not part of any column, if they are spun, all column bets lose.

  • The Ranges. Like the columns, the table is also blocked off into three ranges: one to twelve, thirteen to twenty four and twenty five to thirty six. If any number in the range wins, the range pays off at 2:1. Zero and double zero are not part of any range, if they are spun, all range bets lose.

  • Red, Black, Even, Odd, High and Low. All of the numbers except zero and double zero are colored red or black, are even or odd, or are low (between one and eighteen) or high (between nineteen and thirty six). These bets all include a large range of values and pay off at 1:1. We'll focus on these bets because they are so simple and so commonly used.

Martingale Betting. The Martingale betting system suggests that you organize your casino play as follows:

  1. Establish a budget with a minimum bet. Since tables vary in the size of bets required, we'll just call this amount b, the basic betting unit. At a $10 table, it would often be $10.

  2. Bet the minimum amount, b, on one of the 1:1 bets (red, block, even, odd, high or low).

  3. If the bet wins, you're way ahead. Reset your bet back to the minimum amount, b. If the bet loses, you double your bet. In the even of several losses, you'll be betting 2b, 4b or even 8b.

Now, let's look at our question again. How well does this Martingale system work? We can see that the green zero and double zero complicate the analysis. There are ways to work out the details, but rather than learn a lot of math, we'll learn a little Python and simulate the whole thing. We can collect some statistics showing the results of our simulated Roulette game.

We can ask a whole family of related questions by replacing the Martingale betting system with more complex systems. We can ask questions based on extending the Martingale system to include additional bets. This is the beauty of writing our own simulation: we can modify our program to try out different variations on our betting procedure.

The Craps Problem

Here's the short form of the question: “How well does the Field bet pay in Craps?”. We'll define the gambling jargon and then look at this question again, in a little more detail.

In Craps, players make bets and a pair of dice are thrown to determine the state of the game. Some dice throws are significant events and will resolve some or all of the bests as winners or losers. Some dice throws are less significant and resolve some bets. Some dice throws don't change the state of the game at all.

The Craps table has a number of positions on which you can place bets by stacking up chips, as well as a token that shows the state of the game. A shooter will throw two dice; the number on the dice will do several things. First, the number will pay off any proposition bets based on just this throw of the dice. Second, the number will pay off any of the various number bets that can be placed. Third, the number may change the state of the game, which can also resolve certain kinds of bets.

The Craps game has two states: point “off” and point “on”. The casino will place a large black and white disk on the table to show the state of the game.

Point Off or the Come Out Roll. The first time the shooter throws the dice, the point is off. If the shooter throws 7 or 11, this turn is an immediate winner, and bets are resolved. If the shooter throws 2, 3 or 12, this turn is an immediate loser and bets are resolved. In this case, the point is still off, the game didn't change state, it's still just beginning.

When the point is off, and the shooter throws 4, 5, 6, 8, 9 or 10, the game changes state, and now the point is on. The casino will flip over the large disk to show the "on" side, and put it on the betting space that shows the point number.

Point On. When the point is on, a number of additional bets are allowed. Additionally, the disk sits in a number's space to prevent certain other bets. We'll avoid the complexity of these conditionally permitted bets. In a casino, however, you would see a flurry of activity when a point is established.

When the point is on, and the shooter throws this point number, the round is a winner, and most of the bets are resolved. There are some bets that will persist, however. When the shooters throws a seven, the round is a loser, and all bets are resolved.

Throwing a seven means the shooter lost, and most bets are losers. There are, however, some “don't” bets that will be winners when the shooter doesn't win. These are sometimes called “wrong bets”, and involve a more sophisticated odds calculation. In general, you can put up a lot to win a little when you make wrong bets.

When the shooter throws 2, 3, 11 or 12, nothing much can happen. Certain one-roll proposition bets are resolved, but these four numbers are neither points nor are they 7, which ends the game.

Other Bets. There are a number of bets which don't depend on the state of the game. These are one roll “proposition” bets. The field is one of these bets. You place your bet in the box marked “Field” before the dice are thrown. The number on the dice determines the field bet result immediately.

The field bet wins on any of 2,3,4,9,10,11, or 12. The 3,4,9,10, and 11 pay 1:1 (“even money”) and the 2 and 12 pay off at 2:1.

Analysis. There are a number of questions about the field bet. We can create a simple simulator to see the basic outcome. We can use a more sophisticated simulation of doing Martingale betting (see the section called “The Roulette Problem”) to see how that changes the performance of this bet. Some people use an even more complex betting system for the field by increasing their bet with each win and decreasing it with each loss. We'll stick with a simple simulation as a way to learn Python

Directions

We aren't going to describe the solutions to any of these casino game problems here — that would rob you of the intellectual fun of working out your own solutions to these problems. Instead, we want to provide some hints and nudges that will parallel the course this book will take.

This may already be obvious, but we're going to address these problems by writing new software in the Python language. The reason why it is important to restate the (potentially) obvious is that in Using Python we're going to spend time on learning to control the python program in a simple, manual way. Then, when we write programs, we'll control python with our programs to do more sophisticated work.

Any solution to these kinds of problems will involve some simple math. Almost all computing involves some kind of math. Business programming tends to involve the simplest math. Engineering and science can involve some really complex math. Statistics is often in the middle ground, which is why we will look at it closely in Arithmetic and Expressions.

By the way, in addition to math-oriented computing, there is also computing that could be termed “symbolic” in nature. It might involves words or XML documents or things that aren't obviously mathematical; we'll set this aside as atypical for newbies.

Sequential Thinking. A program in Python is often a sequence of operations. In the casino game definitions, we saw that each game was a sequence of individual steps. We can often summarize programs by looking at their inputs, their processing steps and their outputs. This input-process-output model reflects the sequential order of processing: first, read the inputs; second, do the processing; third, print the outputs. More sophisticated programs (like games or web servers) will interleave these operations. We'll look at this in Programming Essentials.

The sequence of operations is rarely fixed and immutable. With casino games, we have some bets which are winners and some bets which are losers. We have conditional operations of collecting losing bets and paying winning bets. Additionally, we'll have some operations which have to be repeated for a number of simulations, or until some condition is satisfied. We'll look at this in Some Self-Control.

Our exploration of Python starts with arithmetic expressions and moves on to statements, then to sequences of statements. We'll add conditional and iterative statements. The next step will be a simple organizing principle called a function definition. We'll introduce this in Organizing Programs with Function Definitions and use it to package parts of our program until a useful, discrete components that can help us control the overall complexity of our program.

Other Side Of the Coin. Beginning with Getting Our Bearings we'll turn to a different tack. The first parts of our exploration were focused on the processing, and the procedural nature of our problems. The second part of our exploration will look at the data and collections of data.

If we are going to simulate a number of sessions at the Roulette wheel, following our Martingale strategy, we'll need to collect the results and do statistical analysis on the collection. We'll look at collections of data items in Basic Collections of Data: Strings, Lists and Tuples.

We'll address some programming techniques in Additional Processing Patterns — Exceptions and Iterations that make our Python programs more reliable and also a bit simpler. Simplification is a touchy subject: simplifications aren't always appreciated until you see the more complex alternative. Further, since we're approaching Python by moving from the elementary to the advanced, some things we'll look at will be complex but elementary. As we learn more, we can replace them with something simple but advanced.

In More Data Collections: Sets, Mappings, Dictionaries and Files we'll look at some additional data structures that can help us develop truly useful solutions to our problems. These additional data structures will give us foundational knowledge of the Python language and the built-in data types that we can use.

Successful Collaboration. When we look at our problems, we see that there is considerable interaction among a number of objects. For example, in Roulette, we have the following kinds of things:

  • the wheel, which returns a random bin,
  • the table, which holds bets,
  • the player, which uses the Martingale strategy to place bets

This interaction between player, table and wheel forms a larger thing, called the game, which lasts until the player wins big, loses big, or has spent too much time at the table. Each game produces a final result of zero dollars, big bucks or some number of dollars that was available when time ran out. These, in turn are collected for statistical analysis. An even bigger assembly of objects does the simulation and analysis. We'll learn how to define these collaborating objects in Data + Processing = Objects.

A lot of the basic components that make a program robust and reliable are already packaged as Python modules, and we'll cover these in Organizing Programs with Modules. We'll also use the built-in modules as templates for designing our own modules; this allows us to organize our program neatly into discrete, easy-to-manage pieces.

Our final section, Fit and Finish: Complete Programs, will cover some final issues. These are the things that separate a fragile mess that almost works most of the time from a useful program that can be trusted.

Problem FAQ's

1. Why Casino Gambling?
2. Why not Something Simpler?
3. Why not Your Subject Here?
1.

Why Casino Gambling?

We think we've got two compelling reasons for using casino gambling for programming problems in this book.

  • Casino games have an almost ideal level of complexity. If they were too simple, the house edge would be too obvious and people would not play them. If they were too complex, people would not enjoy them as simple recreation. Years (centuries?) of experience in the gaming industry has fine-tuned the table games to fit nicely with the limits of our human intellect.

  • The results are sophisticated but easy to interpret. Probability theory has been applied by others to develop precise expectations for each game. These simulations should produce results consistent with the known probabilities. This book will skim over the probability theory in order to focus on the programming. For a few exercises, the theoretical results will be provided to serve as checks on the correctness of the student's work.

This book does not endorse casino gaming. Indeed, one of the messages of this book is that all casino games are biased against the player. Even the most casual study of the results of the exercises will allow the student to see the magnitude of the house edge in each of the games presented.

2.

Why not Something Simpler?

While many problems are simpler than casino gambling, they don't require customized software written with a powerful language like Python to solve them. It's hard to locate things that are both simpler than casino gambling and still interesting enough to provide more than one trivial exercise.

3.

Why not Your Subject Here?

As an author, I'm not as knowledgeable in Your Subject Here as you are, and can't do it justice. Also, I had to pick something, and I chose something that I knew a little bit about.

More importantly, however, the point of this book is to equip you to go out and tackle Your Subject Here using your new-found programming skills.

Chapter 5. Why Python is So Cool

Some Additional Background

We'll ramble on a bit about Python and the reasons why it is so cool. This won't really help you learn the language. It's mostly op-ed material to provide some justification for why someone would invest time in learning Python. In Core Coolness we'll cover some fundamental reasons why Python is cool. The FAQ in Coolness FAQ's touches on a few more questions that sometimes get asked.

Core Coolness

Python reflects a number of growing trends in how people develop new computer programs. It is a very simple language, supported by an interpreter and surrounded by a vast library of add-on modules. It is an open source project, supported by dozens of individuals; this encourages you to build complete solutions from smaller components and partial solutions. We'll look at each of these facets separately.

Planet Python. Python is really four separate elements in a single, tidy package. I like to think of it as an wonderfully efficient planet that we can visit. To get things done on that planet you have to learn the language. Once you've learned the language, however, you find that the whole planet is organized to do everything you ask precisely and very quickly. Like any well-run organization, it has a number of services that make life convenient and safe, and assure the common good of all the inhabitants. Finally, it offers a kind of public forum for making your requests and seeing the results of those requests.

This mythical Planet Python is the Python program itself, we'll call it python in this book. Windows users will know it as python.exe. The Python program, python, runs on your computer, and carries out statements written in the Python language. The program has just one purpose — execute Python language statements — so it is small and efficient. Because it is so tightly focused, it is wonderfully reliable.

The planet's services are the Python libraries. These libraries include programs you can extend, and pieces of programs that you might use to create a more complete program. Some parts of the libraries are both: things you extend to add new features, and then use in your final program. I think of these as essential services like police departments, public libraries, laundromats, and telephone sanitizers. You build your complete organization or enterprise using these pre-built organization units.

The public forum is the integrated development environment (IDE). This is the environment where you develop your Python program. It's integrated because all the tools you might want are right there in a single program. In this case, the program's name is IDLE. You use IDLE to write Python statements, execute sequences of Python statements and read any resulting messages.

Simplicity. Python is a relatively simple programming language that allows you to express data processing in clear, precise terms. The Python language has an easy-to-use syntax, focused on the programmer who must type, read and understand a program. The language is designed to look a bit like a natural language, with simple punctuation and indentation. Computer languages are more rigid than human languages: when you misspell something in English, people can often determine what you meant, and make sense of what you wrote. The Python program, python, is only a simple piece of software: spelling and punctuation really matter. While Python is easier than most other programming languages, you must still be precise.

Interpreted. The computer science folks characterize the Python program, python, as an interpreter: it interprets and executes the Python language statements, doing your data processing. Because it is interpreting our statements, it can provide useful diagnostic information when something goes wrong. It can also handle all of the tedious housekeeping that is part of how programs make use of the computer's resources. As users, we don't see this housekeeping going on, and as newbie programmers we shouldn't have to cope with it, either.

The computer-science types make a distinction between interpreters (like Python) and compilers (used for the C language). The C compiler (controlled by a program named cc) translates C language statements into a program that uses the hardware-specific internal codes used by your computer. The operating system can then directly execute that resulting program. After you see the results of execution you might make changes, recompile and re-execute. This compilation step makes everything you do somewhat indirect. The compiler translates your C statements into another language which is then executed. This indirection makes compiled languages harder to learn; it also makes diagnosing a problem very hard.

Here's a diagram that may help clarify how Python differs from a language like C. For a C programmer, they will use a complex IDE which includes the C Compiler to translate their C statements into a binary executable program from their statements. For a Python programmer, a simpler IDE uses the python program to execute the Python statements.

Figure 5.1. C Compiler vs. Python

C Compiler vs. Python

The binary executables have relatively direct control over the operating system and computer. A Python-language program controls Python.

Libraries. Python, the project, includes a rich set of supporting libraries. These libraries contain the basic gears, sprockets, flywheels and drive-shafts that you can use to make a program. By separating the library tool-boxes from the core language, the designers of Python could keep the language simple, which means the interpreter can be very efficient and reliable. Yet, they can provide an extensive feature set as separate extensions. Every new idea can be added as another extension.

There are other consequences to having extensive and separate libraries. Principally, good ideas can be preserved and extended, and bad ideas can be ignored. This basic evolution saves programmers from having to design everything perfectly the first time. As you get more experience with the Python programming community, you will see ideas come and go. Some extensions will blossom and become widely used, where others will be quietly ignored because something better has come along.

Another consequence of having separate libraries is that any programming project should begin with a survey of available libraries. This can replace unproductive programming with more productive research and reuse.

Development Environment. Finally, we see that Python also comes with a development environment, or workbench, that you can use to write and execute your Python statements. The integrated development environment (IDE) includes an editor for writing Python files, and the Python interpreter, plus some other tools for searching the Python libraries.

Interestingly, the Python development environment is just another Python program. When you double-click on the IDLE icon, you are starting a Python program that helps you write Python programs. At first, this seems like a real mind-wrenching problem. You might think of it as similar to asking “which came first, the chicken or the egg?”. It isn't all that bad a problem however. In this case, someone else wrote IDLE to help you write your program. Your program, and IDLE (and a large number of other programs) all share the Python program as the driving engine.

Timeline. The Python programming language was created in 1991 by Guido van Rossum based on lessons learned doing language and operating system support. Python is built from concepts in the ABC language and Modula-3. For information ABC, see The ABC Programmer's Handbook [Geurts91], as well as http://www.cwi.nl/~steven/abc/. For information on Modula-3, see Modula-3 [Harbison92], as well as http://www.research.compaq.com/SRC/modula-3/html/home.html.

The current Python development is centralized in SourceForge. See http://python.sourceforge.net for the latest developments.

Coolness FAQ's

1. If Python uses C, why not cut out the middleman and just learn C?
2. If Python is so cool, why doesn't everyone use it?
1.

If Python uses C, why not cut out the middleman and just learn C?

We have a number of reasons for avoiding C. First, programming in C is a more difficult proposition because of the number of tools involved: C uses a compiler to build programs: you don't interact directly with C; you build a program, then interact with the operating system to run that program. Second, the C language is designed to make the C compiler work efficiently, it wasn't designed to be easy to write or easy to read. Third, C exposes a number of house-keeping chores that professionals can exploit for efficiency; they won't help newbies get their first program written.

2.

If Python is so cool, why doesn't everyone use it?

That's like asking why everyone doesn't like the Boston Red Sox, Philly cheese steaks, and the Red Hot Chili Peppers. Some people prefer Mom, Apple Pie and the Beatles. There's really no accounting for taste.

Some languages like Visual Basic and C# have the powerful and sophisticated marketing arm of Microsoft backing them. Other languages, like Java, have Sun backing them, and a large, well-established open-source community.

Some languages, like COBOL, are entrenched in the way data is processed at large organizations. While Python may be superior, it appears cheaper (in the short run) to leave the COBOL programs in place rather than convert them to something less complex and less expensive to operate and maintain.

The most important reason, however, is that languages are often specialized around particular tasks or data structures. Some languages, like SQL, express some operations more precisely and with a useful level of abstraction.

Using Python

First Steps

Now that you have Python installed, we can start using it. We'll look at a number of ways that we can interact with the Python application. We'll use these interactions to learn the language.

In later sections, after we've got a more complete grip on the language and start to write programs, we'll move on to more advanced ways to use the Python program. Our goal is to use Python in an automated fashion to do data processing. Here in phase one, we'll be using Python manually to learn the language.

We'll describe the direct use of the python to process Python-language statements in Instant Gratification. This will help us get started; it provides immediate gratification, but isn't the easiest way to work.

We'll dig into IDLE in IDLE Time. We'll emphasize this as a good way to learn the language as well as build programs.

Chapter 6. Instant Gratification

The Simplest Possible Conversation

There are two ways to exercise the Python program: interactively and with a script. In interactive mode, Python responds to each statement that we type in. In script mode, we give the Python program a file with a script of statements and turn it loose to interpret all of the statements in that script. Both modes produce identical results. Our goal is to write finished programs that will be run as a script. It's a long journey to scripting, which begins with some first small steps. We have to start with experimenting and exploring, so we'll use Python interactively. This gives us the instant gratification of a dialog with the Python program.

To be sure that we've got the basics installed and working, we'll use Python directly for our interactions. In the next chapter, we'll add the IDLE tool to the mix.

We'll look at starting Python in several sections: The Windows Command Prompt, The Mac OS Terminal Tool, and The GNU/Linux Terminal Tool. We'll look at ending out conversation in How Do We Stop?.

The real work starts in Your First Conversation in Python: miles per gallon. We'll look at numbers in Decimal-Points and Accuracy and look at more arithmetic in More Conversations on Arithmetic.

We'll examine some core features of the language in Parenthesis and Precedence, Long-Winded Statements, and More About Punctuation. We'll answer a few questions in Direct Python Interaction FAQ.

The Command or Terminal tool use of Python is the simplest and most ubiquitous way to use Python. This doesn't have flashy, interactive, colorful screens; it's just plain text. When we get to Fit and Finish: Complete Programs, we'll see that this way of using Python has an elegant simplicity that the experts use heavily.

The Windows Command Prompt

The command prompt is sometimes hard to find in Windows. In Windows 2000, you have to look in the Start menu under Programs, and then under Accessories to find the Command Prompt.

You can also use the Run... menu item in the Start menu. This will give you a small dialog box where you can type the name of a program. The name of the command prompt is just cmd. You can type cmd, and click Okay.

When you run the command tool, it will present a black window with a prompt from the operating system that looks something like C:\Documents and Settings\SLott>. Here, you can type the word python, hit return, and you're off and running.

Debugging Windows Command Prompt

In the unlikely event that you can't use Python from the Command Prompt, you have an issue with your Windows “path”. Your path tells the Command Prompt where to find the various commands. The word python becomes a command when the python.exe file is on the system's path.

Generally, you should reinstall Python to give the Python installer a chance to set the path correctly for you. If, for some reason, that doesn't work, here's how you can set the system path in Windows.

Procedure 6.1. Setting the Windows Path

  1. Open the Control Panel

    Use the Start menu, Settings sub menu to locate your Control Panel. We'll abbreviate this Start->Settings->Control Panel

  2. Open the System Control Panel

    Double-click the System Control Panel. This opens the System Properties panel.

  3. Open the Advanced Tab of the System Control Panel

    Click the Advanced tab on the System Control Panel.

    There are three areas: Performance, Environment Variables and Startup and Recovery. We'll be setting the environment variables.

  4. Open the Environment Variables of the Advanced Tab of the System Control Panel

    Click the Environment Variables... button.

    This dialog box has a title of Environment Variables. It shows two areas: user variables and System variables. We'll be updating one of the system variables.

  5. Edit the Path variable

    This dialog box has a title of Environment Variables. Scroll through the list of System variables, looking for Path. Click on the Path to highlight it.

    Click the Edit... button.

    This dialog box has a title of Edit System Variable. It has two sections to show the variable name of Path and the variable value.

  6. Add Python's location to the Path value

    This dialog box has a title of Edit System Variable. It has two sections to show the variable name of Path and the variable value.

    Click on the value and use the right arrow key to scroll through the value you find. At the end, add the following ;C:\python24. Don't forget the ; to separate this search location from other search locations on the path.

    Click OK to save this change. It is now a permanent part of your Windows setup on this computer. You'll never have to change this again.

  7. Finish Changing Your System Properties

    The current dialog box has a title of Environment Variables. Click OK to save your changes.

    The current dialog box has a title of System Properties. Click OK to save your changes.

The Mac OS Terminal Tool

In the Applications folder, you'll find a Utilities folder. In the Utilities folder, you'll find a program named Terminal. Double click Terminal and you'll get a window with a prompt from the operating system that looks something like [DVDi-Mac-1:~] slott%. Here, you can type env python, and you're off and running.

You might want to drag the Terminal icon onto your dock to make it easier to find.

Debugging MacOS Terminal

If Python doesn't work from the Terminal prompt, it isn't installed in the first place. If you have MacOS 10.4 (“Tiger”) and Python doesn't work, your operating system has been corrupted, and needs to be reinstalled. If you have an earlier version of MacOS, you'll either need to get Tiger or go to www.python.org to locate a version of Python for your Macintosh.

The GNU/Linux Terminal Tool

The Fedora Linux desktop, for example, has a Start Here icon which displays the applications that are configured into you GNOME environment. The System Tools icon includes the Terminal application. Double click Terminal and you'll get a window which prompts you by showing something like [slott@linux01 slott]$.In response to this prompt, you can type env python2.4, and you're off and running.

For non-Gnome Linux and Unix variants, you must find your Terminal tool, into which can type python.

Debugging GNU/Linux Terminal

If Python doesn't work from the Terminal window, there are two things that can go wrong.

  • Python isn't installed correctly in the first place. It's impossible to give a single, pat answer for all of the infinite Unix and GNU/Linux variations that are available. Generally, there should be a /usr/lib/python2.4 directory which has the various Python files in it. In some cases, this may be in a directory under /opt, or even /usr/local. In some cases, it is called python, not python2.4. If you can't find the Python 2.4 directory, you should simply redo the installation.

  • Your shell's path isn't set correctly to locate Python. There are a variety of solutions to this; we'll provide one commonly-accepted solution. Generally, the Python program will be /usr/bin/python. If you don't have /usr/bin/python, you'll need to add Python to /usr/bin. In older Red Hat and Fedora GNU/Linux, you will find two files: /usr/bin/python and /usr/bin/python2.4, if python2.4 isn't present, you should reinstall it.

Procedure 6.2. Adding Python to /usr/bin

  1. Locate the python executable

    The location of the installation can vary from Unix to Unix. However, you should start with /usr or /usr/local and /usr/local/lib. You can use the find /usr -name 'python' -print command to search /usr for Python.

  2. Link to /usr/bin/python

    The ln will create a link from the actual location of the python file to /usr/bin/python. The following example assumes you've found the Python executable program in /usr/local/lib/python2.4/bin/python.

    sudo ln /usr/local/lib/python2.4/bin/python /usr/bin/python
        

    You will be asked for the GNU/Linux root password. This is the administrative password you used when you installed GNU/Linux and when you installed Python. You're not using it now, are you? If you normally log in as root, using the administrative password, you shouldn't be doing that as a regular practice.

How Do We Stop?

Once the Python program has started, it looks something like the following. It doesn't matter whether Python starts up from the command prompt or terminal window, the basic operation is the same. The window title and background color may be different, but our interaction with Python will be the same.

Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.

C:\Documents and Settings\SLott>python
Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

When we get the >>> prompt, the Python interpreter is listening to us. We can type any Python statements we want. Each complete statement is executed when it is entered.

To finish using Python, we enter the end-of-file character. We do this when we're completely done with all of our work. We don't absolutely have to do this, because we can always just exit the Command Prompt or Terminal. When we stop the Terminal, the running python will be killed.

MacOS and GNU/Linux. The polite way to tell Python that we're done is Ctrl-D.

Windows. The polite way to finish a conversation with Python is Ctrl-Z, followed by Enter.

Your First Conversation in Python: miles per gallon

The Python program's job is very simple: it prompts you for a statement, executes the statement you entered, and then responds back to you with the result of executing the statement. This little three-step loop is all that Python does. Of course, as we will see, the real power comes from the wide variety of statements we provide in the Python language.

Don't Forget to Run Python

While this may seem like a silly reminder, it's important to start the Python program. We emphasize it because it isn't always obvious what piece of software processes our Python language statements.

In the section called “The Python Program and What It Does” we described our four-tiered device built from the Computer System, Operating System, Terminal (or Command Prompt) and Python. First, we start the computer system with the power button. The Operating System starts more-or-less automatically. Second, we have to locate the Terminal (or Command Prompt), called a “shell”. Finally, we run Python.

Each tier of software has it's own unique prompt. The basic operating system presents a slick GUI desktop metaphor with colorful icons and menus. The shell provides a technical-looking prompt like C:\Documents and Settings\SLott>, or [DVD-iMac-2:~] slott%. Python provides the >>> prompt that tells us we can enter a Python statement.

Bottom Line. We're always interacting with some program on our computer. We can't “simply type things”; we have to run a program which will respond appropriately when we give that program statements in a language it can process.

Since we are all newbies to programming, we'll start with some very simple Python interactions, just to see what kinds of things Python can do. We'll start the Python program and then type Python statements that evaluate a simple formula. For these first few examples, we'll include the reminder to start running Python.

This first example will show the mathematical operation of ÷. If you look at your computer keyboard, you won't find the ÷ key. Python uses / for division.

Example 6.1. Our First Dialog: Miles per Gallon

C:\Documents and Settings\SLott>python  
Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 351 / 18  
19  
1

First, I typed python to start the python program running. If this was my Fedora GNU/Linux machine, I would have used python2.4, instead.

2

I typed 351 / 18 to compute miles per gallon I got driving to Newark and back home. This is a complete Python statement, and Python will evaluate that statement.

3

Python responded with 19: a rotten 19 miles per gallon. I've got to get a new car that uses less gasoline.

This shows Python doing simple integer arithmetic. There were no fractions or decimal places involved. When I entered 355 / 18 and then hit Return, the Python interpreter evaluated this statement. Since the statement was an expression, Python printed the results.

The usual assumption for numbers is that they are integers, with a range of -2,147,483,648 to 2,147,483,647. This seems like a peculiar set of numbers, but it happens to be all the numbers that the creatures of planet Binome (see Binary Codes) can represent when 32 of them participate. This is what the computer scientists call a 32-bit integer. You can then ask, “why 32 bits?” This is the subject for an FAQ.

Note that Python does not like ,'s in numbers. Outside Python, we write large numbers with ,'s to break the numbers up for easy reading. Except for years on the calendar, where we omit the ,'s; we write 2007, not 2,007. Python can't cope with ,'s in the middle of numbers. The mileage on my odometer reads 19,241. But, in Python we write this as 19241.

Bottom Line. For now, be comfortable that Python is perfectly happy with whole numbers that are plus or minus two billion. Remember to avoid commas. We sometimes call these numbers ints, short for integers. Later, we'll see that Python has a pretty expansive set of numbers available to work with.

Decimal-Points and Accuracy

That calculation was nice, but you'll notice that whole numbers aren't really very accurate. If you pull out a calculator, you'll see that Python got a different answer than your calculator shows.

If you include a period in your numbers, you get “floating decimal point” numbers. We call these floating-point or floats. The number of digits on either side of the decimal point can “float”. Floating point numbers are handy for many kinds of calculations.

Our previous conversation used whole numbers. Let's try again, using floating-point numbers.

Example 6.2. Using Floating Decimal Point Numbers

>>> 351. / 18.
19.5
1

I typed 351. / 18. to compute miles per gallon I got driving to Newark and back home.

2

Python responded with 19.5: the more accurate 19.5 miles per gallon.

There's another kind of number that we'll get to later. When we do financial calculations on US dollars, the decimal point is fixed; we have two digits to the right of the decimal point and no more. These fixed-decimal point numbers aren't a built-in feature of Python, but there are ways to extend Python with a library that gives us this capability.

Bottom Line. For now, be comfortable that Python is perfectly happy with floating-point numbers that have about 17 total digits of accuracy, but a range that is huge. Remember to include a decimal point to tell Python that you want to see decimal places in the calculation. Also, remember to avoid commas, they're just confusing.

More Conversations on Arithmetic

So far, we've given arithmetic expressions to Python and Python's response is to evaluate those expressions. When we look at our keyboard, we can see that we have / (for division), + for addition and - for subtraction. What about multiplication (×)? Square roots (√)? Raising to a power? These aren't keys on a standard keyboard.

Here are the arithmetic operations that Python recognizes in forms very similar to the way mathematics is written:

  • Addition (+) is the + character. You say 123+456 to add two numbers.
  • Subtraction (−) is the - character. You say 9116-8765 to find the difference between two numbers.
  • Multiplication (×) is the * character. You say 19*18 to find the product of two numbers.
  • Division (÷) is the / character. You find 351/18 to find the quotient of two numbers.
  • Raising to a power (ap) is the ** sequence of characters. You can say 5**2 to raise a number to a power.

Additionally, Python (and many other programming languages) provide two handy operators that mathematicians don't normally write down in this form. Mathematicians may talk about “modular” arithmetic, with something like a (mod m). This is written in Python using the % character. For non-mathematicians, this is the remainder after division.

>>> 355 % 113
16

Here's what this shows us: 113 goes into 355 three times with 16 left over. Mathematically, 355 = 3 × 113 + 16.

The other mathematical operator that Python gives us is the // sequence of characters. This gives us the rounded-down — no fractions, no decimal places — result of division. At first, that seems a little silly, since 355/113 is 3. So is 355//113.

Consider 355.//113.. Above, we said that using the decimal points made this a floating decimal point calculation. Yet, the answer doesn't seem to reflect this.

>>> 355.//113.
3.0
>>> 355./113.
3.1415929203539825

Aha! When we use //, the floating-point numbers are treated like they were whole numbers, and integer-like division is done. When we use /, we get the “natural” division appropriate to the two numbers: with floating-point numbers, we get precise answers; with integers, we get an integer answer.

Parenthesis and Precedence

The usual mathematical rules of operator precedence apply to Python expressions: multiplies and divides will be done before adds and subtracts. Plus, we get to use ()'s are used to group terms against precedence rules. Unlike mathematics, we can't use []'s and {}'s in arithmetic expressions. Mathematicians can use these, but in Python, we have to limit ourselves to just ()'s.

For example, converting 65° Fahrenheit to Celsius is done as follows.

>>> (65 - 32) * 5 / 9
18
>>> ((65 - 32) * (5 / 9))
18

We have to put the 65-32 in parenthesis so that it is done before the multiply and divide.

What would happen if we said 65-32*5/9? Try it first, to see what happens.

If we don't include the ()'s for grouping, then Python would do what every mathematician would do: compute 32*5/9 first and then the difference between that and 65. Python did what we said, but not what we meant. We know the answer is wrong because 65° Fahrenheit can't be the impossibly hot 48° Celsius.

In the second example, we put in extra ()'s that don't change the resulting answer.

Long-Winded Statements

Python prompts us with the basic "I'm listening" prompt of >>>. When we type an expression statement, Python prints the result for us, and then another prompt.

Python has a second prompt that you will see from time to time. It indicates that your statement isn't complete, and more is required. It's the "I'm still listening" prompt of .... Here's how it works.

For this section only, we'll emphasize the usually invisible Return ( ) key. When we start using compound statements in Chapter 20, Conditional Processing: Only When Necessary, we'll add some additional syntax rules. For now, however, we have to emphasize that statements can't be indented; they must begin without any leading spaces or tabs. Here's a simplest case: converting 65° Fahrenheit to Celsius.

>>> (65 - 32) * 5 / 9 
18
>>>

What happens when the expression is obviously incomplete?

>>> ( 65 - 32 ) * 5 / 

  File "<stdin>", line 1
    (65-32)*5 /
              ^
SyntaxError: invalid syntax

>>>

This leads us to the first of many syntax rules. We'll present them in order of relevance to what we're doing. That means that we're going to skip over some syntax rules that don't apply to our situation.

Syntax Rule One

Statements must be complete on a single line. If the statement is incomplete, you'll get a SyntaxError response.

Just to be complete, we'll present syntax rule two, but it doesn't really have much impact on what we're going to be doing.

Syntax Rule Two

The invisible end-of-line character is slightly different on different platforms. On Windows it is actually two non-printing characters, where on GNU/Linux and MacOS it is a single non-printing character. You may notice this when moving files back and forth between operating systems.

There is an escape clause that applies to rule one (“one statement one line.”) When the parenthesis are incomplete, Python will allow the statement to run on to multiple lines.

>>> ( 65 - 32 
... ) * 5 / 9
18
>>>

Yes, we skipped rules three, four and five.

Syntax Rule Six

Python needs to see matching ()'s before it will consider the statement complete.

It is also possible to continue a long statement using a \ just before hitting Return at the end of the line.

>>> 5 + 6 *\
... 7
47
>>>

This is called an escape and it allows you to break up an extremely long statement. It creates an escape from the usual meaning of the standard meaning of the end-of-line character; the end-of-line is demoted to just another whitespace character, and loses it's meaning of “end-of-statement, commence execution now”.

Syntax Rule Five

You can use \ to escape the usual meaning of a character.

Using \ at the end of a line escapes the meaning of the enter key, and allows a statement go continue onto multiple lines. While legal, this isn't the best policy, and we're going to avoid doing this.

More About Punctuation

We've been ignoring spaces in our expressions. There are some spaces in the examples, but we haven't been dwelling on precisely how many spaces and where the spaces are allowed. It turns out that spaces other than indentation are very flexible. Indentation is not flexible.

Syntax Rule Nine

You can use spaces and tabs freely to separate tokens, or language elements.

We have found some kinds of mistakes that we can make with unclosed ()'s and an extra \ at the end of the line. This leads us to an important debugging tip.

Debugging Typing a Python Statement (“The ... Prompt Problem”)

When you see the ... prompt from Python, it means that your statement is incomplete. Are you missing a ) to make the ()'s complete? Did you accidentally use the \? Hit Return twice and you'll get a nice syntax error and you'll be back at the >>> where you can try again.

Also, you'll get unexpected errors if you try to use [], and {} the way mathematicians do. Python only uses ()'s to group expressions. If you try to use []'s, you'll get a TypeError: unsupported operand type(s) for operator: 'list' and 'int'. If you try to use {}'s, you get a SyntaxError: invalid syntax.

Conversational Python Exercises

Simple Commands. Enter the following one-line commands to Python:

  • copyright
  • license
  • credits
  • help

Simple Expressions. Enter one-line commands to Python to compute the following:

  • 12345 + 23456
  • 98765 - 12345
  • 128 * 256
  • 22 / 7
  • 355 / 113

Direct Python Interaction FAQ

1. Why are numbers 32 bits?
2. Is the 8-bit byte still relevant?
3. What Are The Missing Syntax Rules?
1.

Why are numbers 32 bits?

The coffee-shop answer is “that's the way computers are built”.

The real answer is that the use of 32 bits has a long engineering history. One very important consideration is parallelism. The processor chip designers want to have many things happen at the same time. In the case of retrieving data from memory, getting data in 4-byte chunks will take 1/4 the time of getting data in 1-byte chunks. Modern processors often fetch a very large number of bits from memory and keep it in a special cache buffer on the processor chip.

The number of bits used to represent data has varied somewhat. A comfortable group of bits is called a byte. Some older computers used 9-bits in each byte, and put four of these together to make 36-bit numbers. Early modems used a signal protocol optimized to send 7-bits in each byte.

The 7-bit byte allows for 128 values in a single byte. If we take the US Latin alphabet (26 lower case letters, 26 upper case letters, 10 digits, 40-odd punctuation marks) have about 96 characters. Adding some additional codes for housekeeping, we have 128 character codes, which only needs a 7-bit number to encode each character.

We can then use an eighth bit to carry a primitive error-detection code. We can insist that each valid character code have an even number of bits switched on. If we receive a character with an odd number of bits, we know that a bit got garbled. This is one of the many historical precedents that made 8-bit bytes appealing.

Also, of course, there is an elegant symmetry to using 8-bit bytes when we are using binary number coding. The powers of two that we use for binary number positions are 1, 2, 4, 8, 16, 32, 64 and 128. This sequence of numbers has almost mystic significance. Of course we would prefer 8-bit bytes over 9-bit bytes. 32-bit numbers fit this sequence of numbers better than 36-bit numbers.

From Bytes to Words. Once we've settled on 8-bit bytes, the next question is how many bytes make up a respectable “word”. Early computers had 64 kilobytes of memory, a number that requires only 16 bits (2 bytes) to represent. We can use a two-byte register to identify any of the bytes in memory. Many early microprocessors made use of this. The legendary Apple ][ PC had a 6502 processor chip that worked this way. Growing this to 640K only adds 4 more bits to the address information, a kind of half-byte compromise that Microsoft made use of to create DOS for the Intel 8088 processor chip.

In the metric measurement system, a kilometer is 1,000 meters. In the world of computers, there is an elegant power-of-two number that we use instead: 1024. A kilobyte, then is 1024 bytes; a megabyte is 1024*1024 = 1,048,576 bytes; a gigabyte is 1,073,741,824 bytes.

As the amount of memory grew, the size of numbers had to grow so that each location in memory could have a unique numeric address. Currently, 32-bit numbers are oriented around computers with 2 gigabytes of memory. Newer, larger computers use 64-bit numbers so that they can comfortably handle more than 2 Gb of memory.

2.

Is the 8-bit byte still relevant?

When we look at the world's alphabets, we discover that our 26-letter US Latin alphabet isn't really very useful. For most European languages that use the Latin alphabet we'll need to add a number of accented characters. For mathematics, we'll need to add a huge number of special characters. Once we open the door, we might as well provide for non-Latin alphabets like Greek, Arabic, Cyrillic, Hebrew and others. We're going to need a lot more than 128 character codes. And then there's the Chinese problem: there are thousands of individual characters. This is solved by having Multi-byte Character Sets (MBCS). Currently the Unicode standard uses as many as four bytes to represent the world's alphabets.

Since a byte is no longer an individual character, it is not relevant for that purpose. However, it is the unit in which memory and data are measured, and will be for the foreseeable future.

3.

What Are The Missing Syntax Rules?

Yes, we did skip over rules three, four, seven and eight. These are more advanced topics.

We'll look at rules three and four in Chapter 23, Turning Python Loose with More Sophisticated Scripts. These rules have to do with lines Python ignores, called “comments” and character encoding for Python files.

We'll look at rules seven and eight in Chapter 20, Conditional Processing: Only When Necessary. These rules have to do with indenting and completing compound statements.

Chapter 7. IDLE Time

Using Tools To Be More Productive

We'll look at how we can use the IDLE program to make our lives easier. IDLE puts an Integrated Development Environment (IDE) around the Python program. Rather than work with Python directly, using the text-only interface, we'll add some nice features that help us spot errors, save files, and generally see that's going on.

We'll look at this what this environment helps us do in The Development Environment. We'll touch on the basic features of IDLE in Using IDLE — Python Shell Window. We'll look at how to start and stop IDLE in Starting and Stopping IDLE. We'll do the real work of entering simple Python statements in A Conversation Using IDLE.

In IDLE Interaction FAQ we'll answer some common questions.

The Development Environment

Python programming is often done using an Integrated Development Environment (IDE) named IDLE. The IDLE program does a number of things that make programming easier.

  • IDLE runs the Python interpreter in interactive mode for us. You'll see this in a window named “Python Shell”. You can type Python statements and have them executed immediately. We'll make heavy use of this mode to continue to get instant gratification.
  • IDLE has an easy-to-use text file editor. When you create a new window, IDLE opens a very nice editor. This editor knows the Python language and can highlight syntax in color, making the program easier to read.
  • When we start writing scripts, we'll find that IDLE can run our scripts for us, saving the output from the script for us.

IDLE isn't your only choice for an IDE. It is, however, free and so easy to use that we'll focus on it in this book. There are some alternatives that might want to explore.

  • ActiveState's Komodo is a very sophisticated editor that knows Python.
  • The LEO editor can be used to create complex programs. It is a literate programming editor with outlines. LEO isn't as easy for newbies to use because it is focused on experts. LEO is written in Python, also.
  • MacOS programmers sometimes use BBEdit.
  • Windows programmers sometimes use Textpad.
  • Linux programmers can work directly from the command line, using vi or any of the other text file editors available in GNU/Linux.

Starting and Stopping IDLE

After we get past the operating-specific details, we'll see that the Python Shell window of IDLE is the same on all of out various operating systems.

Windows

You can use the Start menu, Programs submenu, Python 2.4 submenu to locate the IDLE (Python GUI) menu item. This will open two windows, the Python Shell window is what we need, but it is often hidden behind a Console window.

MacOS

You can go to your Applications folder, find the Python 2.4 folder, and double click the IDLE application. This will open two windows, the Python Shell window is what we need, but it is buried under a Console window.

I recommend dragging the IDLE icon onto your dock to make it easier to find.

GNU/Linux

You have two choices for starting IDLE under GNU/Linux: from the Terminal or using the GUI. Configuring GNOME or KDE to include an icon for starting IDLE is beyond the scope of this book. It isn't hard, but it makes the book too big. So we'll skip straight to using the Terminal to start IDLE.

Terminal. From the Terminal prompt, you can type the following command to start IDLE.

env python /usr/lib/python2.4/idlelib/idle.py &

Yes, this is long. There are some ways to shorten this up. We'll cover some of them because they tell us a lot about how GNU/Linux really works. You only have to do one of these. Pick the one that seems simplest to you. The others are just additional information.

Write a Script. To create a script, you'll put a command in a file, and mark that file as executable. Once you've done these two steps, you've effectively added a new command to your GNU/Linux environment.

  1. Use an editor (I like gedit) to create a file named idle. Put the command shown above into that file as the only line. Save the file into your home directory.

  2. Execute the command chmod +x idle to mark your new file as executable.

Now you can type ./idle to start IDLE. We recommend this because when you do it this way, you've written your first program! Okay, it's only one line, but it's a program.

Debugging A Script

If your idle script file doesn't work, there are some common things to confirm:

  • Your file is in the same directory that the Terminal starts in. If you are unsure, you can use the pwd to print the working directory. In my case it is /home/slott. That's where I put my idle startup file.
  • Your file is plain text. A word processor won't save files as plain text automatically, so you should use something like gedit to assure that you're creating a plain text file.

Create an Alias. To create an alias, you have to make sure that the alias command is executed every time you log in. Most shells, it turns out, read a hidden file named .profile every time you log in to GNU/Linux. The bash shell reads .bash_profile. There's a two step process to creating an alias. Once you've done these two steps, you've simplified your shell environment.

  1. Use an editor (I like gedit) to update your .profile or .bash_profile file. You won't see this file in ordinary directory listings; the . in the name means that it's hidden; use ls -a to see all files. Insert the following line at the very end. Note that the apostrophes are essential to making this work.

    alias idle='env python /usr/lib/python2.4/idlelib/idle.py &'
  2. Log out. That way, when you log in again, your .profile is executed.

Now you can type idle to run the IDLE program. This is a handy technique, but isn't the best technique for building more complex software.

Debugging An Alias

If your alias doesn't work, there are some common things to confirm:

  • Your .profile works correctly. You can type sh -v .profile or bash -v .bash_profile to test it. If you see error messages, likely you missed an apostrophe or messed up the spaces.

Create a Link. To create a link, you'll execute one command. This will make the idle.py file exist in your home directory as well as the Python library directory.

  1. Execute the command ln /usr/lib/python2.4/idlelib/idle.py idle.py to create the link.

You may get an error if your Python environment isn't the same as mine. You may have to search around for the correct location for your Python implementation.

Now you can type env python2.4 idle.py to start IDLE. This is pleasantly short and respectably easy to remember.

Using IDLE — Python Shell Window

After we get past the operating-specific details, we see that the Python Shell window of IDLE is the same on all of the various operating systems. The Python Shell window will have the following greeting.


Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.

    ****************************************************************
    Personal firewall software may warn about the connection IDLE
    makes to its subprocess using this computer's internal loopback
    interface.  This connection is not visible on any external
    interface and no data is sent to or received from the Internet.
    ****************************************************************
    
IDLE 1.1.4      
>>> 

If you have personal firewall software and it does warn you about IDLE, you can ignore your personal firewall's messages. Your firewall is detecting ordinary activity called “interprocess communication” among the various components of IDLE. Rather than a personal firewall, I buy routers that do this for all the computers in my home.

You can use the File->Exit to exit from IDLE. You can also close the window by clicking on the close icon.

A Conversation Using IDLE

When IDLE is running, the Python Shell shows the Python >>> prompt. This is the same "I'm Listening" prompt we saw in the section called “Your First Conversation in Python: miles per gallon”. Interacting with Python through IDLE is the same as interacting with Python directly.

>>> -20 * 9/5 + 32
-4

Interesting. When the Stockholm weather says -20 Celsius, that is -4 Fahrenheit. That's cold.

Drat! We used numbers without any decimal points. That means we used integer division, which won't be very accurate. We'd like to try that statement again without having to retype the entire thing from scratch.

IDLE has a couple of features to make it possible to work more efficiently.

First, we have ordinary copy and paste capabilities. If you look on the Edit menu, you'll see the usual culprits: Cut, Copy and Paste. If you are new to this sort of thing, here's the play-by-play.

  1. Click and drag to highlight the -20 * 9/5 + 32.
  2. Use Edit menu, Copy menu item to copy this. Or, you can use Ctrl-C to copy this.
  3. Click after the last >>> prompt.
  4. Use Edit menu, Paste menu item to paste the saved command. Or, you can use Ctrl-V to paste it.

Once you have the almost-correct statement, you can use the left-arrow key to move across the line and add decimal points to make the line look like this: -20 * 9./5. + 32.

The cooler technique is to use the up-arrow key to go back to our original command. Here's the play-by-play.

  1. Hit the Up Arrow to go back to the original command. Twice should do it.
  2. Hit Enter and this line will be entered again, and the blinking cursor will be at the right end of the new line.

Once you have the almost-correct statement, you can now use the left-arrow key to move across the line and add decimal points. This up-arrow and left-arrow editing is perhaps the easiest way to re-enter a command with minor changes.

IDLE Exercises

  1. Check the IDLE Version. Note the version number of IDLE. You have a Help menu, look here for information.

  2. Enter simple commands. In the initial window of IDLE, you can enter the following one-line commands to Python:

    • copyright
    • license
    • credits
    • help
  3. Save a file. Use New Window under the File menu to create a simple file. Write a few words in this file. Save this file. It is very important to note the directory that appears initially when you save. Be sure to pay careful attention to where the file gets saved. If it doesn't get saved to your own home directory, you'll need to figure out two things:

    1. What directory IDLE starts working in.

    2. How to navigate to your home directory.

IDLE Interaction FAQ

1. Why are the multiple ways to use Python?
2. Why all the colors? Can I turn that off?
1.

Why are the multiple ways to use Python?

Python can be used a variety of ways, depending what problem you are solving.

We can interact directly with Python at the “command-line”. This was what we saw in Instant Gratification. This is available because Python is must usable when it is a shell program.

A tool like IDLE makes it easier to enter Python statements and execute them. IDLE shows us a Python Shell windows, which is effectively the command-line interaction with Python, plus offers a handy text editor as a bonus. IDLE is both written in Python and uses Python as a shell program.

A tool like BBEdit or TextPad is a handy text editor that can execute the Python command-line tool for us. This interaction is made possible because — under the hood — Python is a command-line program with the ultra simple character-oriented command-line interface.

2.

Why all the colors? Can I turn that off?

Some newbies find syntax coloring distracting. Most experienced programmers find it very handy because the colors provide immediate feedback that the syntax of the statement is sensible.

If you want to change or disable the syntax coloring, use the Options->Configure IDLE... to provide different syntax coloring.

Arithmetic and Expressions

Before Readin' and Writin' comes 'Rithmetic

The heart of Python is a rich variety of numeric types and arithmetic operators. We can use these various numeric types to do basic mathematical operations on whole numbers, real numbers and complex numbers. We'll look at the basics in Simple Arithmetic.

In addition to the basic arithmetic capabilities, many kinds of problems need additional mathematical and financial functions. We'll look at some of the built-in functions and some functions in add-on modules in Better Arithmetic Through Functions and Extra Functions: math and random.

For more specialized problems, Python has a variety of additional operators. We'll look more deeply at these additional operators in Special Ops.

We'll cover some optional topics in Peeking Under the Hood, including different approaches to execution of Python statements, some notes on Python writing style.

Chapter 8. Simple Arithmetic

Numeric Data and Operators

Python provides four slightly different flavors of numbers: plain integers, long integers, floating-point numbers and complex numbers. Each of these have their various strengths and weaknesses. The mathematical abstraction of a number doesn't really exist inside the computer. Instead, we have different representations of numbers, each reflecting a slightly different tradeoff in the amount of computer memory required and the speed of performing operations.

In Plain Integers, Also Known As Whole Numbers we'll look at basic numbers. In Floating-Point Numbers, Also Known As Scientific Notation we'll look at numbers with a wider range of values. We'll look at Python's ability to handle very large numbers in Long Integers — Whole Numbers on Steroids. We'll review the rules for mixing different species of numbers in Mixing Numbers, Some More Rules.

For the mathematicians and engineers, we'll look at complex numbers in Complex Numbers — For The Mathematically Inclined; this is optional material unless you're really curious.

We'll look at strings of characters in Strings — Anything Not A Number.

For the most part, Python uses conventional decimal numbers, in base 10. However, for specialized computer-related tasks, Python can also work in base 8 or base 16. There is a hidden shoal here, so we'll look at alternate bases in Octal and Hexadecimal — Counting by 8's or 16's.

Plain Integers, Also Known As Whole Numbers

Plain integers in Python are written as strings of digits without commas, periods, or dollar signs. A negative number begins with a single -. Plain integers have range ±2 billion, or about 9 decimal digits.

Internally, an integer is compact, using just four bytes of memory. It's also blazingly fast for most mathematical operations. However, this small size and high speed also mean that it has a limited range of values.

Here are some examples of integers. Note the absence of ,'s, .'s, $'s or other punctuation. We can only use - to mean a negative number.

0
2005
8675309
-42

Here are the basic arithmetic operations that Python recognizes:

  • Addition (+) is the + character.
  • Subtraction (−) is the - character.
  • Multiplication (×) is the * character.
  • Division (÷) is the / character for standard division, and // for integer-like division. We'll look at more details of these two division operators in the section called “The Two Specialized Division Operators”.
  • Raising to a power (ap) is the ** sequence of characters.
  • Modulus (remainder in division) is the % character.
  • Grouping is done with the ( and ) characters.

Here are some examples.

>>> 32 - 42
-10
>>> 42 * 19 + 21 / 6
801
>>> 2**10
1024
>>> 241 % 16
1
>>> (18-32)*5/9
-8

Pay close attention to 42 * 19 + 21 / 6. In particular, remember that your desktop calculator may say that 21 ÷ 6 is 3.5. However, since these are all integer values, Python uses integer division, discarding fractions and remainders. 21/6 is precisely 3.

Does Python Round? Try this to see if Python rounds. If Python does not round, the answers will all be 2. If Python does round, the answers will be 2, 2, 3 and 3.

8 / 4
9 / 4
10 / 4
11 / 4

What happened? It shouldn't be any surprise that integer arithmetic is done very simply. For more sophistication, we'll have to use floating-point numbers and complex numbers, which we'll look at in later sections.

New Syntax: Functions. More sophisticated math is separated into the math module, which we will look at in the section called “The math Module — Trig and Logs”. Before we get to those functions, we'll look at a few less-sophisticated functions.

The absolute value (sometimes called the magnitude or absolute magnitude) operation is done using a slightly different syntax than the conventional mathematical operators like + and - that we saw above. A mathematician would write |n|, but this can be cumbersome for computers. Instead of copying the mathematical notation, Python uses a kind of syntax that we call prefix notation. In this case, the operation is a prefix to the operands.

Here's the formal Python definition for the absolute value function.

abs Function Definition

numberabs(number);
number;

Return the absolute value of the argument.

This tells us that abs(x) has one parameter that must be a numeric value and it returns a numeric value. It won't work with strings or sequences or any of the other Python data types we'll cover in Part VIII, “Basic Collections of Data: Strings, Lists and Tuples”.

Here are some examples using the abs(x) function.

>>> abs(-18)
18
>>> abs(6*7)
42
>>> abs(10-28/2)
4

The expression inside the parenthesis is evaluated first. In the last example, the evaluation of 10-28/2 is -4. Then the abs(x) function is applied to -4. The evaluation of abs(-4) is 4.

Floating-Point Numbers, Also Known As Scientific Notation

Floating decimal point numbers are written as strings of digits with one period to show the decimal point. They can't have commas or dollar signs. A negative number begins with a single -. We call them floats or floating point numbers for short.

These numbers are different from the “fixed-point” decimal numbers that we use for financial calculations. With fixed-point numbers, the number of positions to the right of the decimal place is fixed. Doing fixed-point processing in Python is done with an add-on library; we'll cover this in the section called “One Way To Tackle Fixed Point Math”.

A floating-point number takes at least eight bytes, making it twice the size of a plain integer. The extra complexity of scientific notation makes them much slower than plain integers. They have about 17 digits of useful precision, but they can represent values with an astronomical range.

Here are some examples:

0.
3.1415926
867.5309
-42.0

We can, if we want, write our numbers in scientific notation. A scientist might write 6.022×1023. In Python, they use the letter E or e instead of ×10. Here are some examples.

6.022e23
1.6726e-27
8.675309e3
2.998e8

All of the arithmetic operators we saw in the section called “Plain Integers, Also Known As Whole Numbers” also apply to floating-point numbers. Here are a couple of examples.

>>> 6.62e-34 * 2.99e8
1.97938e-025
>>> 3.1415926 * 3.5**2
38.484509350000003

You Call That Accurate? What is going on with that last example? What is that “0000003” hanging off the end of the answer?

That tiny, tiny error amount is the difference between the decimal (base 10) display and the binary (base 2) internal representation of the numbers. That tiny, annoying error can be made invisible when we look at formatting our output in Chapter 29, Sequences of Characters: Strings. For now, however, we'll leave this alone until we have a few more Python skills under our belt.

One consequence is that some fractions are spot-on, while others involve an approximation. Anything that involves halves, quarters, eighths, etc., will be represented precisely. 3.1 has to be approximated, where 3.25 is something that Python handles exactly.

Mixing Numbers

When you mix numbers, as in 2 + 3.14159, Python coerces the integer value to a floating-point value. This assures that you never loose any information. It also means that you don't have to meticulously check every number in a statement to be sure that they are all floating-point. As long as some numbers are floating-point, the others will likely get promoted properly.

The coercion rules are done for each individual operation. 2+3/4.0 and 2.0+3/4 will do different things. We'll return to this below.

Scientific Notation. Floating point numbers are stored internally using a fraction and an exponent, in a style some textbooks call “scientific notation”. Usual scientific notation uses a power of 10. In the Python language, we write the numbers as if we were using a power of 10. We think of a number like 123000 as 1.23e5. Generally, it means the following, where g is 1.23 and c is 5.

While the Python language allows us to enter our numbers in good-old decimal, our computer doesn't use base 10, it uses base 2. Really, our floating point numbers are converted to the following form.

It's that conversion between the value of g (as entered in base 10) to f (in base 2) back to base 10 that gives us the tiny approximation errors.

One important consequence of this is the need to do some algebra before simply translating a formula into Python. Specifically, if we subtract two nearly-equal floating point numbers, we're going to magnify the importance of the stray error bits that are artifacts of conversion.

Long Integers — Whole Numbers on Steroids

Python allows us to use very long integers. Unlike ordinary integers with a limited range, long integers have arbitrary length; they can have as many digits as necessary to represent an exact answer.

We write long integers as a string of digits (no periods) that end in L or l. Upper case L is preferred, since the lower-case l looks too much like the digit 1. Additionally, Python is graceful about converting to long integers when it is necessary.

The trade-off is that long integers will use a lot of memory and the operations are quite slow. For small examples, you'll never notice. But for larger, more complicated programs, you may be unhappy with their slowness.

How many different combinations of 32 bits are there? The answer is there are different combinations of 32 on-off bits. When we try 2**32 in Python, the answer is too large for ordinary integers, and we get an answer in long integers.

>>> 2**32
4294967296L

There are about 4 billion ways to arrange 32 bits. How many bits in 1K of memory? 1024×8 bits. How many combinations of bits are possible in 1K of memory?

2**(1024*8)

I won't attempt to reproduce the output from Python. It has 2,467 digits. There are a lot of different combinations of bits in only 1K of memory. The computer I'm using has 256×1024 K of memory; there are a lot of combinations of bits available in that memory.

Mixing Numbers

When you mix numbers, as in 2 + 3L, Python coerces the integer value to a long value. This assures that you never loose any information. If you mix long and floating-point numbers, as in 3.14 + 123L, the long number is converted to floating-point.

Mixing Numbers, Some More Rules

We've noted in a couple of places that when you have mixed kinds of numbers Python will coerce the numbers to be all one kind. The rules aren't that complex, but they're important for understanding the semantics of a mathematical formula.

When you mix integers and longs, the integers are coerced to be longs. The idea here is that a long will preserve all the information of an integer, even though the long works more slowly. It's a fair tradeoff. 2+3L is 5L because the 2 was coerced to 2L.

When you mix integers or long integers with floating-point, the integers are coerced to floating-point. Again, the idea is to preserve as much information as possible. However, the floating-point version of a number might not preserve everything.

A floating-point number can represent a vast range of values, but it only has about 17 digits of precision. A long integer can have any number of digits. If your long integer is over 17 digits, some of the precision has to be sacrificed, and it will be the right-most digits of the long integer.

Remember that a floating-point number's right-most digits aren't all perfectly accurate; we're reminded of that every time we see a dangling “0000003”. Consequently, making a floating-point value into a long integer doesn't work out well. Some of the digits on the right-hand end of such a number are more error than precision.

How Coercion Happens. Coercion is something Python does as it evaluates each operator. Here's something you can try to see the effect of these rules.

>>> 2+3/4.0
2.75
>>> 2.0+3/4
2.0

In the first example, the first expression to be evaluated (3/4.0) involves coercing 3 to 3.0, with a result of 0.75. Then the 2 is coerced to 2.0 and the two values added to get 2.75.

In the second example, the first expression to be evaluated (3/4) is done as integer values, with a result of 0. Then this is coerced to 0.0 and added to 2.0 to get 2.0.

As we'll see in the section called “Functions are Factories (really!)” we can force specific conversions if Python's automatic conversions aren't appropriate for our problem.

Complex Numbers — For The Mathematically Inclined

Besides plain integers, long integers and floating-point numbers, Python also provides for imaginary and complex numbers. These use the European convention of ending with J or j. People who don't use complex numbers should skip this section.

3.14J is an imaginary number = .

A complex number is created by adding a real and an imaginary number: 2 + 14j. Note that Python always prints these in ()'s; for example (2+14j).

The usual rules of complex math work perfectly with these numbers.

>>> (2+3j)*(4+5j)
(-7+22j)

Python even includes the complex conjugate operation on a complex number. Syntactically, the operation conjugate follows the complex number, separated by a dot (.). This makes it a post-fix operator. For example:

>>> 3+2j.conjugate()
(3-2j)

A complex number is a pretty complicated object: it has a real part, an imaginary part, and a number of really unusual operations. Complicated objects force us to use a more sophisticated notation. This is part of a larger, more general syntax pattern that we'll return to this additional syntax in Defining New Objects.

Strings — Anything Not A Number

A string is a sequence of characters without a specific meaning. We surround strings with quotes to separate them from surrounding numbers and operators. Unlike a number, which supports arithmetic operations, a string supports different kinds of operations including concatenation and repetition.

You can use either apostrophes (') or quotes (") to surround string values. This gives you plenty of flexibility in what characters are in your strings. You can put an apostrophe into a quoted string, and you can put quotes into an apostrophe'd string. The full set of quoting rules and alternatives, however, will have to wait for Chapter 29, Sequences of Characters: Strings.

Here are some examples of strings. We use apostrophes for the strings that have quotes. We use quotes for the strings that have apostrophes.

"Hello world"
'"The time has come," the walrus said'
"Alice's Adventures in Wonderland"

What if we need both quotes and apostrophes in a single string value? We have to use a technique called an escape. In a quoted string, we may need to escape from the usual meaning of the quote as the end of the string. We use the character \ in front of the quote as an escape. In a quoted string, we use \" to include a quote inside the string. In an apostrophe string, we use \' to embed an apostrophe.

"Larry said, \"Don't do that.\""
'Natalie said, "I won\'t."'

The first example shows a quoted string with a quotation inside it. If we tried "Larry said, "Don't do that."", we would have a syntax error. We'd have a quoted string ("Larry said, "), some random letters (Don't do that.), and another quoted string (""). We have to escape the meaning of the two internal quotes, so we use \" for them.

The second example shows an apostrophe'd string with an apostrophe inside it. To escape the meaning of the apostrophe, we use \'.

String Operators. Strings have two basic operators:

  • Concatenation is the + operator; it puts two strings together to make a new string.
  • Repetition is the * operator; it repeats a strings several times to make a new string.

Here are some examples. Note that we had to include spaces in our strings so that the concatenation would look good.

>>> "Walrus" + " and the " + "Carpenter"
'Walrus and the Carpenter'
>>> "Pigs " * 3
'Pigs Pigs Pigs '
>>> "Whether " + ("pigs have " * 2 ) + "wings"
'Whether pigs have pigs have wings'

We'll use strings more heavily in Chapter 13, Seeing Results. It turns out that strings are actually very sophisticated objects, so we'll defer exploring them in depth until Chapter 29, Sequences of Characters: Strings.

Octal and Hexadecimal — Counting by 8's or 16's

For historical and technical reasons, Python supports programming in octal (base 8) and hexadecimal (base 16). I like to think that the early days of computing were dominated by people with 8 or 16 fingers.

You might say to yourself, "Why am I reading this section? I'm not a computer heavyweight!" It turns out that there is a hidden shoal lurking just under the surface of the numbers we've seen so far. The debugging tip, below, is the reason we have to mention this topic.

For much, much more information on bits, bytes, octal and hexadecimal, see Special Ops.

Base 8 - "Octal". A number with a leading 0 (zero) is octal and uses the digits 0 to 7. Here are some examples:

0
0123
-077
012

When you enter one of these numbers, Python evaluates it as an expression, and responds in base 10.

>>> 0123
83
>>> 0777
511

An attempt to use digits 8 and 9 in an octal number is illegal and gets you a strange looking error message. In base 8, we only have the digits 0 to 7, the value 8 is 010 (1 in the 8's place, 0 in the 1's place).

>>> 09
SyntaxError: invalid token

In the obscure parlance of language parsing, any symbol, including a number is a token. In this case, the token could not be parsed because it began with a zero, and didn't continue with digits between 0 and 7. It isn't a proper numeric token.

Debugging Octal Numbers (Leading Zero Alert)

A number that begins with a zero is supposed to be in base 8. If you are copying numbers from another source, and that other uses leading zeros, you may be surprised by what Python does. If the number has digits of 8 or 9, it's illegal. Otherwise, the number isn't decimal.

I spent a few hours debugging a program where I had done exactly this. I was converting a very ancient piece of software, and some of the numbers had zeroed slapped on the front to make them all line up nicely. I typed them into Python without thinking that the leading zero meant it was really base 8 not base 10.

Base 16 - "Hexadecimal". A number with a leading 0x or 0X is hexadecimal, base 16. In order to count in base 16, we'll need 16 distinct digits. Sadly, our alphabet only provides us with ten digits: 0 through 9. The computer folks have solved this by using the letters a-f (or A-F) as the missing 6 digits. This gives us the following way to count in base 16: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, 10, 11, 12, 13, 14, etc. Here are some examples of hexadecimal numbers:

0x0
0x123
-0xcbb2
0xbead

When you enter one of these numbers, Python evaluates it as an expression, and responds in base 10.

>>> 0x53
83
>>> 0x1ff
511
>>> 0xffcc33
16763955

Hex or octal notation can be used for long numbers. 0x234C678D098BAL, for example is 620976988526778L.

Expression Exercises

  1. Some Simple Expressions. Evaluate each of the following expressions. In some places, changing integers to floating-point produces a notably different result. For example (296/167)**2 and (296.0/167.0)**2.

    pow( 2143/22, 0.25 )

    355/113 * ( 1 - 0.0003/3522 )

    22/17 + 37/47 + 88/83

    (553/312)**2

  2. Stock Value. Compute value from number of shares × purchase price for a stock.

    Once upon a time, stock prices were quoted in fractions of a dollar, instead of dollars and cents. Create a simple print statement for 125 shares purchased at 3 and 3/8. Create a second simple print statement for 150 shares purchased at 2 1/4 plus an additional 75 shares purchased at 1 7/8.

    Don't manually convert 1/4 to 0.25. Use a complete expression of the form 2+1/4.0, just to get more practice writing expressions.

  3. Convert Between °C and °F. Convert temperature from one system to another.

    Conversion Constants:  32°F = 0°C, 212°F = 100°C.

    The following two formulae converts between °C (Celsius) and °F (Fahrenheit).

    Equation 8.1. Convert °C (Celsius) to °F (Fahrenheit)

    Equation 8.2. Convert °F (Fahrenheit) to °C (Celsius)

    Create a print statement to convert 18° C to °F.

    Create a print statement to convert -4° F to °C.

  4. Periodic Payment. How much does a loan really cost?

    Here are three versions of the standard mortgage payment calculation, with m=payment, p=principal due, r=interest rate, n=number of payments.

    Equation 8.3. Mortgage Payment, version 1

    Equation 8.4. Mortgage, payments due at the end of each period

    Equation 8.5. Mortgage, payments due at the beginning of each period

    Use any of these forms to compute the mortgage payment, m, due with a principal, p, of $110,000, an interest rate, r, of 7.25% annually, and payments, n, of 30 years. Note that banks actually process things monthly. So you'll have to divide the interest rate by 12 and multiply the number of payments by 12.

  5. Surface Air Consumption Rate. Surface Air Consumption Rate (SACR) is used by SCUBA divers to predict air used at a particular depth.

    For each dive, we convert our air consumption at that dive's depth to a normalized air consumption at the surface. Given depth (in feet), d, starting tank pressure (psi), s, final tank pressure (psi), f, and time (in minutes) of t, the SACR, c, is given by the following formula.

    Equation 8.6. Surface Air Consumption Rate

    Typical values for pressure are a starting pressure of 3000, final pressure of 500.

    A medium dive might have a depth of 60 feet, time of 60 minutes.

    A deeper dive might be to 100 feet for 15 minutes.

    A shallower dive might be 30 feet for 60 minutes, but the ending pressure might be 1500. A typical c (consumption) value might be 12 to 18 for most people.

    Write print statements for each of the three dive profiles given above: medium, deep and shallow.

    Given the SACR, c, and a tank starting pressure, s, and final pressure, f, we can plan a dive to depth (in feet), d, for time (in minutes), t, using the following formula. Usually the 33(s-f)/c is a constant, based on your SACR and tanks.

    Equation 8.7. Time and Depth from SACR

    For example, tanks you own might have a starting pressure of 2500 and ending pressure of 500, you might have a c (SACR) of 15.2. You can then find possible combinations of time and depth which you can comfortably dive.

    Write two print statements that shows how long one can dive at 60 feet and 70 feet.

  6. Wind Chill. Used by meteorologists to describe the effect of cold and wind combined.

    Given the wind speed in miles per hour, V, and the temperature in °F, T, the Wind Chill, w, is given by the formula below.

    Equation 8.8. Wind Chill, new model

    Equation 8.9. Wind Chill, old model

    Wind speeds are for 0 to 40 mph, above 40, the difference in wind speed doesn't have much practical impact on how cold you feel.

    Write a print statement to compute the wind chill felt when it is -2 °F and the wind is blowing 15 miles per hour.

  7. Force on a Sail. How much force is on a sail?

    A sail moves a boat by transferring force to its mountings. The sail in the front (the jib) of a typical fore-and-aft rigged sailboat hangs from a stay. The sail in the back (the main) hangs from the mast. The forces on the stay (or mast) and sheets move the boat. The sheets are attached to the clew of the sail.

    The force on a sail, f, is based on sail area, a (in square feet) and wind speed, w (in miles per hour).

    Equation 8.10. Sail Clew Load

    For a small racing dinghy, the smaller sail in the front might have 61 square feet of surface. The larger, mail sail, might have 114 square feet.

    Write a print statement to figure the force generated by a 61 square foot sail in 15 miles an hour of wind.

  8. Craps Odds. What are the odds of winning on the first throw of the dice?

    There are 36 possible rolls on 2 dice that add up to values from 2 to 12. There is just 1 way to roll a 2, 6 ways to roll a 7, and 1 way to roll a 12. We'll take this as given until a later exercise where we have enough Python to generate this information.

    Without spending a lot of time on probability theory, there are two basic rules we'll use time and again. If any one of multiple alternate conditions needs to be true, usually expressed as “or”, we add the probabilities. When there are several conditions that must all be true, usually expressed as “and”, we multiply the probabilities.

    Rolling a 3, for instance, is rolling a 1-2 or rolling a 2-1. We add the probabilities: 1/36+1/36 = 2/36 = 1/18.

    On a come out roll, we win immediately if 7 or 11 is rolled. There are two ways to roll 11 (2/36) or 6 ways to roll 7 (6/36).

    Write a print statement to print the odds of winning on the come out roll. This means rolling 7 or rolling 11. Express this as a fraction, not as a decimal number; that means adding up the numerator of each number and leaving the denominator as 36.

  9. Roulette Odds. How close are payouts and the odds?

    An American (double zero) Roulette wheel has numbers 1-36, 0 and 00. 18 of the 36 numbers are red, 18 are black and the zeros are green. The odds of spinning red, then are 18/38. The odds of zero or double zero are 2/36.

    Red pays 2 to 1, the real odds are 38/18.

    Write a print statement that shows the difference between the pay out and the real odds.

    You can place a bet on 0, 00, 1, 2 and 3. This bet pays 6 to 1. The real odds are 5/36.

    Write a print statement that shows the difference between the pay out and the real odds.

Chapter 9. Better Arithmetic Through Functions

Beyond Add, Subtract, Multiply and Divide

We've seen one function, abs(x), that is also a standard mathematical function. The usual mathematical notation is |x|. Most mathematical is difficult to represent with simple lines of text, so the folks who invented Python elected to use "prefix" notation, putting the name of the function first.

This function syntax is pervasive in Python, and we'll see many operations that are packaged in the form of functions. We'll look at many additional function definitions throughout this book. In this chapter, we'll focus on built-in functions.

We'll look at a few basic functions in Say It With Functions; we'll show how formal definitions look in pow and round Definitions. We'll show how you can evaluate complex expressions in Multiple Steps. We'll touch in the accuracy issue in Accuracy?. We'll look at how Python gives you flexibility through optional features in Another Round, Please.

There are a number of conversion or factory functions that we'll describe in Functions are Factories (really!). In Going the Other Way we'll see how we can use conversion functions to make strings from numbers. Finally, in Most and Least, we'll look at functions to find the maximum or minimum of a number of values.

Say It With Functions

Many of the Python processing operations that we might need are provided in the form of functions. Functions are one of the ways that Python lets us specify how to process some data. A function, in a mathematical sense, is a transformation from some input to an output. The mathematicians sometimes call this a mapping, because the function is a kind of map from the input value to the output value.

We looked at the abs function in the previous section. It maps negative and positive numbers to their absolute magnitude, measured as a positive number. The abs function maps -4 to 4, and 3.25 to 3.25.

We'll start out looking at two new mathematical functions, pow and round. Here are some examples of abs, pow and round.

>>> abs(-18)
18
>>> pow(16,3)
4096
>>> round(9.424)
9.0
>>> round(12.57)
13.0

A function is an expression, with the same syntactic role as any other expression, for example 2+3. You can freely combine functions with other expressions to make more complex expressions. Additionally, the arguments to a function can also be expressions. Therefore, we can combine functions into more complex expressions pretty freely. This takes some getting used to, so we'll look at some examples.

>>> 3*abs(-18)
54
>>> pow(8*2,3)*1.5
6144.0
>>> round(66.2/7)
9.0
>>> 8*round(abs(50.25)/4.0,2.0)
100.48
1

In the first example, Python has to compute a product. To do this, it must first compute the absolute value of -18. Then it can multiply the absolute value by 3.

2

In the second example, Python has to compute a product of a pow function and 1.5. To do this, it must first compute the product of 8 times 2 so that it can raise it to the 3rd power. This is then multiplied by 1.5. You can see that first Python evaluates any expressions that are arguments to the function, then it evaluates the function. Finally, it evaluates the overall expression in which the function occurs.

3

In the third example, Python computes the quotient of 66.2 and 7, and then rounds this to the nearest whole number.

4

Finally, the fourth example does a whopping calculation that involves several steps. Python has to find the absolute value of 50.25, divide this by 4, round that answer off to two positions and then multiply the result by 8. Whew!

pow and round Definitions

The function names provide a hint as to what they do. Here are the formal definitions, the kind of thing you'll see in the Python reference manuals.

pow and round Function Definitions

numberpow(x, y, z);
x;
y;
z;

Raises x to the y power. If z is present, this is done modulo z: xy % z.

floatround(number, ndigits);
number;
ndigits;

Rounds number to ndigits to the right of the decimal point.

The 〈 and 〉's are how we show that some parts of the syntax are optional. We'll summarize this in Function Syntax Rules.

Function Syntax Rules

We'll show optional parameters to functions by surrounding them with 〈 and 〉. We don't actually enter the 〈 and 〉's — they aren't letters on our keyboard — they're just hints as to what the alternative forms of the function are. In the case of round, the syntax summary shows us there are two different ways to use this function:

  • We can use round with the one required parameter, number
  • We can use round with two parameters, number and ndigits.

Using round as an example, we have two choices: round (number, ndigits ), which rounds to a number of digits after the decimal point, and round (number ), which rounds to the decimal point.

>>> round( 2.459, 2 )
2.46
>>> round( 2.459 )
2.0

Multiple Steps

We can use the pow(x, y) function for the same purpose as the ** operator. Here's an example of using pow(x, y) instead of x**y.

>>> 2L**32
4294967296L
>>> pow(2L,32)
4294967296L

Also, pow(x, 0.5) is the square root of x. The pow(x, y) function is one of the built-in functions, while the square root function is only available in the math library. We'll look at the math library in the section called “The math Module — Trig and Logs”.

In the next example we'll get the square root of a number, and then square that value. It'll be a two-step calculation, so we can see each intermediate step.

>>> pow( 2, 0.5 )
1.4142135623730951
>>> _ ** 2
2.0000000000000004

The first question you should have is “what does that _ mean?

The _ is a Python short-cut. During interactive use, Python uses the name _ to mean the result it just printed. This saves us retyping things over and over. In the case above, the “previous result” was the value of pow( 2, 0.5 ). By definition, we can replace a _ with the entire previous expression to see what is really happening.

>>> pow( 2, 0.5 ) ** 2
2.0000000000000004

Until we start writing scripts, this is a handy thing. When we start writing scripts, we won't be able to use the _, instead we'll use something that's a much more clear and precise.

Accuracy?

Let's go back to the previous example: we'll get the square root of a number, and then square that value.

>>> pow( 3, 0.5 )
1.7320508075688772
>>> _ ** 2
2.9999999999999996
>>> pow( 3, 0.5 ) ** 2
2.9999999999999996

Here's a big question: what is that “.9999999999999996” foolishness?

That's the left-overs from the conversion from our decimal notation to the computer's internal binary and back to human-friendly decimal notation. We talked about it briefly in the section called “Floating-Point Numbers, Also Known As Scientific Notation”. If we know the order of magnitude of the result, we can use the round function to clean up this kind of small error. In this case, we know the answer is supposed to be a whole number, so we can round it off.

>>> pow( 3, 0.5 ) ** 2
2.9999999999999996
>>> round( _ )
3.0

Debugging Function Expressions

If you look back at Syntax Rule Six, you'll note that the ()'s need to be complete. If you accidentally type something like round(2.45 with no closing ), you'll see the following kind of exchange.

>>> round(2.45
...
... )
2.0

The ... is Python's hint that the statement is incomplete. You'll need to finish the ()'s so that the statement is complete.

Another Round, Please

Above, we noted that the round function had an optional argument. When something's optional, we can look at it as if there are two forms of the round function: a one-argument version and a two-argument version.

  • The one-argument round function rounds a number to the nearest whole number.

  • If you provide the optional second parameter, this is the number of decimal places to round to. If the number of decimal places is a positive number, this is decimal places to the right of the decimal point. If the number of decimal places is a negative number, this is the number of places to the left of the decimal point.

>>> round(678.456)
678.0
>>> round(678.456,2)
678.46
>>> round(678.456,-1)
680

So, rounding off to -1 decimal places means the nearest 10. Rounding off to -2 decimal places is the nearest 100. Pretty handy for doing business reports where we have to round off to the nearest million.

Functions are Factories (really!)

How do we get Python to do specific conversions among our various numeric data types? When we mix whole numbers and floating-point scientific notation, Python automatically converts everything to floating-point. What if we want the floating-point number truncated down to a whole number instead?

Here's another example: what if we want the floating-point number transformed into a long integer instead of the built-in assumption that we want long integers turned into floating-point numbers? How do we control this coercion among numbers?

Python has a number of factory functions that do this kind of number conversion. Each function is a factory that creates a new number from an existing number. Python has numerous factory functions, these are some of the most commonly-used.

These factory functions will also create numbers from string values. When we write programs that read their input from files, we'll see that files mostly have strings. Factory functions will be an important part of reading strings from files and creating numbers from those strings so that we can process them.

float (x ) creates a floating-point number equal to the string or number x. If a string is given, it must be a valid floating-point number: digits, decimal point, and an exponent expression. You can use this function when doing division to prevent getting the simple integer quotient.

For example:

>>> float(22)/7
3.14285714286
>>> 22/7
3
>>> float("6.02E24")
6.0200000000000004e+024

int (x ) creates an integer equal to the string or number x. This will chop off all of the digits to the right of the decimal point in a floating-point number. If a string is given, it must be a valid decimal integer string.

>>> int('1234')
1234
>>> int(3.14159)
3

long (x ) creates a long integer equal to the string or number x. If a string is given, it must be a valid decimal integer. The expression long(2) has the same value as the literal 2L. Examples: long(6.02E23), long(2).

>>> long(2)**64
18446744073709551616L
>>> long(22.0/7.0)
3L

The first example shows the range of values possible with 64-bit integers, available on larger computers. This is a lot more than the paltry two billion available on a 32-bit computer.

Complex Numbers - Math wizards only. Complex is not as simple as the others. A complex number has two parts, real and imaginary. Conversion to complex typically involves two parameters.

The complex function creates a complex number with the real part of real; if the second parameter, imag, is given, this is the imaginary part of the complex number, otherwise the imaginary part is zero. Examples:

>>> complex(3,2)
(3+2j)
>>> complex(4)
(4+0j)

Note that the second parameter, with the imaginary part of the number, is optional. This leads to two different ways to evaluate this function. In the example above, we used both variations.

Conversion from a complex number (effectively two-dimensional) to a one-dimensional integer or float is not directly possible. Typically, you'll use abs(x) to get the absolute value of the complex number. This is the geometric distance from the origin to the point in the complex number plane. The math is straight-forward, but beyond the scope of this introduction to Python.

>>> abs( 3+4j )
5.0

The Formal Definitions. Here are the formal definitions for these factory functions.

int, float, long and complex Function Definitions

integerint(number);
number;

Generates an integer from number.

floatfloat(number);
number;

Generates an floating-point number from number.

longlong(number);
number;

Generates a long integer from number.

complexcomplex(real, imag);
real;
imag;

Generates a complex number from real or from real and imag. If imag is not supplied, it is zero.

If this “complex (real, [imag] )” syntax synopsis with the 〈 and 〉is confusing, you'll need to see Function Syntax Rules.

Going the Other Way

If the int function turns a string of digits into a proper number, can we do the opposite thing and turn an ordinary number into a string of digits?

The str(x) and repr(x) functions convert any Python object to a string. The str(x) string is typically more readable, where the repr(x) string can help us see what Python is doing under the hood. For most garden-variety numeric values, there is no difference. For the more complex data types, however, the results of repr and str can be different.

Here are some examples of converting floating-point expressions into strings of digits.

>>> str( 22/7.0 )
'3.14285714286'
>>> repr( 355/113. )
'3.1415929203539825'

Here are the formal definitions of these two functions. These aren't very useful now, but we'll return to them time and again as we learn more about how Python works.

str and repr Function Definitions

stringstr(object);
object;

Creates a string representation of object.

stringrepr(object);
object;

Creates a string representation of object in Python syntax.

Most and Least

The max and min functions accept any number of values and return the largest or smallest of the values. These functions work with any type of data. Be careful when working with strings, because these functions use alphabetical order, which has some surprising consequences.

>>> max( 10, 11, 2 )
11
>>> min( 'asp', 'adder', 'python' )
'adder'
>>> max( '10', '11', '2' )
'2'

The last example (max( '10', '11', '2' )) shows the “alphabetical order of digits” problem. Superficially, this looks like three numbers (10, 11 and 2). But, they are quoted strings, and might as well be words. What would be result of max( 'ba', 'bb', 'c' ) be? Anything surprising about that? The alphabetic order rules apply when we compare string values. If we want the numeric order rules, we have to supply numbers instead of strings.

Here are the formal definitions for these functions.

max and min Function Definitions

valuemax(sequence);
sequence;

Returns the largest value in sequence.

valuemin(sequence);
sequence;

Returns the smallest value in sequence.

Basic Function Exercises

  1. Numeric Expressions. Write an expression to convert the mixed fraction 3 5/8 to a floating-point number.

  2. Truncation. Evaluate (22.0/7.0)-int(22.0/7.0). What is this value? Compare it with 22.0/7.0. What general principal does this illustrate?

  3. Illegal Conversions. Try illegal conversions like int('A'), int( 3+4j ), int( 2L**64 ). Why are exceptions raised? Why can't a simple default value like zero be used instead?

Chapter 10. Extra Functions: math and random

Batteries Included or All The Math You'll Ever Need

In Meaningful Chunks and Modules, we'll digress to look at the extension library thing. This is because the bulk of the math functions are in a separate module, called math, which we will cover in The math Module — Trig and Logs. We'll also look at the random number generators in The random Module — Rolling the Dice.

For those who will be using Python for financial and other fixed-point calculations, we'll look at fixed-point math, also. However, we'll defer this until Fixed-Point Numbers — Doing High Finance because it is a bit more advanced than using the built-in types of numbers.

Meaningful Chunks and Modules

Python's use of modules is a way to break the solution to a problem down into meaningful chunks. We hinted around about this in Core Coolness. There are dozens of standard Python modules that solve dozens of problems for us. We're not ready to look at modules in any depth, that comes later in Organizing Programs with Modules. This section has just a couple of steps to start using modules so that you can make use of two very simple modules: math and random.

A Python module extends the Python language by adding new classes of objects, new functions and helpful constants. The import statement tells Python to fetch a module, adding that module to the language. For now, we'll use the simplest form: import.

import m

This statement will tell Python to locate the module named m and gather up the definitions. Only the name of the module, m, is added to the local names that we can use. Every name inside module m must be qualified by the module name. We do this by connecting the module name and the function name with a .. When we import module math, we get a cosine function that we refer to with module name dot function name: math.cos.

This module qualification has a cost and a benefit. The cost is that you have to type the module name over and over again. The benefit is that your Python statements are explicit and harbor no assumptions. There are some alternatives to this. We'll cover it when we explore modules in depth.

Another important thing to remember is that you only need to import a module once to tell Python you will be using it. By once, we mean once each time you run the Python program. Each time you exit from the Python program (or turn your computer off, which exits all your programs), everything is forgotten. Next time you run the Python program, you'll need to provide the import statements to add the modules to Python for your current session.

Debugging an Import

If you import a module more than once in a session, no harm is done, Python already knows the module name and doesn't import it a second time. If you forget to import a module, however, you'll see something like this:

>>> math.cos( math.pi/2 )

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in -toplevel-
    math.cos( math.pi/2 )
NameError: name 'math' is not defined

When we see errors like this, we have two possible solutions:

  • Check the spelling of the module name, perhaps we got it wrong.
  • Import the module.

An Interesting Example. For fun, try this:

import this

The this module is atypical: it doesn't introduce new object classes or function definitions. Instead, well, you see that it does instead of extending Python by adding new definitions.

Even though the this module is atypical, you can still see what happens when you use an extra import. What happens when you try to import this a second time?

The math Module — Trig and Logs

The math module defines the common trigonometry and logarithmic functions. It has a few other functions that are handy, like square root. The math module is made available to your programs with:

import math

Since this statement only adds math to the names Python can recognize, you'll need to use the math. prefix to identify the functions which are inside the math module.

Here are a couple of examples of some trigonometry. We're calculating the cosine of 45, 60 and 90 degrees. You can check these on your calculator. Or, if you're my age, you can use a slide rule to confirm that these are correct answers.

>>> import math
>>> math.cos( 45 * math.pi/180 )
0.70710678118654757
>>> math.cos( 60 * math.pi/180 )
0.50000000000000011
>>> math.cos( 90 * math.pi/180 )
6.1230317691118863e-017
>>> round( math.cos( 90*math.pi/180 ), 3 )
0.0

Debugging Math Functions

The most common problem when using math functions is leaving off the math. to qualify the various functions imported from this module. If you get a “NameError: name 'cos' is not defined” error message, it means you haven't included the math qualifier.

The next most common problem is forgetting to import math each time you run IDLE or Python. You'll get a NameError: name 'math' is not defined error if you forgot to import math.

The other common problem is failing to convert angles from degrees to radians.

The math module contains the following trigonometric functions. The trig functions all use radians to measure angles. If your problem uses degrees, you'll have to convert from degrees to radians. If your trigonometry is rusty, remember that 2π radians are 360 degrees.

Trigonometry Function Definitions

numberacos(x);
x;

Returns the arc cosine of x.

numberasin(x);
x;

Returns the arc sine of x.

numberatan(x);
x;

Returns the arc tangent of x.

numberatan2(y, x);
y;
x;

Returns the arc tangent of y/x.

numbercos(x);
x;

Returns the cosine of x radians.

numbercosh(x);
x;

Returns the hyperbolic cosine of x radians.

numbersin(x);
x;

Returns the sine of x radians.

numbersinh(x);
x;

Returns the hyperbolic sine of x radians.

numbertan(x);
x;

Returns the tangent of x radians.

numbertanh(x);
x;

Returns the hyperbolic tangent of x radians.

Additionally, the following constants are also provided.

pi
The value of π, 3.1415926535897931
e
The value of e, 2.7182818284590451, used for the exp(x) and log(x) functions.

Here's an example of using some of these more advanced math functions. Here is a trig identity for the cosine of 39 degrees. We use 39*math.pi/180 to convert from degrees to radians. We also use the square root function (sqrt).

>>> import math
>>> math.sqrt( 1-math.sin(39*math.pi/180)**2 )
0.77714596145697101
>>> math.cos( 39*math.pi/180 )
0.7771459614569709

Here are some more of these common trigonometric functions, including logarithms, anti-logarithms and square root.

>>> math.exp( math.log(10.0) / 2 )
3.1622776601683795
>>> math.pow( 10.0, 0.5 )
3.1622776601683791
>>> math.sqrt( 10.0 )
3.1622776601683795

Logarithm Function Definitions

numberexp(x);
x;

Returns e**x, inverse of log (x ).

numberhypot(x, y);
x;
y;

Returns the Euclidean distance, sqrt(x*x + y*y), length of the hypotenuse of a right triangle with height of y and length of x.

numberlog(x);
x;

Returns the natural logarithm (base e) of x, inverse of exp (x).

numberlog10(x);
x;

Returns the logarithm (base 10) of x, inverse of 10**x.

floatpow(x, y);
x;
y;

Returns x**y.

numbersqrt(x);
x;

Returns the square root of x. This version returns an error if you ask for sqrt(-1), even though Python understands complex and imaginary numbers. A second module, cmath, includes a version of sqrt(x) which correctly creates imaginary numbers.

More math Functions

The following batch of functions supplement the basic round function with more sophisticated computations on floating-point numbers. You can probably guess from the names what ceiling and floor mean.

>>> math.ceil( 2.1 )
3.0
>>> math.floor( 2.999 )
2.0

The math module contains the following other functions for dealing with floating-point numbers.

Other Floating-Point Function Definitions

numberceil(x);
x;

Returns the next larger whole number. math.ceil(5.1) == 6, math.ceil(-5.1) == -5.0.

numberfabs(x);
x;

Returns the absolute value of the x as a floating-point number.

numberfloor(x);
x;

Returns the next smaller whole number. math.floor(5.9) == 5, math.floor(-5.9) == -6.0.

numberfmod(x, y);
x;
y;

Returns the remainder after division of x/y, doing the calculation with floating-point numbers, This depends on the platform's portable C library and may return a different result than the Python x % y.

Misuse and Abuse

Some of the math functions only work for a limited domain of values. Specifically, square root is only defined for non-negative numbers and logarithms are only defined for positive numbers. What does Python do when we violate these rules?

Try the following expressions

math.sqrt(-1)
math.log(-1)
math.log(0)

You'll see one of two kinds of results. The details vary among the operating systems.

  • You'll see a result of nan. This is a special code that means Not a Number.

  • You'll see an exception, like ValueError or OverflowError. An exception will display a bunch of debugging information that ends with the exception name and a short explanation.

Both results amount to the same thing: the result cannot be computed.

The random Module — Rolling the Dice

The random module defines functions that simulate random events. This includes coin tosses, die rolls and the spins of a Roulette wheel. The random module is made available to your program with:

import random

Since this statement only adds random to the names Python can recognize, you'll need to use the random. prefix on each of the functions in this section.

The randrange is a particularly flexible way to generate a random number in a given range. Here's an example of some of the alternatives. Since the answers are random, your answers may be different from these example answers. This shows a few of many techniques available to generate random data samples in particular ranges.

>>> random.randrange(6)
3
>>> random.randrange(1,7)
3
>>> random.randrange(2,37,2)
6
>>> random.randrange(1,36,2)
5
1

We're asking for a random number, n, such that 0 ≤ n < 6. The number will be between 0 and 5, inclusive.

2

We're asking for a random number, n, such that 1 ≤ n < 7. The number will be between 1 and 6, inclusive.

3

We're asking for a random number, 2n, such that 2 ≤ 2n < 37. The number will be even and between 2 and 36, inclusive.

4

We're asking for a random number, 2n+1, such that 1 ≤ 2n+1 < 36. The number will be an odd number between 1 and 35, inclusive.

The random module contains the following functions for working with simple distributions of random numbers. There are several more sophisticated distributions available for more complex kinds of simulations. Casino games only require these functions.

Random Function Definitions

valuechoice(sequence);
sequence;

Chooses a random value from the sequence sequence. Example: random.choice( ['red', 'black', 'green'] ).

numberrandom();

Creates a random floating-point number, r, such that 0 ≤ r < 1.0. Note that random doesn't require any arguments, but does require the empty ()'s to alert Python that it is really the name of a function. We use it like this: random.random().

integerrandrange(start, stop, step);
start;
stop;
step;

Chooses a random element from range (start, stop, step). We'll revisit this in the section called “Built-in Functions for Lists”. For now, we'll stick with the following examples: randrange(6) returns a number, n, 0 ≤ n < 6. randrange(1,7) returns a number, n, 1 ≤ n < 7. randrange(10,100,5) returns a number, n, between 10 and 95 incremented by 5's, 10 ≤ 5k < 100.

numberuniform(a, b);
a;
b;

Creates a random floating-point number, r, such that ar < b.

Extra Function Exercises

  1. Evaluate These Expressions. The following expressions are somewhat more complex, and use functions from the math module.

    math.sqrt( 40.0/3.0 - math.sqrt(12.0) )

    6.0/5.0*( (math.sqrt(5)+1) / 2 )**2

    math.log( 2198 ) / math.sqrt( 6 )

  2. Tossing a Coin. There are several ways the random module can be used to simulate tossing a coin. Write expressions that use choice and randrange.

    Additionally, using something like int( random()*x ) you can simulate a coin toss. If we use zero for heads and 1 for tails, what is an appropriate value for x? What if we use round instead of int? What about ciel and floor?

    Can you also use uniform to simulate a coin toss? Do you need to also use int?

Function FAQ's

1. Why do functions have an usual syntax?
2. Why is math (or random or decimal) a separate module?
3. But everything I do involves math (or random or decimal), why do I have to import it in every single script?
1.

Why do functions have an usual syntax?

Python functions all consistently look a little like the mathematical sin(x). Mathematicians have evolved a number of other forms for functions. Python's syntax is, at least, consistent. Rather than ask why Python looks the way it does, we prefer to ask why the mathematicians have so many different forms for functions.

2.

Why is math (or random or decimal) a separate module?

There are two reasons for keeping math ( or random or decimal) in separate modules.

  • Not everyone needs math so why include it needlessly?
  • There will always be new implementations of basic numeric algorithms with different trade-offs for range, precision, speed and amount of storage. Rather than pick one, Python leaves it to you to select among the various alternatives and pick that one that best meets your needs.
3.

But everything I do involves math (or random or decimal), why do I have to import it in every single script?

There is one very important reason for importing the module in every single script. It keeps you (and Python) honest: nothing is assumed. You said you needed math, making it clear to everyone else who reads your script. While you know that all your programs are mathematical, almost no one else knows this. The import statement sets the assumptions on a script-by-script basis, making each a successful, stand-alone program, without requiring any insider information or background to understand it.

Chapter 11. Special Ops

Binary Data and Operators

While we write numbers using decimal digits, base 10, computers don't really work that way internally. We touched on the computer's view in Octal and Hexadecimal — Counting by 8's or 16's. Internally, the computer works in binary, base 2, which makes the circuitry very simple and very fast. One of the benefits of using Python is that we don't need to spend much time on the internals, so this chapter is optional.

We'll take a close look at data in Bits and Bytes, this will provide some justification for having base 8 and base 16 numbers. We'll add some functions to see base 8 and base 16 in Different Bases and Representations. Then we'll look at the operators for working with individual bits in Operators for Bit Manipulation.

On a minimally-related topic, we'll look more closely at the two division operators in The Two Specialized Division Operators. This is also optional material. We include it because you might be reading someone else's program which uses the // operator, and you want to know what it means.

Bits and Bytes

The special operators that we're going to cover in this chapter work on individual bits. First, we'll have to look at what this really means. Then we can look at what the operators do to those things called bits.

A bit is a “binary digit”. The concept of bit closely parallels the concept of decimal digit with one important difference. There are only two binary digits (0 and 1), but there are 10 decimal digits (0 through 9).

Decimal Numbers. Our decimal numbers are a sequence of digits using base 10. Each decimal digit's place value is a power of 10. We have the 1,000's place, the 100's place, the 10's place and the 1's place. A number like 2185 is 2 × 1000 + 1 × 100 + 8 × 10 + 5.

Binary Numbers. Binary numbers are a sequence of binary digits using base 2. Each bit's place value in the number is a power of 2. We have the 256's place, the 128's place, the 64's place, the 32's place, the 16's place, the 8's, 4's, 2's and the 1's place. We can't directly write binary numbers in Python. We'll show them as a series of bits, like this 1-0-0-0-1-0-0-0-1-0-0-1. This starts with a 1 in the 2048's place, a 1 in the 128's place, plus a 1 in the 8's place, plus a 1, which is 2185.

Octal Numbers. Octal numbers use base 8. In Python, we begin octal numbers with a leading zero. Each octal digit's place value is a power of 8. We have the 512's place, the 64's place, the 8's place and the 1's place. A number like 04211 is 4 × 512 + 2 × 64 + 1 × 8 + 1 = 2185 in decimal.

Each group of three bits forms an octal digit. This saves us from writing out all those bits in detail. Instead, we can summarize them.

Binary: 1-0-0  0-1-0  0-0-1  0-0-1
Octal:    4      2      1      1

Hexadecimal Numbers. Hexadecimal numbers use base 16. In Python, we begin hexadecimal numbers with a leading 0x. Since we only have 10 digits, and we need 16 digits, we'll borrow the letters a, b, c, d, e and f to be the extra digits. Each hexadecimal digit's place value is a power of 16. We have the 4096's place, the 256's place, the 16's place and the 1's place. A number like 0x8a9 is 8 × 256 + 10 × 16 + 9 = 2217 in decimal.

Each group of four bits forms a hexadecimal digit. This saves us from writing out all those bits in detail. Instead, we can summarize them.

Binary:      1-0-0-0  1-0-1-0  1-0-0-1
Hexadecimal:    8        a        9

Bytes. A byte is 8 bits. That means that a byte contains bits with place values of 128, 64, 32, 16, 8, 4, 2, 1. If we set all of these bits to 1, we get a value of 255. A byte has 256 distinct values. Computer memory is addressed at the individual byte level, that's why you buy memory in units measured in megabytes or gigabytes.

In addition to small numbers, a single byte can store a single character encoded in ASCII. It takes as many as four bytes to store characters encoded with Unicode.

An integer has 4 bytes, which is 32 bits. In looking at the special operators, we'll look at them using integer values. Python can work with individual bytes, but it does this by unpacking a byte's value and saving it in a full-sized integer.

Different Bases and Representations

In Octal and Hexadecimal — Counting by 8's or 16's we saw that Python will accept base 8 or base 16 (octal or hexadecimal) numbers. We begin octal numbers with 0, and use digits 0 though 7. We begin a hexadecimal number with 0x and use digits 0 through 9 and a through f.

Python normally answers us in decimal. How can we ask Python to answer in octal or hexadecimal instead?

The hex(n) function converts its argument to a hexadecimal (base 16) string. A string is used because additional digits are needed beyond 0 through 9; a-f are pressed into service. A leading 0x is placed on the string as a reminder that this is hexadecimal. Here are some examples:

>>> hex(684)
'0x2ac'
>>> hex(1023)
'0x3ff'
>>> 0xffcc33
16763955
>>> hex(_)
'0xffcc33'

Note that the result of the hex function is technically a string, An ordinary number would be presented as a decimal value, and couldn't contain the extra hexadecimal digits. That's why there are apostrophes in our output.

The oct(n) function converts its argument to an octal (base 8) string. A leading 0 is placed on the string as a reminder that this is octal not decimal. Here are some examples:

>>> oct(512)
'01000'
>>> oct(509)
'0775'.

Here are the formal definitions.

hex and oct Function Definitions

stringhex(number);
number;

Creates a hexadecimal string representation of number.

stringoct(number);
number;

Creates an octal string representation of number.

More Hexadecimal and Octal tools. The hex and oct functions make a number into a specially-formatted string. The hex function creates a string using the hexadecimal digit characters. The oct uses the octal digits. There is a function which goes the other way: it can convert strings of digit characters into proper numbers so we can do arithmetic.

The int function has two forms. The int (x) form converts a decimal string, x, to an integer. For example int('25') is 25. The int (x, b) form converts a string, x, in base b to an integer.

In case you don't recall how this works, remember that in the number 1985, we're implicitly computing 1*10**3 + 9*10**2 + 8*10 + 5. Each digit has a place value that is a power of some number. That number is the "base" for the numbers we're writing. Python assumes that a string of digits is decimal. A string of digits which begins with 0 is in base 8. A string of digits which begins with 0x is in base 16.

Here are some examples of converting strings that are in other bases to good old base 10 numbers.

>>> int('010101',2)
21
>>> int('321',4)
57
>>> int('2ac',16)
684

In base 2, the place values are 32, 16, 8, 4, 2, 1. The string 10101 is evaluated as 1*16 + 1*4 + 1 = 21.

In base 4, the place values are 16, 4 and 1. The string 321 is evaluated as 3*16 + 2*4 + 1 = 57.

Recall from the section called “Octal and Hexadecimal — Counting by 8's or 16's” that we have to press additional symbols into service to represent base 16 numbers. We use the letters a-f for the digits after 9. The place values are 256, 16, 1; the string 2ac is evaluated as 2*256 + 10*16 + 12 = 684.

While it seems so small, it's really important that numbers in another base are written using strings. To Python, 123 is a decimal number. '123' is a string, and could mean anything. When you say int('123',4), you're telling Python that the string '123' should be interpreted as base 4 number, which maps to 27 in base 10 notation. On the other hand, when you say int('123'), you're telling Python that the string '123' should be interpreted as a base 10 number, which is 123.

int Function Definition

integerint(x, base);
x;
base;

Generates an integer from the value x. If x is a string, and base is supplied, x must be proper number in the given base. If base is omitted, and x is a string, it must be decimal.

Operators for Bit Manipulation

We've already seen the usual math operators: +, -, *, /, %, **; as well as a large collection of mathematical functions. While these do a lot, there are still more operators available to us. In this section, we'll look at operators that directly manipulate the binary representation of numbers. The inhabitants of Binome (see Binary Codes are more comfortable with these operators than we are.

We won't wait for the FAQ's to explain why we even have these operators. These operators exist to provide us with a view of the real underlying processor. Consequently, they are used for some rather specialized purposes. We present them because they can help newbies get a better grip on what a computer really is.

In this section, we'll see a lot of hexadecimal and octal numbers. This is because base 16 and base 8 are also nifty short-hand notation for lengthy base 2 numbers. We'll look at hexadecimal and octal numbers first. Then we'll look at the bit-manipulation operators.

There are some other operators available, but, strictly speaking, they're not arithmetic operators, they're logic operations. We'll return to them in Conditional Processing: Only When Necessary.

Precedence. We know one basic precedence rule that applies to multiplication and addition: Python does multiplication first, and addition later. The second rule is that ()'s group things, which can change the precedence rules. 2*3+4 is 10, but 2*(3+4) is 14.

Where do these special operators fit? Are they more important than multiplication? Less important than addition? There isn't a simple rule. Consequently, you'll often need to use ()'s to make sure things work out the way you want.

The ~ operator. The unary ~ operator flops all the bits in a plain or long integer. 1's become 0's and 0's become 1's. Note that this will have unexpected consequences when the bits are interpreted as a decimal number.

>>> ~0x12345678
-305419897
>>> hex(~0x12345678)
'-0x12345679'

What makes this murky is the way Python interprets the number has having a sign. The computer hardware uses a very clever trick to handle signed numbers. First, let's visualize the unsigned, binary number line, it has 4 billion positions. At the left we have all bits set to zero. In the middle we have a value where the 2-billionth place is 1 and all other values are zero. At the right we have all bits set to one.

Figure 11.1. The Basic Number Line

The Basic Number Line

Now, let's redraw the number line with positive and negative signs. Above the line, we put the signed values that Python will show us. Below the line, we put the internal codes used. The positive numbers are what we expected: 0x00000000 is the full 32-bit value for zero, 1 is 0x00000001; no surprise there. Below the 2 billion, we put 0x7fffffff. That's the full 32-bit value for positive 2 billion (try it in Python and see.) Below the -2 billion, we put 0x80000000, the full 32-bit value for -2 billion. Below the -1, we put 0xffffffff.

Figure 11.2. Encoding Signs On The Number Line

Encoding Signs On The Number Line

This works very nicely. Let's start with -2 (0xfffffffe). We add 1 to this and get -1 (0xffffffff), just what we want. We add 1 to that and get 0x00000000, and we have to carry the 1 into the next place value. However, there is no next place value, the 1 is discarded, and we have a good-old zero.

This technique is called 2's complement. Consequently, the ~ operation is mathematically equivalent to adding 1 and switching the number's sign between positive and negative.

This operator has the same very high precedence as the ordinary negation operation, -. Try the following to see what happens. First, what's the value of -5+4? Now, add the two possible ()'s and see which result is the same: (-5)+4 and -(5+4). The one the produces the same result as -5+4 reveals which way Python performs the operations.

Here are some examples of special ops mixed with ordinary operations.

>>> -5+4
-1
>>> -(5+4)
-9
>>> (-5)+4
-1

The & operator. The binary & operator returns 1-bits everywhere that the two input bits are both 1. Each result bit depends on one input bit and the other input bit both being 1. The following example shows all four combinations of bits that work with the & operator.

>>> 0&0, 1&0, 1&1, 0&1
(0, 0, 1, 0)

Here's the same kind of example, combining sequences of bits. This takes a bit of conversion to base 2 to understand what's going on.

>>> 3 & 5
1

The number 3, in base 2, is 0011. The number 5 is 0101. Let's match up the bits from left to right:

  0 0 1 1
& 0 1 0 1
  -------
  0 0 0 1

This is a very low-priority operator, and almost always needs parentheses when used in an expression with other operators. Here are some examples that show you how & and + combine.

>>> 3&2+3
1
>>> 3&(2+3)
1
>>> (3&2)+3
5

The ^ operator. The binary ^ operator returns a 1-bit if one of the two inputs are 1 but not both. This is sometimes called the exclusive or operation to distinguish it from the inclusive or. Some people write “and/or” to emphasize the inclusive sense of or. They write “either-or” to emphasize the exclusive sense of or.

>>> 3^5
6

Let's look at the individual bits

  0 0 1 1
^ 0 1 0 1
  -------
  0 1 1 0

Which is the binary representation of the number 6.

This is a very low-priority operator, be sure to parenthesize your expression correctly.

The | operator. The binary | operator returns a 1-bit if either of the two inputs is 1. This is sometimes called the inclusive or to distinguish it from the exclusive or.

>>> 3|5
7
>>>

Let's look at the individual bits.

  0 0 1 1
| 0 1 0 1
  -------
  0 1 1 1

Which is the binary representation of the number 7.

This is a very low-priority operator, and almost always needs parentheses when used in an expression with other operators. When we combine &'s and |'s we have to be sure we've grouped them properly. Here's the kind of thing that you'll sometimes see in programs that build up specific patterns of bits.

>>> 3&0x1f|0x80|0x100
387
>>> hex(_)
'0x183'

Let's look at this in a little bit of detail. Our first expression has two or operations, they're the lowest priority operators. The first or operation has 3&0x1f or 0x80. So, Python does the following steps to evaluate this expression.

  1. Calculate the and of 3 and 0x1f. This is 3 (try it and see.) You can work it out by hand if you know that 3 is 0-0-0-1-1 in binary and 0x1f is 1-1-1-1-1.

  2. Calculate the or of the previous result (3) and 0x80.

  3. Calculate the or of the previous result (0x83) and 0x100. This has the decimal value of 387.

  4. Calculate the hex string for the previous result, using the _ short-hand for the previously printed result. This shows that the hex value is 0x183, what we expected.

The << Operator. The << is the left-shift operator. The left argument is the bit pattern to be shifted, the right argument is the number of bits. This is mathematically equivalent to multiplying by a power of two, but much, much faster. Shifting left 3 positions, for example, multiplies the number by 8.

This operator is higher priority than &, ^ and |. Be sure to use parenthesis appropriately.

>>> print 0xA << 2
40

0xA is hexadecimal; the bits are 1-0-1-0. This is 10 in decimal. When we shift this two bits to the left, it's like multiplying by 4. We get bits of 1-0-1-0-0-0. This is 40 in decimal.

The >> Operator. The >> is the right-shift operator. The left argument is the bit pattern to be shifted, the right argument is the number of bits. Python always behaves as though it is running on a 2's complement computer. The left-most bit is always the sign bit, so sign bits are shifted in. This is mathematically equivalent to dividing by a power of two, but much, much faster. Shifting right 4 positions, for example, divides the number by 16.

This operator is higher priority than &, ^ and |. Be sure to use parenthesis appropriately.

>>> print 80 >> 3
10

The number 80, with bits of 1-0-1-0-0-0-0, shifted right 3 bits, yields bits of 1-0-1-0, which is 10 in decimal.

Debugging Special Operators

The most common problems with the bit-fiddling operators is confusion about the relative priority of the operations. For conventional arithmetic operators, ** is the highest priority, * and / are lower priority and + and - are the lowest priority. However, among &, ^ and |, << and >> it isn't obvious what the priorities are or should be.

When in doubt, add parenthesis to force the order you want.

The Two Specialized Division Operators

While most features of Python correspond with common expectations from mathematics and other programming languages, the division operator, /, has certain complexities. This is due to the lack of a common expectation for what division should mean. In a mathematics text book, the author will provide additional explanations to clarify the precise meaning of an operator. In a Python program, also, we need to clarify the precise meaning of the / operator.

A basic tenet of Python is that the data determine the result of an operation. For example, when we say 2+3, both numbers are plain integers, and the result is expected to be a plain integer. When we say 2+3.14, Python will coerce the 2 to be the mathematically equivalent 2.0; now both numbers are floating-point, and the answer can be a floating-point number.

This rule meets most of our expectations for ordinary math. However, this doesn't work out well for division because there are two different, conflicting expectations:

  • Sometimes we expect division to create precise answers, usually the floating-point equivalents of fractions.
  • Other times, we want a rounded-down integer result.

There's no best answer and no real compromise. Try the following to see what Python does.

>>> 355/113
>>> 355.0/113
>>> 355/113.0
>>> 355.0/113.0

The Unexpected Integer. Here are two examples of the classical definition of division. We've used the formula for converting 18° Celsius to Fahrenheit. The first version uses integers, and gets an integer result. The second uses floating-point numbers, which means the result is floating-point.

>>> 18*9/5+32
64
>>> 18.0*9.0/5.0 + 32.0
64.4

In this example, we got an inaccurate answer from a formula that we are sure is correct. When a formula has a / operator, the inaccuracy can stem from the use of integers where floating-point numbers were more appropriate. (This can also occur using integers where complex numbers were implicitly expected.)

When we used integers, we got a Fahrenheit temperature of 64, which wasn't precisely correct. When we used floating-point numbers, we got a value of 64.4, which was correct.

The Problem. The problem we have is reconciling the basic rule of Python (data determines the result) and the two conflicting meanings for division. We have a couple of choices for the solution.

We could solve this by using explicit conversions like float(x) or int(x). The idea, however, is for Python be a simple and sparse language, without a dense clutter of conversions to cover the rare case of an unexpected type of data.

Instead, Python has two division operators. For precise fractional results, the / will work nicely.

There are times when we want division to simply compute the quotient. For this reason, Python has a second division operator, //. This more specialized // operator will produces rounded-down integer answers, even if both numbers happen to be floating-point.

Additional Tools. In addition to having two division operators, Python gives us two tools to clarify the precise meaning of the / operator. There are two parts to this: a statement that can be placed in a program, as well as a command-line option that can be used when starting the Python program.

  • We can specify that the division operator, /, will operate under the classical rules where the type of data determines the result. If we do this, we may have to add float(x) or int(x) conversions.
  • We can specify that we are using the new rules. In the cases that we want rounded-down division, we can use the // operator, and when we want precise fractional answers, we can use the / operator.

Program Statements to Control /To ease the transition from older to newer language features, there is a from __future__ import division statement that changes the definition of the / operator from classical (depends on the arguments) to future (always produces floating-point).

Note that __future__ has two underscores before and after future.

>>> 18*9/5+32
64
>>> from __future__ import division
>>> 18*9/5+32
64.4
>>> 18*9//5+32
64
1

We used the classical definition of the / operator and got an inaccurate result.

2We set the future definition of the / operator.
3This line shows the new use of the / operator to produce precise floating-point results, even if both arguments are integers.
4This line shows the // operator, which always produces rounded-down results.

The from __future__ statement will set the expectation that your script uses the new-style floating-point division operator. This allows you to start writing programs with version 2.4 that will work correctly with all future versions. By version 3.0, this import statement will no longer be necessary, and will have to be removed from the few modules that used them.

Debugging The from __future__

There are two common spelling mistakes: omitting the double underscore from before and after __future__, and misspelling division.

  • If you get ImportError: No module named _future_, you misspelled __future__.
  • If you get SyntaxError: future feature divinizing is not defined, you misspelled division.

Command Line Options to Control /Another tool to ease the transition is an option that we can use as part of the python command that starts the Python interpreter. This option can force a particular interpretation of the / operator or warn about incorrect use of the / operator.

The Python command-line option of -Q controls the meaning of the / operator.

  • If you run Python with -Qold, you get the classical definition, where the / operator's result depends on the arguments.
  • If you run Python with -Qnew, the / operator's result will be a precise floating-point fraction.

Here's how it looks when we start Python with the -Qold option.

MacBook-2:~ slott$ python -Qold
Python 2.4.4 (#1, Oct 18 2006, 10:34:39) 
[GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 355/113
3
>>> 355./113.
3.1415929203539825
>>> 355.//113.
3.0
1

Here is the python command with the -Qold option. This will set Python to do classical interpretation of the / operator.

2

When we do old-style / division with integers, we get an integer result.

3

When we do old-style / division with floating-point numbers, we get the precise floating-point result.

4

When we do // division with floating-point numbers, we get the rounded-down result.

Here's how it looks when we start Python with the -Qnew option.

MacBook-2:~ slott$ python -Qnew
Python 2.4.4 (#1, Oct 18 2006, 10:34:39) 
[GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 355/113
3.1415929203539825
>>> 355./113.
3.1415929203539825
>>> 355.//113.
3.0
1

Here is the python command with the -Qnew option. This will set Python to do the new interpretation of the / operator.

2

When we do new-style / division with integers, we get the precise floating-point result.

3

When we do new-style / division with floating-point numbers, we get the precise floating-point result.

4

When we do // division with floating-point numbers, we get the rounded-down result.

Some programmers will use -Qold to force an old module or program to work the way it used to when they running a new version of Python. When Python 3.0 is released, however, this transition will no longer be supported; by that time they should have fixed your programs and modules.

You can include the command line option when you run the Python interpreter. For GNU/Linux and MacOS users, you can also put the option on a special #! line that must be the first line of your script file.

#!/usr/bin/env python -Qnew

This #! technique doesn't work well for Windows. We'll cover this in detail in Chapter 23, Turning Python Loose with More Sophisticated Scripts for more information.

Debugging The -Q Option

If you misspell the -Q option you'll see errors like the following. If so, check your spelling carefully.

C:\Documents and Settings\SLott>python -Qwhat

-Q option should be `-Qold', `-Qwarn', `-Qwarnall', or `-Qnew' only
usage: python [option] ... [-c cmd | file | -] [arg] ...
Try `python -h' for more information.

If you get a message that includes Unknown option: -q, you used a lower-case q instead of an upper-case Q.

Special Ops Exercises

  1. Bit Masking. One common color-coding scheme uses three distinct values for the level of red, green and blue that make up each picture element (pixel) in an image. If we allow 256 different levels of red, green and blue, we can mash a single pixel in 24 bits. We can then cram 4 pixels into 3 plain-integer values. How do we unwind this packed data?

    We'll have to use our bit-fiddling operators to unwind this compressed data into a form we can process. First, we'll look at getting the red, green and blue values out of a single plain integer.

    We can code 256 levels in 8 bits, which is two hexadecimal digits. This gives us a red, green and blue levels from 0x00 to 0xFF (0 to 255 decimal). We can string the red, green and blue together to make a larger composite number like 0x0c00a2 for a very bluish purple.

    What is 0x0c00a2 & 0xff? Is this the blue value of 0xa2? Does it help to do hex( 0x0c00a2 & 0xff )?

    What is (0x0c00a2 & 0xff00) >> 8? hex( (0x0c00a2 & 0xff00) >> 8 )?

    What is (0x0c00a2 & 0xff0000) >> 16? hex( (0x0c00a2 & 0xff0000) >> 16 )?

  2. Division. How can we break a number down into different digits?

    What is 1956 / 1000? 1956 % 1000?

    What is 956 / 100? 956 % 100?

    What is 56 / 10? 56 % 10?

    What happens if we do this procedure with 1956., 956. and 56. instead of 1956, 956 and 56? Can we use the // operator to make this work out correctly?

Special Ops FAQ's

1. Why is there bit-fiddling?
2. Why are there two division operators?
1.

Why is there bit-fiddling?

Some processing requires manipulating individual bits. In particular, sound and image data is often coded up in a way that is best processed using these bit-fiddling operations. Additionally, the various compression schemes like MP3 and JPEG use considerable manipulation of individual bits of data.

2.

Why are there two division operators?

Sometimes we expect division to create precise answers, usually the floating-point equivalents of fractions. Other times, we want a rounded-down integer result. One way to work around this problem is to add lots of int functions to force integer operations. Another way is to provide two division operators with different meanings.

Chapter 12. Peeking Under the Hood

How Expressions Work

These are some optional topics to provide additional background in Python and programming. We'll talk a little about what it means to execute the statements in a program and evaluate expressions in Execution — Two Points of View. We'll provide some style notes in Expression Style Notes. Also, we'll talk about how fixed point math is implemented in One Way To Tackle Fixed Point Math.

Execution — Two Points of View

What does it mean when a computer “does” a specific task? This is the essential, inner mystery of programming. There are two overall approaches to specifying what should happen inside the computer. Most modern languages are a mixture of both approaches. These two approaches are sometimes called functional and procedural, or applicative and imperative. Since the programming language business is very competitive, any term we chose is loaded with meaning and many hairs get split in these conversations. We'll look at both the applicative and imperative views of Python, because Python uses each approach where it is appropriate.

Applicative Approach. Functional or applicative programming is characterized by a style that looks a lot like conventional mathematics. Functions are applied to argument values using an evaluate-apply cycle.

We can see the applicative approach when we look, for example, at . This can be interpreted as “evaluate c to get its current value (for example, 18); apply a multiply operation using 9 and the current value of c; apply a divide operation with the previous result (9c) and 5; apply an addition operation with 32 and the previous result (9c/5)”. The result is 64.4.

We call this process “expression evaluation”. We expect our programming language to apply math-like operations and functions using math-like rules: apply the parenthesized operations first, apply the high priority operations (like multiply and divide) in preference to low priority operations (like add and subtract).

Python has some sophisticated expression operators. Some of them transcend the simple add-subtract-multiple-divide category, and include operators that apply a function to a list to create a new list, apply a function to filter a list and apply a function to reduce a list to a single value.

When we evaluate a function like abs(-4), we name the -4 an argument to the function abs(x). When looking at 3+4, we could consider 3 and 4 to be argument values to the + function. We could — hypothetically — imagine rewriting 3+4 to be +(3,4) just to show what it really means.

Imperative Approach. On the other hand, the imperative style is characterized by using a sequential list of individual statements. Donald Knuth, in his Art of Computer Programming [Knuth72], shows a language he calls Mix. It is a purely imperative language, and is similar to the hardware languages used by many computer processor chips.

The imperative style lists a series of commands that the machine will execute. Each command changes the value of a register in the central processor, or changes the value of a memory location. In the following example, each line contains the abbreviation for a command and a reference to a memory location or a literal value. Memory locations are given names to make them easy to read. Literal values are surrounded by =. The following fragment uses a memory locations named C and F, as well as a processor register.

LDA C
MUL =9=
DIV =5=
ADD =32=
STA F

This first command loads the processor's A register with the value at memory location C. The second command multiplies the register by 9. The third command divides the register by 5. The next command adds 32 to the register. The final command stores the contents of the A register into the memory location of the variable F.

Python. Python, like many popular languages, has elements drawn from both applicative and imperative realms. We'll focus initially on expressions and expression evaluation, minimizing the imperative statements. We'll then add various procedural statements to build up to the complete language.

The basic rule is that each statement is executed by first evaluating all of the expressions in that statement, then performing the statement's task. The evaluation of each expression is done by evaluating the parameters and applying the functions to the parameters.

This evaluate-apply rule is so important, we'll repeat here so that you can photocopy this page and make a counted cross-stitch sampler to hang over your computer. Yes, it's that important.

The Evalute-Apply Rule

Each statement is executed by (1) evaluating all of the expressions in that statement, then (2) performing the statement's task.

The evaluation of an expression is done by (1a) evaluating all parameters and (1b) applying the function to the parameters.

Example: (2+3)*4, evaluates two parameters: 2+3 and 4, and applies the function *. In order to evaluate 2+3, there are two more parameters: 2 and 3, and a function of +.

While it may seem excessive to belabor this point, many programming questions arise from a failure to fully grasp this concept. We'll return to it several times, calling it the evaluate-apply cycle. For each feature of the language, we need to know what happens when Python does its evaluation. This is what we mean by the semantics of a function, statement or object.

Expression Style Notes

There is considerable flexibility in the language; two people can arrive at different presentations of Python source. Throughout this book we will present the guidelines for formatting, taken from the Python Enhancement Proposal (PEP) 8, posted on www.python.org/pep.

Python programs are meant to be readable. The language borrows a lot from common mathematical notation and from other programming languages. Many languages (C++ and Java) for instance, don't require any particular formatting; line breaks and indentation become merely conventions; bad-looking, hard-to-read programs are possible. Python makes the line breaks and indentations part of the language, forcing you to create programs that are easier on the eyes.

Spaces are used sparingly in expressions. Spaces are never used between a function name and the ()'s that surround the arguments. It is considered poor form to write:

int (22.0/7)

A long expression may be broken up with spaces to enhance readability. For example, the following separates the multiplication part of the expression from the addition part with a few wisely-chosen spaces.

b**2 - 4*a*c

One Way To Tackle Fixed Point Math

In the section called “Floating-Point Numbers, Also Known As Scientific Notation”, we saw that floating-point numbers are for scientific and engineering use and don't work well for financial purposes. US dollar calculations, for example, are often done in dollars and cents, with two digits after the decimal point.

If we try to use floating-point numbers for dollar values, we have problems. Specifically, the slight discrepancy between binary-coded floating-point numbers and decimal-oriented dollars and cents become a serious problem. Try this simple experiment.

>>> 2.35
2.3500000000000001

There's a standard trick that can be used to solve this problem: use scaled numbers. When doing dollars and cents math, you can scale everything by 100, and do the math in pennies. When you print the final results, you can scale the final result into dollars with pennies to the right of the decimal point. This section will provide you some pointers on doing this kind of numeric programming.

Later, in Fixed-Point Numbers — Doing High Finance we'll look at the decimal module, which does this in a more sophisticated and flexible way.

Running Out Of Digits. There can be a difficult trade-off here. When we only have a fixed number of digits, we have to allocate the bits between left-of-the-decimal-point and right-of-the-decimal-point. We call this the range vs. precision problem: a bigger range of values means less available precision because we used too many digits on the left side; more precision means a lower range because we used too many digits on the right side.

Look at our 32-bit plain integers. We have numbers up to a hair over 2,000,000,000. When we scale this to allocate two digits for pennies, we only have a useful range of 20 million dollars. Fine for my household budget, but not much for a medium-sized company.

Python, however, removes this range vs. precision by giving us long integers. Since we have unlimited range, we can pick a useful precision without worrying about the range. We can easily do all the penny-denominated math that we care to do. The cost for this flexibility is speed: long integers are rather slow. If you are doing complex engineering calculations, you may not want to use long integers to represent fixed point numbers. However, if you are just adding up a list of financial accounts, long integers should perform quickly enough.

When we use scaled numbers, it means that the proper value is represented as a scaled value and the precision factor. For example, if we are doing our work in pennies, the value of $12.99 is represented as a scaled value of 1299 with a precision of 2 digits. The precision factor can be thought of as a power of 10. In our case of 12.99, our precision factor is 100.

We have three cases to think about when doing fixed-point math using scaled integers: addition (and subtraction), multiplication and division. Addition and subtraction don't change the precision. Multiplication increases the precision of the result and division reduces the precision. So, we'll need to look at each case carefully.

Addition and Subtraction. If our two numbers have the same precision, we can simply add or subtract normally. This is why we suggest doing everything in pennies: the precisions always match. If our two numbers have different precisions, we need to shift the smaller precision number. We do this by multiplying by an appropriate power of 10.

What is $12.00 + $5.99? Assume we have 12 (the precision is dollars) and 599 (the precision is pennies). We add them like this: 12*100 + 599. We applied the penny precision factor of 100 to transform dollars into pennies.

Multiplication. When we multiply two numbers, the result has the sum of the two precisions. If we multiply two amounts in pennies (2 digits to the right of the decimal point), the result has 4 digits of precision. We have to be careful when doing this kind of math to determine the rounding rules, and correctly scale the result.

What is 7.5% of $135.99? Assume we have 13599 (the precision is pennies, 2 digits after the decimal point) and 75 (the precision is 10th of a percent, three digits to the right of the decimal point). When we multiply, our result will have precision of 5 digits to the right of the decimal point. The result (1019925) represents $10.19925. We need to both round and shift this back to have a precision of 2 digits to the right of the decimal point.

We can both round and scale with an expression like the following. The /1000 resets the scale from 5 digits of precision to 2 digits of precision. This is because 10,000/100 is 1,000, our adjustment to the scale factor.

round(13599L*75,-3)/1000

Division. When we divide two numbers, the result's precision is the difference between the numerator's and denominator's precision. If we divide two amounts in pennies (2 digits of precision), the result has zero digits of precision. Indeed, the result is actually a ratio between penny amounts, and isn't in pennies. We have to be careful when doing this kind of math to determine the rounding rules, and correctly scale the answer.

Generally, if we want 2 digits of precision in our result, we need to be sure the numerator's precision is at least 2 digits more than the denominator's precision. This means scaling the numerator first, then doing the division. If the numerator has too much precision to begin with, we'll have to round and then scale the result after division.

Say we have a bill of $45,276 for 416.15 hours of labor. What is the exact dollars per hour to the penny? Our hours have a precision of two digits, 41615, with a precision factor of 100. We need our dollars to start with five digits of precision because we start with two digits, we'll lose two when dividing by hours, and we want one more digit so we can round properly. We'll represent the dollars as 4527600000 with a precision factor of 100000. The division gives us 108797, with a precision factor of 1000. This can be rounded correctly and divided by 10 to get the value to the penny, properly rounded, of 10880, which means $108.80.

round(45276L*100000/41615,-1)/10

The Bigger Picture. Whew! It looks like the special cases of adding (and subtracting), multiplying and dividing are really complex. Actually, they aren't too bad, they're just new to you.

There's a trick to this, and the trick is to begin with the goal in mind and work forward to what data we need to satisfy our goal. For adding and subtracting, our goal precision can't be different from our input precision. When multiplying and dividing, we work backwards: we write down our goal precision, we write down the precision from our calculation, and we work out rounding and scaling operations to get from our calculation to our goal.

It turns out that this trick is essential to programming. We'll return to it time and again.

Programming Essentials

Input-Process-Output

We often define programs using the pattern “input-process-output”. We'll work through this sequence backwards. In order to see output from a script, we'll need to use the print statement. We'll look at this in Seeing Results.

Once we are comfortable with the print statement, we can introduce scripted execution in Turning Python Loose With a Script. When we start making more finished and polished programs, we're going to want to make them easy to use. There are a lot of options and shortcuts available to us, and we'll touch on a few of them here. Later, we'll add even more ease-of-use features.

We In order to do processing, we'll introduce variables and the assignment statement in Generalizing a Calculation. This will allow us to do the basic steps of processing. We'll describe some additional features in Assignment Bonus Features

When we add input in Can We Get Your Input?, we'll have all three parts to the input-process-output pattern.

Chapter 13. Seeing Results

The print Statement

We write programs so they can produce useful results. We'll start with statements that immediately satisfy our goal: seeing the results. We'll cover the basic print statement in The print Statement. We'll add some useful features in Dressing Up Our Output.

Yes, this chapter is really short; the print statement is delightfully simple.

The print Statement

The print statement takes a list of values and, well, prints them. It converts numbers and other objects to strings and puts the characters out on a file called standard output. Generally, this standard output file is directed to the Python Shell window in IDLE. If you run Python directly, it is directed to the Terminal (or Command Prompt) window where Python was started.

While outside the scope of this book, it is important to note that each shell has ways to redirect the standard output file. Python has considerable flexibility, and so does the shell that runs Python. Too many choices is either confusing or empowering. We'll limit ourselves to looking at the choices Python gives. You can, however, look at your GNU/Linux shell documentation or Windows Command Prompt documentation to see what additional choices you have.

When we are interacting with Python and we give Python an expression, the result is printed automatically. This is the way Python responds when interacting with a person. When we run script, however, we won't be typing each individual statement, and Python won't automatically print the result of each expression. Instead, we have to tell Python to show us results by writing an explicit print statement that shows the response we want.

The basic print statement looks like this:

printexpression,...〉

Statement Syntax Rules

We'll show optional clauses in statements by surrounding them with 〈 and 〉's. We don't actually enter the 〈〉's, they surround optional clauses to show us what alternative forms of the statement are.

We use a trailing ellipsis (…) to indicate something that can be repeated. There's no real upper limit on the number of times something can be repeated.

Also notice that we put a , after the expression. This is your hint that expressions are separated with ,'s if you have more than one.

In the case of print, the syntax summary shows us there are many different ways to use this statement:

  • We can say print with no clauses.
  • We can say print expression with one expression.
  • We can say print expression , expression with two expressions, separated by ,'s.
  • And so on, for any number of expressions, separated by ,'s.

Here are some examples of a basic print statement.

print 22/7, 22./7.
print 335/113, 335./113.
print ((65 - 32) * (5 / 9))

Dressing Up Our Output

We can make our printed output easier to read by including quoted strings. See the section called “Strings — Anything Not A Number” to review how we write strings.

For example, the following trivial program prints a string and a number. Since our string had an apostrophe in it, we elected to surround the string with quotes (").

print "Isn't Python cool?", 6*7

Here's another example.

import math
print 'Value of "pi"', 6.0/5.0*( (math.sqrt(5)+1) / 2 )**2

The print list can end with a comma, to allow piecing together a long line of output from multiple statements. The following program will produce one line of output from two print statements. If we have very complex expressions, this can make our program easier to read by breaking into understandable chunks.

print "335/113=",
print 335.0/113.0

Debugging Print

One obvious mistake you will make is misspelling print. You'll see NameError: name 'primpt' is not defined as the error message. I've spelled it “primpt” so often, I've been tempted to rewrite the Python language to add this as an alternative.

The other common mistake that is less obvious is omitting a comma between the values you are printing. When you do this, you'll see a SyntaxError: invalid syntax message.

If the result of a print statement doesn't look right, remember that you can always enter the various expressions directly into IDLE's Python shell to examine the processing one step at a time.

Print Exercises

  1. Print Expression Results. In the Simple Expressions exercises in Chapter 6, Instant Gratification, we entered some simple expressions into the Python interpreter. Change these expressions into nice-looking print statements.

    Be sure to print a label or identifier with each answer. Here's a sample.

    print "9-1's * 9-1's = ", 111111111*111111111
    

Print FAQ

1. How can I get more control over the output?
2. How can I direct output to stderr?
3. How do I produce binary output? MP3's, MOV's, JPEG's, etc.
1.

How can I get more control over the output?

The print statement offers relatively little control over the printed output. It always puts a space between items, which may not always be desirable.

The string formatting operator provides complete control over the formatting of data. We'll cover this in depth in Chapter 29, Sequences of Characters: Strings. First, we want to introduce a number of programming statements. Once we've got more of the language under our belt, we'll tackle the “fit and finish” issues of nicely formatted output.

2.

How can I direct output to stderr?

We'll talk about this in detail in Chapter 38, Files — The Permanent Record. However, if you can't wait until then, we'll provide some hints as to what will come in the future.

import sys
print >>sys.stderr, "an error"
3.

How do I produce binary output? MP3's, MOV's, JPEG's, etc.

We'll talk about this in detail in Chapter 38, Files — The Permanent Record. There's no quick-and-dirty shortcut for that kind of operation; it requires interacting with the file system. Also, these more sophisticated data formats require more sophisticated programming.

Chapter 14. Turning Python Loose With a Script

Scripting Round One: IDLE

One of our goals is to have the Python interpreter execute our scripts. Program scripts can vary from a few simple expressions to complex sequences of Python commands. There are two parts to this: creating the script and then running the script. We'll cover the basics of creating the script in Making A Script File. We show a simple technique for running a script in IDLE in Running Scripts in IDLE.

In the long run, however, we'll want to use more direct methods to run our scripts. After all, we don't want to have to start IDLE every time we want to run our program. After we get some more experience with programming, we'll look at making our programs a perfectly seamless part of our work environment.

We'll provide some answers to common questions in Scripting FAQ.

Making A Script File

The first step in Python programming is to create the program script. For the following examples, we'll create a simple, two-line script, called example1.py.

Example 14.1. example1.py

print 65, "F"
print ( 65 - 32 ) * 5 / 9, "C"

Within IDLE, you create a file by using the File menu, the New Window item. This will create a new window into which you can enter your two-line Python program. Check your spelling and spacing carefully.

When you use the File menu, Save item, be sure to read where the file is going to be saved. You'll notice that IDLE may be starting in C:\Python24, your Macintosh HD, or /home/slott or some other unexpected directory.

For now, be sure to save this file in your home directory. This could be C:\Documents and Settings\SLott, or /home/slott.

You can't easily use a word processor for this, since word processors include a lot of formatting markup that Python can't read. If you want to try and use an office product to create this kind of file, you have to be absolutely sure that you save the file as pure text.

There are several ways we can run the Python interpreter and have it evaluate our script file. Since IDLE is virtually identical on all platforms, we'll cover this next.

Writing and Saving A Script

One of the biggest benefits of using IDLE is that your Python script has various syntax elements highlighted. In mine, the keywords show up in orange, strings in green, and my expressions are black. If I misspell print, it doesn't show up in orange, but shows up in black.

Another common problem we see is people saving their file to unexpected locations on their disk. It's important to save the file to a directory where you can find it again.

One interesting confusion we've seen arises when people forgetting to save the file. IDLE will ask you if you want to save the file when you attempt to run it. Sometimes this message is unexpected and that can be confusing. Our advice is to save early and save often.

Alternatives to IDLEIf you don't want to use IDLE to create text files, you do have several choices for nice program editors. These will require you down download and install additional software.

  • Windows. You have the built-in notepad, or you can purchase any of a large number of programmer's text editors, including TextPad. There are free editors like jEdit, also.

  • MacOS. You have the built-in textedit application. Be sure to use the Format menu, Make Plain Text menu item to strip the file down to just text. Or you can purchase any of a large number of programmer's text editors, including BBEdit. There are free editors like jEdit, also.

  • GNU/Linux. If you are using GNOME, you have gedit. If you want, you can also use vim or emacs, two very fine sophisticated editors that have been used for decades to write software.

After you create your file outside IDLE, you can open the file with IDLE in order to run it. You use the File menu, Open... item to open a file you created outside IDLE. It's important to take note of where you save files so that you can find them and open them again.

Running Scripts in IDLE

The window for your script file will have a Run menu. The ordinary Python Shell window doesn't have this menu. On the Run menu, you'll find the Run Module menu item, which will execute your script file. This will showing the results in the Python Shell window.

Why is it called “run module”? Most Python files are called “modules”, which are files of definitions. For now, we'll call them scripts, because that is a much more descriptive name.

If you have trouble finding the Run menu, be sure you are looking at the correct window. The initial window in IDLE is the Python Shell. It has the Shell menu and shows the >>> prompt. When you create a new window to edit a script (or you open a script file), this widow will have the Run menu. When you open a script or save a script, the window name reflects the name of the script file.

When we select Run Module menu item from the Run menu, we see the following in the Python Shell window.

>>> ================================ RESTART ================================
>>> 
65 F
18 C
>>> 

This shows us that the Python shell was restarted using our script as input. It also shows us the output from our two print statements. We ran our first program.

Debugging Aids in IDLE

If you have syntax errors, you'll see a pop-up dialog box named Syntax error with a message like “There's an error in your program: invalid syntax”. You'll also notice that some part of your script will be highlighted in red. This is near the error.

Since IDLE highlights various syntax elements, you can use the color as a hint. In mine, the keywords show up in orange, strings in green, and my expressions are black. If I misspell print, it doesn't show up in orange, but shows up in black.

If you have semantic errors, you'll see these in the shell window in red. For example, I got the following by messing up my program.

Traceback (most recent call last):
  File "E:/Personal/NonProgrammerBook/notes/sample1.py", line 1, in -toplevel-
    print 65, "F"/2
TypeError: unsupported operand type(s) for /: 'str' and 'int'

You can see my erroneous print statement: it has "F"/2. And you can also see Python's complaint. While the syntax is acceptable, it doesn't mean anything to divide the letter "F" by 2.

We can fix our script file, save it, and re-run it. You'll notice that the Run Module menu item has a short-cut key, usually F5. This edit-save-run cycle is how software gets built.

Script Exercises

  1. Simple Script. Create a Python file with the following three commands, each one on a separate line: copyright, license, credits.

  2. Print Script. Create and run Python file with commands like the following examples: print 12345 + 23456; print 98765 - 12345; print 128 * 256; print 22 / 7.

  3. Another Simple Print Script. Create and run a Python file with commands like the following examples: print "one red", 18.0/38.0; print "two reds in a row",(18.0/38.0)**2.

  4. Numeric Types. Compare the results of 22/7 and 22.0/7. Explain the differences in the output.

Scripting FAQ

1. What are the various ways to use Python?
2. Why are there so many ways to use Python?
3. Do I have to write a script?
1.

What are the various ways to use Python?

Python can be used a variety of ways, depending what problem you are solving.

  • Interactively. We can interact directly with Python at the “command-line”. This was what we saw in Chapter 6, Instant Gratification. A tool like IDLE makes it easier to enter Python statements and execute them. We looked at this in Chapter 7, IDLE Time.

  • Scripted. Tis makes the processing completely automatic. We'll look at this in Chapter 23, Turning Python Loose with More Sophisticated Scripts In the long run, this automation is our goal. However, to learn the language, we find the direct interaction is very helpful. Manual interaction via IDLE is our “training wheels” for learning the language.

  • Through The Web. While beyond the scope of this book, Python can be part of the Internet, with your application running on a web server.

2.

Why are there so many ways to use Python?

Or, why can't we just use IDLE? The huge number of choices is a natural consequence of creating a simple, flexible program. Many people use Python through IDLE and are happy and successful in what they do.

More sophisticated problems, however, often require more complex use of Python. Since the Python program (python, or python.exe) can be used a variety of ways, we can use Python to build a number of different kinds of solutions to our data processing problems.

In a book like this, we hate to present Python from a single point of view. We prefer to present a number of choices so that different readers can locate one that looks like it will solve their problem.

3.

Do I have to write a script?

You don't have to write scripts, you can do everything through interaction with IDLE. Scripting is not required, but it is generally the goal of programming. An automated solution should be something that can be double-clicked, or something that is invoked by a web server.

Chapter 15. Generalizing a Calculation

Formulas and Variables