Copyright © 2002, 2005, 2007, 2008, 2009 Steven F. Lott
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.
5/29/2009
Table of Contents
List of Figures
List of Tables
List of Examples
List of Equations
Table of Contents
The Zen Of Python.
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
You need this book because you need to learn Python. There are lots of reasons why you need to learn Python. Here are a few.
You need a programming language which is easy to read and has a vast library of modules focused on solving the problems you're faced with.
You saw an article about Python specifically, or dynamic languages in general, and want to learn more.
You're starting a project where Python will be used or is in use.
A colleague has suggested that you look into Python.
You've run across a Python code sample on the web and need to learn more.
Python reflects a number of growing trends in software development, putting it at or near the leading edge of good programming languages. It is a very simple language surrounded by a vast library of add-on modules. It is an open source project, supported by many individuals. It is an object-oriented language, binding data and processing into class definitions. It is a platform-independent, scripted language, with complete access to operating system API's. It supports integration of complex solutions from pre-built components. It is a dynamic language, which avoids many of the complexities and overheads of compiled languages.
This book is a complete presentation of the Python language. It is oriented toward learning, which involves accumulating many 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 within this limit, we've found that it helps to present a language as ever-expanding layers. We'll lead you from a very tiny, easy to understand subset of statements to the entire Python language and all of the built-in data structures. We've also found that doing a number of exercises helps internalize each language concept.
Three Faces of a Language. There are three facets to a programming language: how you write it, what it means, and the additional practical considerations that make a program useful. While many books cover the syntax and semantics of Python, in this book we'll also cover the pragmatic considerations. Our core objective is to build enough language skills that good object-oriented design will be an easy next step.
The syntax of a language is often covered in the language reference manuals. In the case of relatively simple languages, like Python, the syntax is simple, and is covered in the Python Language tutorial that is part of the basic installation kit. We'll provide additional examples of language syntax. For people new to programming, we'll provide additional tips focused on the newbie.
The semantics of the language can be a bit more slippery than the syntax. Some languages involve obscure or unique concepts that make it difficult to see what a statement really means. In the case of languages like Python, which have extensive additional libraries, the burden is doubled. First, one has to learn the language, then one has to learn the libraries. The number of open source packages made available by the Python community can increase the effort required to understand an entire architecture. The reward, however, is high-quality software based on high-quality components, with a minimum of development and integration effort.
Many languages offer a number of tools that can accomplish the same basic task. Python is no exception. It is often difficult to know which of many alternatives performs better or is easier to adapt. We'll try to focus on showing the most helpful approach, emphasizing techniques that apply for larger development efforts. We'll try to avoid quick and dirty solutions that are only appropriate when learning the language.
Professional programmers who need to learn Python are our primary audience. We provide specific help for you in a number of ways.
Instructors are a secondary audience. If you are looking for classroom projects that are engaging, comprehensible, and focus on perfecting language skills, this book can help. Each chapter in this book contains exercises that help students master the concepts presented in the chapter.
This book assumes an basic level of skill with any of the commonly-available computer systems. The following skills will be required.
When you've finished with this book you should be able to do the following.
This book falls into five distinct parts. To manage the clue absorption rate, the first three parts are organized in a way that builds up the language in layers from central concepts to more advanced features. Each layer introduces a few new concepts, and is presented in some depth. Programming exercises are provided to encourage further exploration of each layer. The last two parts cover the extension modules and provide specifications for some complex exercises that will help solidify programming skills.
Some of the chapters include digressions on more advanced topics. These can be skipped, as they cover topics related to programming in general, or notes about the implementation of the Python language. These are reference material to help advanced students build skills above and beyond the basic language.
Part I, “Language Basics” introduces the basic feartures of the Python language, covering most of the statements but sticking with basic numeric data types. Chapter 1, Background and History provides some history and background on Python. Chapter 3, Getting Started covers installation of Python, using the interpreter interactively and creating simple program files. Chapter 4, Simple Numeric Expressions and Output covers the basic expressions and core numeric types. Chapter 6, Variables, Assignment and Input introduces variables, assignment and some simple input constructs. Chapter 7, Truth, Comparison and Conditional Processing adds truth, conditions and loops to the language. Chapter 9, Functions introduces the basic function definition and function call constructs; Chapter 10, Additional Notes On Functions introduces the call by name and call by value features of Python, as well as advanced function call features.
Part II, “Data Structures” adds a number of data structures to enhance the expressive power of the language. In this part we will use a number of different kinds of objects, prior to designing our own objects. Chapter 11, Sequences: Strings, Tuples and Lists extends the data types to include various kinds of sequences. These include Chapter 12, Strings, Chapter 13, Tuples and Chapter 14, Lists. Chapter 15, Mappings and Dictionaries describes mappings and dictionaries. Chapter 17, Exceptions covers exception objects, and exception creation and handling. Chapter 19, Files covers files and several closely related operating system (OS) services. Chapter 20, Advanced Sequences describes more advanced sequence techniques, including multi-dimensional matrix processing. This part attempts to describe a reasonably complete set of built-in data types.
Part III, “Data + Processing = Objects” describes the object-oriented programming features of Python. Chapter 21, Classes introduces basics of class definitions and introduces simple inheritance. Chapter 22, Advanced Class Definition adds some features to basic class definitions. Chapter 23, Some Design Patterns extend this discussion further to include several common design patterns that use polymorphism. Chapter 24, Creating or Extending Data Types describes the mechanism for adding types to Python that behave like the built-in types.
Part IV, “Components, Modules and Packages” 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 28, Modules provides basic semantics
and syntax for creating modules. We cover the organization of packages
of modules in Chapter 29, Packages. An overview of the
Python library is the subject of Chapter 30, The Python Library. Chapter 31, Complex Strings: the re Module
covers string pattern matching and processing with the
re module. Chapter 32, Dates and Times: the time and
datetime Modules covers the
time and datetime module.
Chapter 35, Programs: Standing Alone covers the creation of main
programs. We touch just the tip of the client-server iceberg in Chapter 36, Programs: Clients, Servers, the Internet and the World Wide
Web.
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” and the string module
is covered in Chapter 12, Strings. Chapter 19, Files touches on fileinput,
os, os.path,
glob, and fnmatch.
Part V, “Projects” presents several larger and more complex programming problems. These are ranked from relatively simple to quite complex. Chapter 37, Areas of the Flag covers computing the area of the symbols on the American flag. Chapter 38, The Date of Easter has several algorithms for finding the date for Easter in a given year. Chapter 39, Musical Pitches has several algorithms for the exact frequencies of musical pitches. Chapter 40, Bowling Scores covers scoring in a game of bowling. Chapter 41, Mah Jongg Hands describes algorithms for evaluating hands in the game of Maj Jongg. Chapter 42, Chess Game Notation deals with interpreting the log from a game of chess.
This book can't cover everything Python. There are a number of things which we will not cover in depth, and some things which we can't even touch on lightly. This list will provide you directions for further study.
The rest of the Python library. The library is a large, sophisticated, rapidly-evolving collection of software components. We selected a few modules that are widely-used. There are many books which cover the library in general, and books which cover specific modules in depth.
The subject of Object-Oriented (OO) design is the logical next stepd in learning Python. That topic is covered in Building Skills in Object-Oriented Design [Lott05].
Database design and programming requires a knowledge of Python and a grip on OO design. It requires a digression into the relational model and the SQL language.
Graphical User Interface (GUI) development
requires a knowledge of Python, OO design and
database design. There are two commonly-used toolkits:
Tkinter and pyGTK.
We'll cover pyGTK in a future volume on
graphics programming and GUI design with
GTK.
Web application development, likewise, requires a knowledge of Python, OO design and database design. This topic requires digressions into internetworking protocols, specifically HTTP and SOAP, plus HTML, XML and CSS languages. There are numerous web development frameworks for Python.
We have to adopt a style for presenting Python. We won't present a complete set of coding standards, instead we'll present examples. This section has some justification of the style we use for the examples in this book.
Just to continune this rant, we find that actual examples speak louder than any of the gratuitously detailed coding standards which are so popular in IT shops. We find that many IT organizations waste considerable time trying to write descriptions of a preferred style. A good example, however, trumps any description. As consultants, we are often asked to provide standards to an inexperienced team of programmers. The programmers only look at the examples (often cutting and pasting them). Why spend money on empty verbiage that is peripheral to the useful example?
One important note: we specifically reject using complex prefixes
for variable names. Prefixes are little more than visual
clutter. In many places, for example, an integer parameter with
the amount of a bet might be called pi_amount where
the prefix indicates the scope (p for a parameter)
and type (i for an integer). We reject the
pi_ as useless and uninformative.
This style of name is only appropriate for primitive types, and
doesn't address complex data structures well at all. How does one name a
parameter that is a list of dictionaries of class instances?
pldc_?
In some cases, prefixes are used to denote the scope of an
instance variables. Variable names might include a cryptic one-letter
prefix like “f” to denote an instance variable; sometimes
programmers will use “my” or “the” as an
English-like prefix. We prefer to reduce clutter. In Python, instance
variables are always qualified by self., making the
scope crystal clear.
All of the code samples were tested on Python 2.5 for MacOS, using an iMac running MacOS 10.5. Additional testing of all code was done with Windows 2000 on a Dell Latitude laptop, as well as a Dell Precision running Fedora Core.
Here is a typical Code sample.
Example 1. Typical Python Example
combo = { }
for i in range(1,7):
for j in range(1,7):
roll= i+j
combo.setdefault( roll, 0 )
combo[roll] += 1
for n in range(2,13):
print "%d %.2f%%" % ( n, combo[n]/36.0 )
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.
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.
I'd like to thank Carl Frederick for asking me if I was using Python to develop complex applications. At the time, I said I'd have to look into it. This is the result of that investigation.
I am indebted to Thomas Pautler, Jim Bullock, Michaël Van Dorpe, Matthew Curry, Igor Sakovich, Drew, John Larsen and Robert Lucente for supplying much-needed corrections to errors in previous editions.
A programming language involves two closely interleaved topics. On one hand, there are the statement constructs that process information inside the computer, with visible effects on the various external devices. On the other hand are the various types of data and relationship structures for organizing the information manipluated by the program.
This part describes the most commonly-used Python statements, sticking with basic numeric data types. Part II, “Data Structures” will present a reasonably complete set of built-in data types and features for Python. While the two are tightly interwoven, we pick the statements as more fundamental because we we can (and will) add new data types. Indeed, the essential thrust of object-oriented programming (covered in Part III, “Data + Processing = Objects”) is the creation of new data types.
Some of the examples in this part refer to the rules of various common casino games. Knowledge of casino gambling is not essential to understanding the language or this part of the book. We don't endorse casino gambling. Indeed, many of the exercises reveal the magnitude of the house edge in most casino games. However, casino games have just the right level of algorithmic complexity to make for excellent programming exercises.
In Chapter 3, Getting Started we'll describe the basics of computer programming, installing a Python interpreter, using Python interactively, and writing simple scripts. In Chapter 4, Simple Numeric Expressions and Output we'll introduce the print statement, and arithmetic expressions including the numeric data types, operators, conversions, and some built-in functions. We'll expand on this in Chapter 5, Advanced Expressions. We'll introduce variables, the assignment statement, and input in Chapter 6, Variables, Assignment and Input, allowing us to create simple input-process-output programs. When we add truth, comparisons, conditional processing, iterative processing and assertions in Chapter 7, Truth, Comparison and Conditional Processing, we'll have all the tools necessary for programming. In Chapter 9, Functions and Chapter 10, Additional Notes On Functions, we'll show how to define and use functions, the first of many tools for organizing programs to make them understandable.
Table of Contents
This chapter describes the history of Python in the section called “History”. After that, the section called “Comparisons” is a subjective comparison between Python and a few other other languages, using some quality criteria harvested from two sources: the Java Language Environment White Paper and “On the Design of Programming Languages”. This material can be skipped by newbies: it doesn't help explain Python, it puts it into a context among other programming languages.
Python is a relatively simple programming language that includes a rich set of supporting libraries. This approach keeps the language simple and reliable, while providing specialized feature sets as separate extensions.
Python has an easy-to-use syntax, focused on the programmer who must type in the program, read what was typed, and provide formal documentation for the program. Many languages have syntax focused on developing a simple, fast compiler; but those languages may sacrifice readability and writability. Python strikes a good balance between fast compilation, readability and writability.
Python is implemented in C, and relies on the extensive, well understood, portable C libraries. It fits seamlessly with Unix, Linux and POSIX environments. Since these standard C libraries are widely available for the various MS-Windows variants, and other non-POSIX operating systems, Python runs similarly in all environments.
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 www.cwi.nl/~steven/abc/. For information on Modula-3, see Modula-3 [Harbison92], as well as www.research.compaq.com/SRC/modula-3/html/home.html.
The current Python development is centralized in Python.org. See www.python.org for the latest developments.
Python reflects a number of growing trends in software development. It is a very simple language surrounded by a vast library of add-on modules. It is an open source project, supported by dozens of individuals. It is an object-oriented language. It is a platform-independent, scripted language, with complete access to operating system API's. It supports integration of complex solutions from pre-built components. It is a dynamic language, allowing more run-time flexibility than statically compiled languages.
Additionally, Python is a scripting language with full access to Operating System (OS) services. Consequently, Python can create high level solutions built up from other complete programs. This allows someone to integrate applications seamlessly, creating high-powered, highly-focused meta-applications. This kind of very-high-level programming (programming in the large) is often attempted with shell scripting tools. However, the programming power in most shell script languages is severely limited. Python is a complete programming language in its own right, allowing a powerful mixture of existing application programs and unique processing to be combined.
Python includes the basic text manipulation facilities of Awk or Perl. It extends these with extensive OS services and other useful packages. It also includes some additional data types and an easier-to-read syntax than either of these languages.
Python has several layers of program organization. The Python package is the broadest organizational unit; it is collection of modules. The Python module, analogous to the Java package, is the next level of grouping. A module may have one or more classes and free functions. A class has a number of static (class-level) variables, instance variables and methods. We'll lookl at these layers in detail in appropriate sections.
Some languages (like COBOL) have features that are folded into the language itself, leading to a complicated mixture of core features, optional extensions, operating-system features and special-purpose data structures or algorithms. These poorly designed languages may have problems with portability. This complexity makes these languages hard to learn. One hint that a language has too many features is that a language subset is available. Python suffers from none of these defects: the language has only 21 statements (of which five are declaratory in nature), the compiler is simple and portable. This makes the the language is easy to learn, with no need to create a simplified language subset.
We'll measure Python with two yardsticks. First, we'll look at a yardstick originally used for Java. Then we'll look at yardstick based on experience designing Modula-2.
The Java Language Environment White Paper [Gosling96] lists a number of desirable features of a programming language:
Python meets and exceeds most of these expectations. We'll look closely at each of these twelve desireable attributes.
Simple and Familiar. By simple, we mean that there is no GOTO statement, we don't need to explicitly manage memory and pointers, there is no confusing preprocessor, we don't have the aliasing problems associated wuth unions. We note that this list summarizes the most confusing and bug-inducing features of the C programming language.
Python is simple. It relies on a few core data structures and statements. The rich set of features is introduced by explicit import of extension modules. Python lacks the problem-plagued GOTO statement, and includes the more reliable break, continue and exception raise statements. Python conceals the mechanics of object references from the programmer, making it impossible to corrupt a pointer. There is no language preprocessor to obscure the syntax of the language. There is no C-style union (or COBOL-style REDEFINES) to create problematic aliases for data in memory.
Python uses an English-like syntax, making it reasonably familiar to people who read and write English or related languages. There are few syntax rules, and ordinary, obvious indentation is used to make the structure of the software very clear.
Object-Oriented. Python is object oriented. Almost all language features are
first class objects, and can be used in a variety of contexts. This is
distinct from Java and C++ which create confusion by having objects as
well as primitive data types that are not objects. The built-in
type(x) function
can interrogate the types of all objects. The language permits
creation of new object classes. It supports single and multiple
inheritance. Polymorphism is supported via run-time interpretation,
leading to some additional implementation freedoms not permitted in
Java or C++.
Secure. The Python language environment is reasonably secure from
tampering. Pre-compiled python modules can be distributed to prevent
altering the source code. Additional security checks can be added by
supplementing the built-in __import__
function.
Many security flaws are problems with operating systems or framework software (for example, database servers or web servers). There is, however, one prominent language-related security problem: the "buffer overflow" problem, where an input buffer, of finite size, is overwritten by input data which is larger than the available buffer. Python doesn't suffer from this problem.
Python is a dynamic language, and abuse of features like the
exec statement or the eval
function can introduce security problems. These mechanisms are easy to
identify and audit in a large program.
Interpreted. An interpreted language, like Python allows for rapid, flexible, exploratory software development. Compiled languages require a sometimes lengthy edit-compile-link-execute cycle. Interpreted languages permit a simpler edit-execute cycle. Interpreted languages can support a complete debugging and diagnostic environment. The Python interpreter can be run interactively; which can help with program development and testing.
The Python interpreter can be extended with additional high-performance modules. Also, the Python interpreter can be embedded into another application to provide a handy scripting extension to that application.
Dynamic. Python executes dynamically. Python modules can be distributed as source; they are compiled (if necessary) at import time. Object messages are interpreted, and problems are reported at run time, allowing for flexible development of applications.
In C++, any change to centrally used class headers will lead to lengthy recompilation of dependent modules. In Java, a change to the public interface of a class can invalidate a number of other modules, leading to recompilation in the best case, or runtime errors in the worst case.
Portable. Since Python rests squarely on a portable C source, Python
programs behave the same on a variety of platforms. Subtle issues like
memory management are completely hidden. Operating system
inconsistency makes it impossible to provide perfect portability of
every feature. Portable GUI's are built using the widely-ported Tk GUI
tools Tkinter, or the GTK+ tools and the the
pyGTK bindings.
Robust. Programmers do not directly manipulate memory or pointers, making the language run-time environment very robust. Errors are raised as exceptions, allowing programs to catch and handle a variety of conditions. All Python language mistakes lead to simple, easy-to-interpret error messages from exceptions.
Multithreaded. The Python threading module is a
Posix-compliant threading library. This is not completely supported on
all platforms, but does provide the necessary interfaces. Beyond
thread management, OS process management is also available, as are
execution of shell scripts and other programs from within a Python
program.
Additionally, many of the web frameworks include thread management. In products like TurboGears, individual web requests implicitly spawn new threads.
Garbage Collection. Memory-management can be done with explicit deletes or automated garbage collection. Since Python uses garbage collection, the programmer doesn't have to worry about memory leaks (failure to delete) or dangling references (deleting too early).
The Python run-time environment handles garbage collection of all Python objects. Reference counters are used to assure that no live objects are removed. When objects go out of scope, they are eligible for garbage collection.
Exceptions. Python has exceptions, and a sophisticated try statement that handles exceptions. Unlike the standard C library where status codes are returned from some functions, invalid pointers returned from others and a global error number variable used for determining error conditions, Python signals almost all errors with an exception. Even common, generic OS services are wrapped so that exceptions are raised in a uniform way.
High Performance. The Python interpreter is quite fast. However, where necessary, a class or module that is a bottleneck can be rewritten in C or C++, creating an extension to the runtime environment that improves performance.
One of the languages which strongly influenced the design of Python was Modula-2. In 1974, N. Wirth (creator of Pascal and its successor, Modula-2) wrote an article “On the Design of Programming Languages” [Wirth74], which defined some timeless considerations in designing a programming language. He suggests the following:
a language be easy to learn and easy to use;
safe from misinterpretation;
extensible without changing existing features;
machine [platform] independent;
the compiler [interpreter] must be fast and compact;
there must be ready access to system services, libraries and extensions written in other languages;
the whole package must be portable.
Python syntax is designed for readability; the language is quite simple, making it easy to learn and use. The Python community is always alert to ways to simplify Python. The Python 3.0 project is actively working to remove a few poorly-concieved features of Python. This will mean that Python 3.0 will be simpler and easier to use, but incompatible with Python 2.x in a few areas.
Most Python features are brought in via modules, assuring that extensions do not change or break existing features. This allows tremendous flexibility and permits rapid growth in the language libraries.
The Python interpreter is very small. Typically, it is smaller than the Java Virtual Machine. Since Python is (ultimately) written in C, it has the same kind of broad access to external libraries and extensions. Also, this makes Python completely portable.
Table of Contents
This chapter is becoming less and less relevant as Python comes pre-installed with most Linux-based operating systems. Consequently, the most interesting part of this chapter is the Windows Installation, where we describe downloading and installing Python on Windows.
Python runs on a wide, wide variety of platforms. If your particular operating system isn't described here, refer to www.python.org/community for more information.
Mac OS developers will find it simplest to upgrade to Leopard (Max OS 10.5), since it has Python 2.5.1 included. This installation includes the complete suite of tools, but doesn't include a clever Applications icon for launching IDLE. You can make this icon yourself using Applescript. If installiung Leopard is undesirable, for some reason, you'll need to do an install or upgrade of Python in your existing Mac OS. We'll cover this in Macintosh Installation.
For other GNU/Linux developers, you'll find that Python is generally included in most distributions. In the unlikely event that you have an old distribution and can't upgrade, we'll present some alternatives that should cover the most common situations.
Start with GNU/Linux and UNIX Overview. This section has a quick procedure for examining your current configuration to see if you have Python in the first place. If you have Python, and it's version 2.5, you're all done. Otherwise, you'll have to determine what tools you have for doing an installation or upgrade.
If you have Yellowdog Updater Modified (YUM) see YUM Installation.
If you have one of the GNU/Linux variants that uses the Red Hat Package Manager (RPM), see RPM Installation.
The alternative to use the source installation procedure in "Build from Scratch" Installation.
The goal of installation is to get the Python interpreter and
associated libraries. Windows users will get a program called
python.exe. Linux and MacOS users will get the
Python interpreter, a program named python.
In addition to the libraries and the interpreter, your Python installation comes with a tutorial document on Python that will step you through a number of quick examples. For newbies, this provides an additional point of view that you may find helpful. You may also want to refer to the official Beginner's Guide Wiki.
In some circumstances, your Windows environment may require administrator privilege. The details are beyond the scope of this book. If you can install software on your PC, then you have administrator privileges. In a corporate or academic environment, someone else may be the administrator for your PC.
The Windows installation of Python has three broad steps.
We'll go through each of these in detail.
Backup. Before installing software, back up your computer. I strongly recommend that you get a tool like Norton's Ghost™. This product will create a CD that you can use to reconstruct the operating system on your PC in case something goes wrong. It is difficult to undo an installation in Windows, and get your computer back the way it was before you started.
I've never had a single problem installing Python. I've worked with a number of people, however, who either have bad luck or don't read carefully and have managed to corrupt their Windows installation by downloading and installing software. While Python is safe, stable, reliable, virus-free, and well-respected, you may be someone with bad luck who has a problem. Often the problem already existed on your PC and installing Python was the straw that broke the camel's back. A backup is cheap insurance.
You should also have a folder for saving your downloads. You can
create a folder in My Documents called
downloads. I suggest that you keep all of your
various downloaded tools and utilities in this folder for two reasons. If
you need to reinstall your software, you know exactly what you downloaded.
When you get a new computer (or an additional computer), you know what
needs to be installed on that computer.
Download. After making a backup, go to the www.python.org web site and look for
the Download area. In here, you're looking for the pre-built Windows
installer. This book will emphasize Python 2.5. In that case, the kit is
python-2.5.. When
you click on the filename, your browser should start downloading the
file. Save it in your x.msidownloads folder.
Backup. Now is a good time to make a second backup. Seriously. This backup will have your untouched Windows system, plus the Python installation kit. It is still cheap insurance.
If you have anti-virus software [you do, don't you?] you may need to disable this until you are done installing Python.
At this point, you have everything you need to install Python:
You'll need two things to install Python. If you don't have both, see the previous section on pre-installation.
Double-click the Python installer
(python-2.5.).x.msi
The first step is to select a destination directory. The default
destination should be C:\Python25. Note that Python
does not expect to live in the C:\My Programs folder.
Because the My Programs folder has a space in the
middle of the name — something that is atypical for all operating systems
other than Windows — subtle problems can arise. Consequently, Python folks
prefer to put Python into C:\Python25 on Windows
machines. Click to continue.
The next step is to confirm that you want to backup replaced files.
The option to make backups is already selected and the folder is usually
C:\Python25\BACKUP. This is the way it should be.
Click to continue.
The next step is the list of components to install. You have a list of five components.
There is an button that is necessary if you are using a company-supplied computer for which you are not the administrator. If you are not the administrator, and you have permission to install additional software, you can click on this button to get the Advanced Options panel. There's a button labeled that you'll need to click in order to install Python on a PC where you don't have administrator privileges.
Click to continue.
You can pick a Start Menu Group for the Python program, IDLE and the
help files. Usually, it is placed in a menu named Python
2.5. I can't see any reason for changing this, since it only
seems to make things harder to find. Click to
continue.
The installer puts files in the selected places. This takes less than a minute.
Click ; you have just installed Python on your computer.
The only problem you are likely to encounter doing a Windows installation is a lack of administrative privileges on your computer. In this case, you will need help from your support department to either do the installation for you, or give you administrative privileges.
In your menu, under , you will now have a group that lists five things:
GUI is the Graphic User Interface. We'll turn to IDLE in the section called “The IDLE Development Environment”.
If you select the
menu item, you'll see the Python (command line) window.
This will contain something like the following.
Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>>
If you hit Ctrl-Z and then Enter, Python will exit. The basic Python program works. You can skip to the next chapter to start using Python.
If you select the menu item, this will open a Microsoft Help reader that will show the complete Python documentation library.
Python is part of the MacOS environment. Tiger (MacOS 10.4) includes
Python 2.3.5 and IDLE. Leopard (MacOS 10.5) includes Python 2.5.1.
Generally, you don't need to do much to get started. You'll just need to
locate the various Python files. Look in
/System/Library/Frameworks/Python.Framework/Versions
for the relevant files.
In order to upgrade software in the Macintosh OS, you must know the administrator, or “owner” password. If you are the person who installed or initially setup the computer, you had to pick an owner password during the installation. If someone else did the installation, you'll need to get the password from them.
The Mac OS installation of Python has three broad steps.
We'll go through each of these in detail.
Before installing software, back up your computer. While you can't easily burn a DVD of everything on your computer, you can usually burn a DVD of everything in your Mac OS X Home directory.
I've never had a single problem installing Python. I've worked with a number of people, however, who either have bad luck or don't read carefully and have managed to corrupt their Mac OS installation by downloading and installing software. While Python is safe, stable, reliable, virus-free, and well-respected, you may be someone with bad luck who has a problem. A backup is cheap insurance.
You should also have a folder for saving your downloads. You can
create a folder in hour Documents called
downloads. I suggest that you keep all of your
various downloaded tools and utilities in this folder for two reasons. If
you need to reinstall your software, you know exactly what you downloaded.
When you get a new computer (or an additional computer), you know what
needs to be installed on that computer.
Download. After making a backup, go to the www.python.org web site and look for
the Download area. In here, you're looking for the pre-built Mac OS X
installer. This book will emphasize Python 2.5. In that case, the kit is
python-2.5..
When you click on the filename, your browser should start downloading
the file. Save it in your x-macosxdate.dmgdownloads folder.
Backup. Now is a good time to make a second backup. Seriously. It is still cheap insurance.
At this point, you have everything you need to install Python:
When you double-click the
python-2.5.
file, it will create a disk image named x-macosxdate.dmgUniversal MacPython
2.5.. This disk image has your
license, a ReadMe file, and the
xMacPython.mpkg.
When you double-click the MacPython.mpkg fie,
it will take all the necessary steps to install Python on your computer.
The installer will take you through seven steps. Generally, you'll read
the messages and
Introduction. Read the message and click .
Read Me. This is the contents of the ReadMe file on the installer disk image. Read the message and click .
License. You can read the history of Python, and the terms and conditions for using it. To install Python, you must agree with the license. When you click , you will get a pop-up window that asks if you agree. Click to install Python.
Select Destination. Generally, your primary disk drive, usually named
Macintosh HD will be highlighted with a green
arrow. Click .
Installation Type. If you've done this before, you'll see that this will be an upgrade. If this is the first time, you'll be doing an install. Click the or button.
You'll be asked for your password. If, for some reason, you aren't the administrator for this computer, you won't be able to install software. Otherwise, provide your password so that you can install software.
Finish Up. The message is usually "The software was successfully installed". Click to finish.
In your Applications folder, you'll find a MacPython
2.5 folder, which contains a number of applications.
BuildApplet
Extras
IDLE
PythonLauncher
Update Shell Profile.command
Look in
/System/Library/Frameworks/Python.Framework/Versions
for the relevant files. In the bin,
Extras and Resources directories
you'll find the various applications. The bin/idle
file will launch IDLE for us.
Once you've finished installation, you should check to be sure that everything is working correctly.
Now you can go to your Applications 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.
Here's what you'll see in the Python Shell window.
Python 2.5.1 (r251:54863, Oct 5 2007, 21:08:09)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
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.2.1
>>>
The menu bar will have a menu named with the menu item . Use this to finish using IDLE for now, and skip to the next chapter.
You may notice a menu. This has the menu item, which you can access through the menu or by hitting F1. This will launch Safari to show you the Python documents available on the Internet.
In order to install software in GNU/Linux, you must know the administrator, or “root” password. If you are the person who installed the GNU/Linux, you had to pick an administrator password during the installation. If someone else did the installation, you'll need to get the password from them.
Normally, we never log in to GNU/Linux as root
except when we are installing software. In this case, because we are going
to be installing software, we need to log in as root,
using the administrative password.
If you are a GNU/Linux newbie and are in the habit of logging in as
root, you're going to have to get a good GNU/Linux
book, create another username for yourself, and start using a proper
username, not root. When you work as
root, you run a terrible risk of damaging or corrupting
something. When you are logged on as anyone other than
root, you will find that you can't delete or alter
important files.
Do You Already Have Python? Many GNU/Linux and Unix systems have Python installed. On some older Linuxes [Linuxi? Lini? Linen?] there may be an older version of Python that needs to be upgraded. Here's what you do to find out whether or not you already have Python.
You'll need to run the Terminal tool. The
GNOME desktop that comes with Red Hat and Fedora 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 icon, or pick
it off the menu, and you'll get a window which prompts you by showing
something like [slott@linux01 slott]$. In response to this
prompt, enter env python, and see what happens.
Here's what happens when Python is not installed.
slott%env pythontcsh: python: not found
Here's what you see when there is a properly installed, but out-of-date Python on your GNU/Linux box.
slott% env python
Python 2.3.5 (#1, Mar 20 2005, 20:38:20)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1809)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
In this case, the version number is 2.3.5, which is good, but we need to install an upgrade.
Unix is not Linux. For non-Linux commercial Unix installations (Solaris™, AIX™, HP/UX™, etc.), check with your vendor (Sun, IBM, HP, etc.) It is very likely that they have an extensive collection of open source projects like Python pre-built for your UNIX variant. Getting a pre-built kit from your operating system vendor is the best way to install Python.
If you are a Red Hat or Fedora user, you likely have a program named Yum. If you don't have Yum, you should upgrade to Fedora Core 8, which includes Python 2.5, Yum (plus many other new programs.)
Note that Yum repositories do not cover every combination of operating system and Python distribution. For example, there isn't a handy pre-built setup for Python 2.5 on Fedora Core 6. In many cases, you'll want to do an operating system upgrade in order to introduce a new Python distribution.
If you have an out-of-date Python, you'll have to enter two commands in the Terminal window.
yum upgrade python yum install tkinter
The first command will upgrade the Python 2.5 distribution. You can
use the command "install" instead of "upgrade" in
the unlikely event that you somehow have Yum, but don't have Python.
The second command will assure that the extension package named
tkinter is part of your Fedora installation. It is not,
typically, provided automatically. You'll need this to make use of the
IDLE program used extensively in later
chapters.
Many variants of GNU/Linux use the Red Hat Package Manager (RPM). The rpm tool automates the installation of software and the important dependencies among software components. If you don't know whether on not your GNU/Linux uses the Red Hat Package manager, you'll have to find a GNU/Linux expert to help you make that determination.
Red Hat Linux (and the related Fedora Core distributions) have a version of Python pre-installed. Sometimes, the pre-installed Python is an older release and needs an upgrade.
This book will focus on Fedora Core GNU/Linux because that's what I have running. Specifically, Fedora Core 8. You may have a different GNU/Linux, in which case, this procedure is close, but may not be precisely what you'll have to do.
The Red Hat and Fedora GNU/Linux installation of Python has three broad steps.
We'll go through each of these in detail.
Resolving RPM Dependencies. When doing manual RPM installations, you may have to make several passes. This occurs when the package you're trying to install depends on a package that is missing or out of date. The installation step breaks down into a series of attempts to locate and install the needed packages.
First, attempt to install the package. If all of the foundation is in place, this will work, and you'll be finished. If you don't have the complete foundation in place, you'll get messages telling you what's missing or out-of-date.
If RPM reports any missing or wrong version packages, you must freshen or install the missing packages. This will build the proper foundation. Note that foundations have sub-foundations, and sub-foundations have sub-sub-foundations. This process can go pretty deep, so keep notes on where you are in the process.
Finally, finish installing the package you started out trying to install. Ideally, you took a detour and installed everything on which this package depends, so the second time around it should install. If the package doesn't install, you'll be back at step 2 with a different list of foundational components to put in place.
Before installing software, back up your computer.
You should also have a directory for saving your downloads. I
recommend that you create a /opt directory for these
kinds of options which are above and beyond the basic Linx installation.
You can keep all of your various downloaded tools and utilities in this
directory for two reasons. If you need to reinstall your software, you
know exactly what you downloaded. When you get a new computer (or an
additional computer), you know what needs to be installed on that
computer.
A typical scenario for installing Python is a command like the following. This has specific file names for Fedora Core 9. You'll need to locate appropriate RPM's for your distribution of Linux.
rpm -i http://download.fedora.redhat.com/pub/fedora/linux/development\ /i386/os/Packages/python-2.5.1-18.fc9.i386.rpm
Often, that's all there is to it. In some cases, you'll get warnings about the DSA signature. These are expected, since we didn't tell RPM the public key that was used to sign the packages.
Run the Terminal tool. At the command line prompt, enter env
python, and see what happens. Generally, we should be able to
simply enter python and run the python
environment.
[slott@linux01 ~]$ python Python 2.5.1 (r251:54863, Oct 30 2007, 13:54:11) [GCC 4.1.2 20070925 (Red Hat 4.1.2-33)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
If you hit Ctrl-D (the GNU/Linux end-of-file character), Python will exit. The basic Python program works.
There are many GNU/Linux variants, and we can't even begin to cover each variant. You can use a similar installation on Windows or the Mac OS, if you have the GCC compiler installed. Here's an overview of how to install using a largely manual sequence of steps.
Pre-Installation. Make backups and download the installation kit. You're looking
for the a file named
python-2.5..x.tgz
Installation. The installation involves a fairly common set of commands. If you are an experienced system administrator, but a novice programmer, you may recognize these.
Change to the /opt/python directory with the following command.
cd /opt/python
Unpack the archive file with the following command.
tar -zxvf Python-2.5.x.tgz
Do the following four commands to configure the installation scripts, make the Python package and then install Python on your computer.
cd Python-2.5 ./configure make make install
Run the Terminal tool. At the command line prompt, enter env
python, and see what happens.
[slott@linux01 ~]$ python Python 2.5.1 (r251:54863, Oct 30 2007, 13:54:11) [GCC 4.1.2 20070925 (Red Hat 4.1.2-33)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
If you hit Ctrl-D (the GNU/Linux end-of-file character), Python will exit. The basic Python program works.
The most likely problem you'll encounter in doing a generic installation is not having the appropriate GNU GCC compiler. In this case, you will see error messages from configure which identifies the list of missing packages. Installing the GNU GCC can become a complex undertaking.
Table of Contents
Python is an interpreted, dynamic language. The Python interpreter can be used in two modes: interactive and scripted. In interactive mode, Python responds to each statement while we type. In script mode, we give Python a file of statements and turn it loose to interpret all of the statements in that script. Both modes produce identical results. When we're producing a finished application program, we set it up to run as a script. When we're experimenting or exploring, however, we may use Python interactively.
We'll describe the interactive command-line mode for entering simple Python statements in Command-Line Interaction. In The IDLE Development Environment we'll cover the basics of interactive Python in the IDLE environment. We'll describes the script mode for running Python program files in Script Mode.
We'll look at interaction on the command line first, because it is the simplest way to interact with Python. It parallels scripted execution, and helps us visualize how Python application programs work. This is the heart of IDLE as well as the foundation for any application programs we build.
Starting and stopping Python varies with your operating system. Generally, all of the variations are nearly identical, and differ only in minor details.
Windows. There are two ways to start interactive Python under Windows.
You can run the command tool (cmd.exe) or you can
run the Python (Command Line) program. If
you run cmd.exe, enter the command
python to start interactive Python. If you run
from the
menu, the result will be essentially the
same.
To exit from Python, enter the end-of-file character sequence, Control-Z and Return.
Mac OS, GNU/Linux and Unix. You will run the Terminal tool. You can enter the command python to start interactive Python.
To exit from Python, enter the end-of-file character, Control-D.
When we run the Python interpreter (called
python, or Python.exe in
Windows), we see a greeting like the following:
52:~ slott$env pythonPython 2.5.1 (r251:54863, Oct 5 2007, 21:08:09) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information.>>>
When we get the >>> prompt, the Python
interpreter is looking for input. We can type any Python statements we
want. Each complete statement is executed when it is entered. Some
statements are called compound statements; a
compound statement has a suite of statements indented inside of it.
Python will wait until the entire compound statement is entered before
it does does the evaluation.
In this section, we'll emphasize the prompts from Python. This can help newbies see the complete cycle of interaction between themselves and the Python interpreter. In the long run we'll be writing scipts and won't see this level of interaction.
The Return Key. For this section only, we'll also emphasize the usually invisible Return (↵) key. When we start using compound statements in Chapter 7, Truth, Comparison and Conditional Processing, we'll add some additional syntax rules. For now, however, statements can't be indented; they must begin without any leading spaces or tabs.
>>>2 + 3 ↵5>>>
This shows Python doing simple integer arithmetic. When you
entered 2 + 3 and then hit Return, the Python interpreter evaluated this
statement. Since the statement was only an expression, Python printed
the results.
We'll dig into to the various kinds of numbers in Simple Numeric Expressions and Output. For now, it's enough to
know that you have integers and floating-point numbers that look much
like other programming languages. As a side note, integers have two
slightly different flavors -- fast (but small) and long (but slow).
Python prefers will use the fast integers (called
int) until your numbers get so huge that it has
to switch to long.
Arithmetic operators include the usual culprits: +,
-, *, /, % and
** standing for addition, subtraction, multiplication,
division, modulo (remainder after division) and raising to a power. The
usual mathematical rules of operator precedence (multiplys and divides
done before adds and subtracts) are in full force, and ()'s are used to
group terms against precedence rules.
For example, converting 65° Fahrenheit to Celsius is done as follows:
>>>(65 - 32) * 5 / 9 ↵18>>>(65.-32)*5/9↵18.333333333333332>>>
Note that the first example used all integer values, and the result was an integer result. In the second example, the presence of a float caused all the values to be coerced to float.
End-Of-Statement Rules. What happens when the expression is obviously incomplete?
>>>( 65 - 32 ) * 5 / ↵File "<stdin>", line 1 (65-32)*5 / ^ SyntaxError: invalid syntax>>>
One basic syntax rule is that statements must be complete on a single line. There are few formal lexical rules for the structure of statements; we'll present them more formally after we've experienced them.
There is an escape clause in the basic rule of “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>>>
It is also possible to continue a long statement using a \ escape just before hitting Return at the end of the line.
>>>5 + 6 *\ ↵...7↵47>>>
This escape allows you to break up an extremely long statement for easy reading. It creates an escape from the usual 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”.
Indentation. Python relies heavily on indendentation to make a program readable. When interacting with Python, we are often typing simple expression statements, which are not indented. Later, when we start typing compound statements, indentation will begin to matter.
Here's what happens if we try to indent a simple expression statement.
>>> 5+6
SyntaxError: invalid syntax
Command History. When we type a complete expression, Python evaluates it and displays the result. When we type a complete statement, Python executes it silently. We'll see more of this, starting in Chapter 6, Variables, Assignment and Input. We'll make heavy use of this feature in Chapter 4, Simple Numeric Expressions and Output.
Small mistakes can be frustrating when typing a long or complex statement. Python has a reasonable command history capability, so you can use the up-arrow key to recover a previous statement. Generally, you'll prefer to create script files and run the scripts. When debugging a problem, however, interactive mode can be handy for experimenting.
One of the desirable features of well-written Python is that most things can be tested and demonstrated in small code fragments. Often a single line of easy-to-enter code is the desired style for interesting programming features. Many examples in reference manuals and unit test scripts are simply captures of interactive Python sessions.
There are a number of possible integrated development environments (IDE) for Python. Python includes the IDLE tool, which we'll emphasize. Additionally, you can purchase a number of IDE's that support Python. In Other Tools we'll look at tools that you can use to create a IDE-like toolset.
Starting and stopping IDLE varies with your operating system. Generally, all of the variations are nearly identical, and differ only in minor details.
Windows. There are several ways to start IDLE in Windows. You can use from the menu on the menu.
You can also run IDLE from the command prompt. This requires two configuration settings in Windows.
Assure that C:\Python25\Lib\idlelib on
your system PATH. This directory contains
IDLE.BAT.
Assure that .pyw files are associated with
C:\Python25\pythonw.exe. In order suppress
creation of a console window for a GUI application, Windows offers
pythonw.exe.
You can quit IDLE by using the menu item under the menu.
Mac OS. In the Mac OS, if you've done an upgrade, you may find the
IDLE program in the Python
2.5 folder in your Applications
folder. You can double-click this icon to run
IDLE.
You can always find IDLE in the directory
/System/Library/Frameworks/Python.framework/Versions/Current/bin.
Generally, this is on your PATH, and you can type the command
idle in a Terminal window to start IDLE. The
idle2.5 icon is a document, not an applicaction,
and can't easily be put into your Dock.
You can create your own Applescript icon to run the IDLE shell script. This requires a single line of Applescript:
do shell script "/System/Library/Frameworks/Python.framework/Versions/Current/bin/idle"
When you run IDLE from the icon, you'll notice that two windows are opened: a Python Shell window and a Console window. The Console window isn't used for much.
When you run IDLE from the Terminal window, no console window is opened. The Terminal window is the Python console.
You can quit IDLE by using the menu item under the menu. You can also quit by using the menu item under the menu.
Since the Macintosh keyboard has a command key, ⌘, as well as a control key, ctrl, there are two keyboard mappings for IDLE. You can use the item under the menu to select any of the built-in Key Sets. Selecting the IDLE Classic Mac settings may be more comfortable for Mac OS users.
GNU/Linux. We'll avoid the GNOME and KDE subtleties. Instead, we'll focus
on running IDLE from the
Terminal tool. Since the file path is
rather long, you'll want to edit your .profile
(or .bash_profile) to include the following alias
definition.
alias idle='env python /usr/lib/python2.5/idlelib/idle.py &'
This allows you to run IDLE by entering the command idle in a Terminal window.
You can quit IDLE by using the menu item under the menu.
Initially, you'll see the following greeting from IDLE.
Python 2.5.1 (r251:54863, Oct 5 2007, 21:08:09)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
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.2.1
>>> The personal firewall notification is a reminder that IDLE uses Internetworking Protocols (IP) as part of its debugger. If you have a software firewall on you development computer, and the firewall software complains, you can allow the connection.
IDLE has a simple and relatively standard text editor, which does Python syntax highlighting. It also has a Python Shell window which manages an interactive Python session. You will see that the Python Shell window has a and a menu.
When you use the menu item in the menu, you'll see a file window, which has a slightly different menu bar. A file window has name which is a file name (or untitled), and two unique menus, a and a menu.
Generally, you'll use IDLE in two ways:
You'll enter Python statements in the Python Shell window.
You'll create files, and run those module files using the item in the menu. This option is usually F5.
The Python Shell window in
IDLE presents a >>>
prompt. At this prompt, you can enter Python expressions or statements
for evaluation. This window has a complete command history, so you can
use the up arrow to select a previous statement and
make changes.
You can refer back to Command-Line Interaction; those interactions will look and behave the same in IDLE as they do on the command line.
The Shell Window is essentially the command-line interface wrapped in a scrolling window. The IDLE interface, however, provides a consistent working environment, which is independent of each operating system's command-line interface.
The and menus provides functions you'll use when developing larger programs. For our first steps with Python, we won't need either of these menus. We'll talk briefly about the functions, but can't really make use of them until we've learned more of the language.
The Shell Menu. The menu is used to restart the Python interpreter, or scroll back through the shell's log to locate the most recent restart. This is important when you are developing a module that is used as a library. When you change that module, you need to reset the shell so that the previous version is forgotten and the new version can be imported into a fresh, empty interpreter.
Generally, being able to work interactively is the best way to develop working programs. It encourages you to create tidy, simple-looking components which you can exercise directly.
The Debug Menu. The menu provides some handy tools for watching how Python executes a program.
The item is used to locate the source file where an exception was raised. You click on the exception message which contains the file name and select the menu item, and IDLE will open the file and highlight the selected line.
The item opens an interactive debugger window that allows you to step through the executing Python program.
The item opens a window that displays the current Python stack. This shows the arguments and working variables in the Python interpereter. The stack is organized into local and global namespaces, a conceot we need to delve into in Chapter 6, Variables, Assignment and Input.
The option will open the Stack Viewer automatically when a program raises an unhandled exception. How exceptions are raised and handled is a concept we'll delve into in Chapter 17, Exceptions.
Each file window in IDLE is a simple text editor with two additional menus. The menu has a series of items for fairly common source text manipulations. The formatting operations include indenting, commenting, handling tabs and formatting text paragraphs.
The menu makes it easy to execute the file you are editing.
The menu item brings up the Python Shell window.
The item checks the syntax for your file. If there are any errors, IDLE will highlight the offending line so you can make changes. Additionally, this option will check for inconsistent use of tabs and spaces for indentation.
The , F5, runs the entire file. You'll see the output in the Python Shell window.
In interactive mode, Python displays the results of expressions. In script mode, however, Python doesn't automatically display results.
In order to see output from a Python script, we'll introduce the print statement. This statement takes a list of values and prints their string representation on the standard output file. The standard output is typically directed to the Terminal window. We'll revisit this in depth in The print Statement.
print "PI = ", 355.0/113.0
We can have the Python interpreter execute our script files.
Application program scripts can be of any size or complexity. For the
following examples, we'll create a simple, two-line script, called
example1.py.
There are several ways we can start the Python interpreter and have it evaluate our script file.
Explicitly from the command line. In this case we'll be running Python and providing the name of the script as an argument.
Implicitly from the command line. In this case, we'll either use the GNU/Linux shell comment (sharp-bang marker) or we'll depend on the file association in Windows.
Manually from within IDLE. It's important for newbies to remember that IDLE shouldn't be part of the final delivery of a working application. However, this is a great way to start development of an application program.
Running Python scripts from the command-line applies to all operating systems. It is the core of delivering final applications. We may add an icon for launching the application, but under the hood, an application program is essentially a command-line start of the Python interpreter.
The simplest way to execute a script is to provide the script file name as a parameter to the python interpreter. In this style, we explicitly name both the interpreter and the input script. Here's an example.
This will provide the example1.py file to the
Python interpreter for execution.
We can streamline the command that starts our application. For
POSIX-standard operating systems (GNU/Linux, UNIX and MacOS), we make
the script file itself executable and directing the shell to locate the
Python interpreter for us. For Windows users, we associate our script
file with the python.exe interpreter. There are one
or two steps to this.
Associate your file with the Python interpreter. Except for
Windows, you make sure the first line is the following:
#!/usr/bin/env python. For Windows,
you must assure that .py files are associated
with python.exe and .pyw
files are associated with
pythonw.exe.
The whole file will look like this:
#!/usr/bin/env python print 65, "F" print ( 65 - 32 ) * 5 / 9, "C"
example1.py
to make the file example1.py executable.
You only do this once, typically the first time you try to run the
file. For Windows, you don't need to do this.Now you can run a script in most GNU/Linux environments by saying:
./example1.py
Windows Setup. Windows users will need to be sure that
python.exe is on their PATH. This
is done with the System control panel. Click on the
tab. Click on the
button. Click on the
System variables Path line, and click the
button. This will often have a long list
of items, sometimes starting with “%SystemRoot%”. At the
end of this list, add “;” and the direction location of
Python.exe. On my machine, I put it in C:\Python23.
For Windows programmers, the windows command interpreter uses the
last letters of the file name to associate a file with an interpreter.
You can have Windows run the python.exe program
whenever you double-click a .py file. This is done
with the Folder Options control panel. The
tab allows you to pair a file type
with a program that processes the file.
POSIX Setup. We have to be sure that the Python interpreter is in value of
the PATH that our shell uses. We can't delve into the
details of each of the available UNIX Shells. However, the general
rule is that the person who administers your POSIX computer should
have installed Python and updated the
/etc/profile to make Python available to all
users. If, for some reason that didn't get done, you can update your
own .profile to add Python to your
PATH variable.
Throughout the rest of this book, we're going to use this script processing mode as the standard way to run Python programs. Many of the examples will be shown as though a file was sent to the interpreter.
For debugging and testing, it is sometimes useful to import the program definitions, and do some manipulations interactively. We'll touch on this in the section called “Hacking Mode”.
Here's a second example. We'll create a new file and write another
small Python program. We'll call it
example2.py.
Example 3.3. example2.py
#!/usr/bin/env python """Compute the odds of spinning red (or black) six times in a row on an American roulette wheel. """ print (18.0/38.0)**6
This is a one-line Python program with a two line module document string. That's a good ratio to strive for.
After we finish editing, we mark this as executable using
chmod +x example2.py. Since this is a property of the file,
this is remains true no matter how many times we edit, copy or rename
the file.
When we run this, we see the following.
$./example2.py0.0112962280375
Which says that spinning six reds in a row is about a one in eighty-nine probability.
Informally, we've seen that simple Python statements must be complete on a single line. As we will see in following chapters, compound statements are built from simple and compound statements.
Fundamentally, Python has a simple equivalence between the lexical line structure and the statements in a Python program. This forces us to write readable programs with one statement per line. There are nine formal rules for the lexical structure of Python.
Simple statements must be complete on a single Logical Line. Starting in Chapter 7, Truth, Comparison and Conditional Processing we'll look at compound statements, which have indented suites of statements, and which span multiple Logical Lines. The rest of these rules will define how Logical Lines are built from Physical Lines through a few Line Joining rules.
Physical Lines are defined by the platform; they'll end in
standard \n or the Windows ASCII CR
LF sequence (\r\n).
Comments start with the # character outside a
quoted string; comments end at the end of the physical line. These are
not part of a statement; they may occur on a line by themselves or at
the end of a statement.
Coding-Scheme Comments. Special comments that are by VIM or
EMACS can be included in the first or second line of a Python file.
For example, # -*- coding: latin1 -*-
Explicit Line Joining. A \ at the end of a physical
line joins it to the next physical line to make a logical line. This
escapes the usual meaning of the line end
sequence. The two or three-character sequences (\\n or
\\r\n) are treated as a single space.
Implicit Line Joining. Expressions with ()'s,
[]'s or {}'s can be split into multiple
physical lines.
Blank Lines. When entering statements interactively, an extra blank line is treated as the end of an indented block in a compound statement. Otherwise, blank lines have no signficance.
Indentation. The embedded suite of statements in a compound statement must be indented by a consistent number of spaces or tabs. When entering statements interactively or in an editor that knows Python syntax (like IDLE), the indentation will happen automatically; you will outdent by typing a single backspace. When using another text editor, you will be most successful if you configure your editor to use four spaces in place of a tab. This gives your programs a consisent look and makes them portable among a wide variety of editors.
Whitespace at the beginning of a line is part of indentation, and is significant. Whitespace elsewhere within a line is not significant. Feel free to space things out so that they read more like English and less like computer-ese.
Create an Exercises Directory. Create a directory (or folder) for keeping your various exercise scripts. Be sure it is not in the same directory in which you installed Python.
Use IDLE's Shell Window. Start IDLE. Refer back to the exercises in the section called “Command-Line Interaction”. Run these exercises using IDLE.
Use IDLE's File Window. Start IDLE. Note the version number. Use under the menu to create a simple file. The file should have the following content.
""" My First File """ print __doc__
Save this file in your exercises directory; be sure the name
ends with .py. Run your file with the
menu item in the
menu, usually F5.
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.
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.
Interactive Differences. First, run IDLE (or Python) interactively and enter the
following "commands": copyright,
license, credits. These are
special global objects that print interesting things on the
interactive Python console.
Create a Python file with the three commands, each one on a
separate line: copyright,
license, credits. When you run
this, it doesn't produce any output, nor does it produce an
error.
Now create a Python file with three commands, each on a separate line: print copyright, print license, print credits.
Interestingly, these three global variables have different
behavior when used in a script. This is rare. By default, there are
just three more variables with this kind of behavior:
quit, exit and
help.
Numeric Types. Compare the results of 22/7 and 22.0/7. Explain the differences in the output.
This section lists some additional tools which are popular ways to create, maintain and execute Python programs. While IDLE is suitable for many purposes, you may prefer an IDE with a different level of sophistication.
The Komodo Edit is an IDE that is considerably more sophisticated than IDLE. It is — in a way — too sophisticated for this book. Our focus is on the language, not high-powered IDE's. As with IDLE, this is a tool that runs everywhere, so you can move seamlessly from GNU/Linux to Wiundows to the Mac OS with a single, powerful tool.
See www.komodo.com for more information on ordering and downloading.
Windows programmers might want to use a tool like
Textpad. See www.textpad.com for information on
ordering and downloading. Be sure to also download the
python.syn file from www.textpad.com/add-ons,
which has a number of Python syntax coloring configurations.
To use Textpad, you have two setup steps. First, you'll need to add the Python document class. Second you'll need to tell Textpad about the Python tool.
The Python Document Class. You need to tell Textpad about the
Python document class. Use the menu; the
menu item lets you add
Python documents to Textpad. Name your new
document class Python and click
. Give your class members named
*.py and click .
Locate your python.syn file and click
. Check the new Python document class, and
click if everything looks right to create
a new Textpad document class.
The Python Tool. You'll want to add the Python interpreter as a
Textpad tool. Use the
menu again, this time selecting the
item. Scroll down the list of
preferences on the left and click on . On
the right, you'll get a panel with the current set of tools and a
prominent button on the top right-hand
side. Click , and select
from the menu that appears. You'll
get a dialog for locating a file; find the
Python.exe file. Click
to save this program as a
Textpad tool.
You can check this by using menu and item again. Scroll down the list to find . Click the sign and open the list of tools. Click the tool and check the following:
Python.exe$File$FileDirYou might also want to turn off the Sound Alert option; this will beep when a program finishes running. I find this makes things a little too noisy for most programs.
Macintosh programmers might want to use a tool like BBEdit. BBEdit can also run the programs, saving the output for you. See www.barebones.com for more information on BBEdit.
To use BBEdit, you have two considerations when writing Python programs.
You must be sure to decorate each Python file with the following
line: #!/usr/bin/env python. This tells
BBEdit that the file should be interpreted by
Python. We'll mention this again, when we get to script-writing
exericses.
The second thing is to be sure you set the “” option when you use the the item in the (“shebang”) menu. Without this, scripts are run in the root directory, not in the directory that contains your script file.
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 python.sourceforge.net/pep.
We'll include guidelines that will make your programming consistent with the Python modules that are already part of your Python environment. These guidelines should also also make your programming look like other third-party programs available from vendors and posted on the Internet.
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 indendentation become merely conventions; bad-looking, hard-to-read programs are common. On the other hand, Python makes the line breaks and indentations part of the language, forcing you to create programs that are easier on the eyes.
General Notes. We'll touch on many aspects of good Python style as we introduce each piece of Python programming. We haven't seen much Python yet, but we do need some guidance to prevent a few tiny problems that could crop up.
First, Python (like all of Linux) is case sensitive. Some languages that are either all uppercase, or insensitive to case. We have worked with programmers who actually find it helpful to hse the Caps Lock key on their keyboard to expedite working in an all-upper-case world. Please don't do this. Python should look like English, where lower-case letters predominate.
Second, Python makes use of indentation. Most programmers indent very nicely, and the compiler or interpreter ignores this. Python doesn't ignore it. Indentation is useful for write clear, meaning documents and programs are no different.
Finally, your operating system allows a fairly large number of
characters to appear in a file name. Until we start writing modules and
packages, we can call our files anything that the operating system will
tolerate. Starting in Part IV, “Components, Modules and Packages”, however, we'll
have to limit ourselves to filename that use only letters, digits and
_'s. There can be just one ending for the file:
.py.
A file name like exercise_1.py is better than
the name execise-1.py. We can run both programs
equally well from the command line, but the name with the hyphen limits
our ability to write larger and more sophisticated programs.
Table of Contents
Basic expressions are the most central and useful feature of modern programming languages. To see the results of expressions, we'll use a simple output statement. This chapter starts out with the section called “The print Statement”, which covers the print statement. the section called “Numeric Types and Operators” covers the basic numeric data types and operators that are integral to writing expressions Python. the section called “Numeric Conversion Functions” covers conversions between the various numeric types. the section called “Built-In Functions” covers some of the built-in functions that Python provides.
Before delving into numbers, we'll look briefly at the print statement. We'll cover just the essential syntax of the print statement in this section. While the print statement is very handy, it has some odd syntax quirks that we have to defer until later.
Python 3.0 will replace this irregular statement with a built-in function that is perfectly regular, making it simpler to explain and use. The print statement is handy, but it has some confusing details that will be simplified.
The print statement takes a list of values and, well, prints them. Speaking strictly, it does two things: it converts the objects to strings and puts the characters of those strings on standard output. Generally, standard output is the console window where Python was started, although there are ways to change this that are beyond the scope of this book.
Here's a quick summary of the more important features of
print statement syntax. In short, the keyword,
print, is followed by a comma-separated list of
expressions.
print 〈expression,...〉
This syntax summary isn't completely correct because it implies that the list of expressions is terminated with a comma. Rather than fuss around with complex syntax diagrams (that's what the Python reference manual is for) we've show an approximation that is close enough.
The , in a print statement is
used to separate the various expressions.
A , can also be used at the end of the
print statement to change the formatting; this is
an odd-but-true feature that is unique to print
statement syntax.
It's hard to capture all of this sublety in a single syntax diagram.
One of the simplest kind of expressions is a quoted string. You
can use either apostrophes (') or quotes (")
to surround strings. This gives you some flexibility in your strings.
You can put an apostrophe into a quoted string, and you can put quotes
into an apostrophe'd string without the special
escapes that some other languages require. The
full set of quoting rules and alternatives, however, will have to wait
for Chapter 12, Strings.
For example, the following trivial program prints three strings and two numbers.
print "Hi, Mom", "Isn't it lovely?", 'I said, "Hi".', 42, 91056
Multi-Line Output. Ordinarily, each print statement produces one line of output. You can end the print statement with a trailing , to combine the results of multiple print statements into a single line. Here are two examples.
print "335/113=", print 335.0/113.0 print "Hi, Mom", "Isn't it lovely?", print 'I said, "Hi".', 42, 91056
Since the first print statement ends with a , it does not produce a complete line of output. The second print statement finishes the line of output.
Redirecting Output. The print statement's output goes to the operating system's standard output file. How do we send output to the system's standard error file? This involves some more advanced concepts, so we'll introduce it with a two-part recipe that we need to look at in more depth. We'll revisit these topics in Part IV, “Components, Modules and Packages”.
First, you'll need access to the standard error object; you get this via the following statement.
import sys
Second, there is an unusual piece of syntax called a "chevron print" which can be used to redirect output to standard error.
print >>file, [expression, ]
The file can be either sys.stdout or
sys.stderr. Here is an example of a small script
which produces messages on both stderr and stdout.
Example 4.1. mixedout.py
#!/usr/bin/env python """Mixed output in stdout and stderr.""" import sys print >>sys.stderr, "This is an error message" print "This is stdout" print >>sys.stdout, "This is also stdout"
When you run this inside IDLE, you'll notice that the stderr is colored red, where the stdout is colored black. You'll also notice that the order of the output in IDLE doesn't match the order in our program. Most POSIX operating systems buffer stdout, but does not buffer stderr. Consequently, stdout messages don't appear until the buffer is full, or the program exits.
A program produces a number of kinds of output. The print statement is a handy jumping-off point. Generally, we'll replace this with more advanced techiques.
Final Reports. Our desktop applications may produce text-based report files. These are often done with print statements.
PDF or other format output files. A desktop application which produces PDF or other format files will need to use additional libraries to produce PDF files. For example, ReportLab offers PDF-production libraries. These applications won't make extensive use of print statements.
Error messages and processing logs. Logs and errors are often
directed to the standard error file. You won't often use the
print statement for this, but use the
logging library.
Debugging messages. Debugging messages are often handled by
the logging library.
The print statement is a very basic tool for debugging a complex Python program. Feel free to use print statements heavily to create a clear picture of what a program is actually doing. Ultimately, you are likely to replace print statements with other, more sophisticated methods.
Python Enhancement Proposal (PEP) 3105 suggests writing a
print function which replaces the irregular
print statement syntax with a regular function call.
This function can then be altered in simple ways to produce more
sophisticated output. We'll provide an example of this approach in the section called “Advanced Parameter Handling For Functions”.
Python provides four basic types of numbers: plain integers, long integers, floating point numbers and complex numbers.
Numbers all have several things in common. Principally, the standard
arithmetic operators of +, -, *,
/, % and ** are all available for
all of these numeric types. Additionally, numbers can be compared, using
comparison operators that we'll look at in the section called “Comparisons”. Also, numbers can be coerced from one type
to another.
More sophisticated math is separated into the
math module, which we will cover later. However, a
few advanced math functions are an integral part of Python, including
abs(x) and
pow(x, y).
Plain integers are at least 32 bits long. The range is at least -2,147,483,648 to 2,147,483,647 (approximately ±2 billion).
Python represents integers as strings of decimal digits. A number does not include any punctuation, and cannot begin with a leading zero (0). Leading zeros are used for base 8 and base 16 numbers. We'll look at this below.
>>>255+100355>>>397-42355>>>71*5355>>>355/1133
While most features of Python correspond with common expectations from mathematics and other programming languages, the division operator, /, poses certain problems. Specifically, the distinction between the algorithm and the data representation need to be made explicit. Division can mean either exact floating-point results or integer results. Mathematicians have evolved a number of ways of describing precisely what they mean when discussing division. We need similar expressive power in Python.We'll look at more details of division operators in the section called “Division Operators”.
Octal and Hexadecimal. For historical reasons, Python supports programming in octal and hexadecimal. I like to think that the early days of computing were dominated by people with 8 or 16 fingers.
A number with a leading 0 (zero) is octal, base 8, and uses the
digits 0 to 7. 0123 is octal and equal to 83
decimal.
A number with a leading 0x or
0X is hexadecimal, base 16, and uses the digits 0
through 9, plus a, A, b, B, c, C, d, D, e, E, f, and F.
0x2BC8 is hexadecimal and equal to 11208.
Hex, octal and long notations can be combined.
0x234C678D098BAL, for example is
620976988526778L.
Watch for leading zeros in numbers. If you transcribe programs from other languages, they may use leading zeros on decimal numbers.
Function Notation. The absolute value operation is done using a slightly different notation than the conventional mathematical operators like + and - that we saw above. It uses functional notation, sometimes called prefix notation. A mathematician would write |n|. Here's the formal Python definition:
abs (number) →
numberReturn 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 Chapter 11, Sequences: Strings, Tuples and Lists.
Here's an example using the
abs(x) function.
>>>print abs(10-28/2)4
The expression inside the parenthesis is evaluated first (yielding
-4). Then the abs(x)
function is applied to -4. This evaluates to 4.
One of the useful data types that Python offers are 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. However, these will operate more slowly than plain integers. Long integers end in L or l. Upper case L is preferred, since the lower-case l looks too much like the digit 1. Python is graceful about converting to long integers when it is necessary.
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 anwer in long integers.
>>>print 2**324294967296L
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?
print 2L**(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.
Python will silently convert between ultra-fast integers and
slow-but-large long integers. You can force a conversion using the
int or long factory
functions.
Python offers floating-point numbers, often implemented as
"double-precision" numbers, typically using 64 bits. Floating-point
numbers are based on scientific notation, where
numbers are written as a mantissa and an
exponent. Generally, powers of 10 are used with
the exponent, giving us numbers that look like this:
.
When we write a number that includes a decimal point, Python uses floating point representation. We can also use a form of scientific notation with an explicit mantissa and exponent. Here are some examples:
.0625 0.0625 6.25E-2 625E-4
The last example isn't properly normalized, since the mantissa isn't between 0 and 10.
Generally, a number, n, is some mantissa, g, and an exponent of c. For human consumption, we use a base of 10.
Internally, most computers use a base of 2, not 10. This leads to slight errors in converting certain values, which are exact in base 10, to approximations in base 2.
For example, 1/5th doesn't have a precise representation. This isn't generally a problem because we have string formatting operations which can make this tiny representation error invisible to users.
>>>1./50.20000000000000001
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.
>>>print (2+3j)*(4+5j)(-7+22j)
Python even includes the complex conjugate operation on a complex
number. This operation follows the complex number separated by a dot
(.). This notation is used because the conjugate is treated
like a method function of a complex number object (we'll return to this
method and object terminology in Chapter 21, Classes). For
example:
>>>print 3+2j.conjugate()(3-2j)
We can convert a number from one type to another. A conversion may involve a loss of precision because we've reduced the number of bits available. A conversion may also add a false sense of precision by adding bits which don't have any real meaning.
We'll call these factory functions because they are a factory for creating new objects from other objects. The idea of factory function is a very general one, and these are just the first of many examples of this pattern.
Also, this section is only an introduction. A more complete list of conversion functions is provided in the section called “String Conversion Functions”.
There are a number of conversions from one numeric type to another.
int (x) →
integerGenerates an integer from the object
x. If x is a
floating point number, digits to the right of the decimal point
are truncated as part of creating an integer. If the floating
point number is more than about 10 digits, a long integer object
is created to retain the precision. If
x is a long integer that is too large
to be represented as an integer, there's no conversion. If
x is a string, the string is parsed to
create an integer value. Complex values can't be turned into
integers directly.
float (x) →
floatGenerates a float from object x.
If x is an integer or long integer, a
floating point number is created. Note that long integers can have
a large number of digits, but floating point numbers only have
approximately 16 digits; there can be some loss of precision.
Complex values can't turned into floating point numbers
directly.
long (x) →
longGenerates a long integer from x.
If x is a floating point number, digits
to the right of the decimal point are truncated as part of
creating a long integer.
complex (real,
[imag]) → complexGenerates a complex number from real and imag.
If this “complex (real,
[imag] )” syntax synopsis is
confusing, you might want to see Syntax For Newbies.
We'll show optional parameters to functions by surrounding them
with []'s. In the case of complex, there will be
two different ways to use the function, with one parameter,
real, or with two parameters,
real, imag. We don't
actually enter the []'s, they're just hints as to what the two forms
of the function are.
In the case of “complex
(real, [imag]
)”, we have two choices.
>>>complex( 2.0, 3.0 )(2+3j)>>>complex( 4.0 )(4+0j)
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. Examples: float("6.02E24"),
float(23). This is handy when doing division to prevent
getting the simple integer quotient.
For example:
>>>print float(22)/7, 22/73.14285714286 3
int (x ) creates an
integer equal to the string or number x. If a
string is given, it must be a valid decimal integer string. Examples:
int("1243"), int(3.14159).
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).
For example:
>>>print long(2)**6418446744073709551616
This shows the range of values possible with 64-bit integers, available on larger computers.
Complex is not as simple as the others. A complex number has two parts, real and imaginary. Conversion to complex typically involves two parameters.
complex (r,
[i] ) creates a complex number with
the real part of r; if the second parameter,
i, is given, this is the imaginary part of
the complex number, otherwise the imaginary part is zero. The string
must be a valid complex number. Examples:
>>>print complex(3,2), complex(4), complex("3+4j")(3+2j) (4+0j) (3+4j)
Note that the second parameter, with the imaginary part of the number, is optional. This leads to a number of different ways to call this function. In the example above, we used three variations: two numeric parameters, one numeric parameter and one string parameter.
Python has a number of built-in functions, which are an integral part of the Python interpreter. We can't look at all of them because many are related to features of the language that we haven't addressed yet.
One of the built-in mathematical functions will have to wait for
complete coverage until we've introduced the more complex data types,
specifically tuples, in Chapter 13, Tuples. The divmod (x,
y ) function returns a tuple object with
the quotient and remainder in division.
The bulk of the math functions are in a separate module, called
math, which we will cover in the section called “The math Module”. The formal definitions of mathematical
built-in functions are provided below.
abs (number) →
numberReturn the absolute value of the argument, |x|.
pow (x,
y, [z]) →
numberRaise x to the y power. If z is present, this is done modulo z, xy % z.
round (number,
[ndigits]) → floatRound number to ndigits beyond the decimal point.
cmp (x,
y) → integerCompare x and y, returning a number. If the number is less than 0, then x<y; if the number is zero, then x == y; if the number is positive, then x>y.
The round (number,
[ndigits] ) function rounds a number to
the nearest whole number. If the n parameter is given, this is the
number of decimal places to round to. If n is positive, this is decimal
places to the right of the decimal point. If n is negative, this is the
number of places to the left of the decimal point. Examples:
round(678.456,2) yields 678.46;
round(678.456,-1) yields 680.
The cmp(x,
y) function is handy for the
comparisons used when sorting objects into order. For example,
cmp(2,35) yields -1, telling us that the first
value is less than the second value.
The string conversion functions provide alternate representations for numeric values. This list expands on the function definitions in the section called “Numeric Conversion Functions”.
hex (number) →
stringCreate a hexadecimal string representation of
number. A leading '0x' is placed on the
string as a reminder that this is hexadecimal.
hex(684) yields the string
'0x2ac'.
oct (number) →
stringCreate a octal string representation of
number. A leading '0' is placed on the string
as a reminder that this is octal not decimal.
oct(509) yields the string
'0775'.
int (string,
[base]) → integerGenerates an integer from the string x. If base is supplied, x must be in the given base. If base is omitted, x must be decimal.
str (object) →
stringGenerate a string representation of the given object. This is the a "readable" version of the value.
repr (object) →
stringGenerate a string representation of the given object. Generally, this is the a Python expression that can reconstruct the value; it may be rather long and complex.
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. For example
int('010101',2) yields 21. int('321',4) is 57,
int('2ac',16) is 684.
The str(x) and
repr(x) functions convert any
Python object to a string. The
str(x) version is typically
more readable, where the
repr(x) version is an
internalized representation. For most garden-variety numeric values,
there is no difference. For the more complex data types, however, the
resultsof repr and str can be
very different. For classes you write (see Chapter 21, Classes), your class definition must provide these
string representation functions.
These are two built-in functions which operate on a collection of data elements.
max (sequence) →
valueReturn the largest value in sequence.
min (sequence) →
valueReturn the smallest value in sequence.
The max and min
functions accept any number of values and return the largest or smallest
of the values. max(1,2,3) yields 3, min(1,2,3)
yields 1.
There are two sets of exercises. The first section, the section called “Basic Output and Functions”, covers simpler exercises to reinforce Python basics. The secoind section, the section called “Numeric Types and Expressions”, covers more complex numeric expressions.
Print Expression Results. In Simple Expressions, we entered some simple expressions into the Python interpreter. Change these simple expressions into 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
Evaluate and Print Expressions. Write short scripts to print the results of the following
expressions. In most places, changing integers to floating point
produces a notably different result. For example
(296/167)**2 and (296.0/167.0)**2. Use
long as well as complex types to see the differences.
355/113 * ( 1 - 0.0003/3522 )
22/17 + 37/47 + 88/83
(553/312)**2
Numeric Conversion. Write a print statement to print the mixed fraction 3 5/8 as a floating point number and as an integer.
Numeric Truncation. Write a print statement to compute
(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?
Illegal Conversions. Try illegal conversions like int('A') or
int( 3+4j ). Why are exceptions raised? Why can't a
simple default value like zero or None be used
instead?
Evaluate and Print Built-in Math Functions. Write short scripts to print the results of the following expressions.
pow( 2143/22, 0.25 )
pow(553/312,2)
pow( long(3), 64 )
long( pow(float(3), 64) )
Why do the last two produce different results? What does the difference between the two results tell us about the number of digits of precision in floating-point numbers?
Evaluate and Print Built-in Conversion Functions. Here are some more expressions for which you can print the results.
hex( 1234 )
int( hex(1234), 16 )
long( '0xab' )
int( '0xab' )
int( '0xab', 16 )
int( 'ab', 16 )
cmp( 2, 3 )
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.
Convert Between °C and °F. Convert temperatures 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).
Create a print statement to convert 18° C to °F.
Create a print statement to convert -4° F to °C.
Periodic Payment on a Loan. 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.
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.
Note that the results are negative numbers. You are, after all, paying down a principle.
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.
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.
For example, tanks you own might have a starting pressure of 2500 and 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.
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).
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.
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.
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 zeroes 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.
If you have Python 2.6, you can start using with the
print function. The print function is not part of
Python 2.6, it's a future expansion. To ease the transition from older to
newer language features, there is a __future__
module available. You can get this future expansion by using the following
statement at the beginning of your script or working session in
IDLE.
from __future__ import print_function
This will alert Python that you want to use the
print function instead of the
print statement. We'll look at the
import statement in depth in Part IV, “Components, Modules and Packages”.
The print function has the following formal definition.
print
(object,..., [,sep, ][,end, ][,file])
→ numberConvert the objects to strings and write the strings to the given file.
If sep is not specified, it is a single
space. If end is not specified, it is a
single \n. If the file is
not specified it is sys.stdout.
Examples:
from __future__ import print_function
import sys
print("335/113=",335.0/113.0)
print("Hi, Mom", "Isn't it lovely?", end='')
print('I said, "Hi".', 42, 91056)
print("Red Alert!", file-sys.stderr)
The print statement uses a trailing , to suppress
the newline that defines the end of a line of output. To do this with the
print function, use end=''.
To send output to standard error, use
file=sys.stderr.
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)
The preferred form is the following:
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
Table of Contents
This chapter covers some more advanced topics. the section called “The math Module” covers two important modules,
math and random. the section called “Division Operators” covers the important distinction between the
division operators. We also provide some supplemental information that is
more specialized. the section called “Bit Manipulation Operators” covers some
additional bit-fiddling operators that work on the basic numeric types.
the section called “Expression Style Notes” has some notes on style.
A Python module extends the Python execution environment by adding new classes, functions and helpful constants. We tell the Python interpreter to fetch a module with a variation on the import statement. There are several variations on import, which we'll cover in depth in Part IV, “Components, Modules and Packages”.
For now, we'll use the simple import:
import m
This will import module m. Only the module's
name, m is made available. Every name inside the
module m must be qualified
by prepending the module name and a .. So if module
m had a function called spam,
we'd refer to it as m.spam.
There are dozens of standard Python modules. We'll get to the most important ones in Part IV, “Components, Modules and Packages”. For now, we'll focus on extending the math capabilities of the basic expressions we've looked so far.
The math module is made available to your
programs with:
import math
The math module contains the following
trigonometric functions
math.acos (x ) →
numberarc cosine of x.
math.asin (x ) →
numberarc sine of x.
math.atan (x ) →
numberarc tangent of x.
math.atan2 (y,
x ) → numberarc tangent of y/x.
math.cos (x ) →
numbercosine of x.
math.cosh (x ) →
numberhyperbolic cosine of x.
math.exp (x ) →
numbere**x, inverse of log(x).
math.hypot (x,
y ) → numberEuclidean distance, sqrt(x*x + y*y), length of the hypotenuse of a right triangle with height of y and length of x.
math.log (x ) →
numbernatural logarithm (base e) of x, inverse of exp(x).
math.log10 (x ) →
numbernatural logarithm (base 10) of x, inverse of 10**x.
math.pow (x,
y ) → numberx**y.
math.sin (x ) →
numbersine of x.
math.sinh (x ) →
numberhyperbolic sine of x.
math.sqrt (x ) →
numbersquare 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.
math.tan (x ) →
numbertangent of x.
math.tanh (x ) →
numberhyperbolic tangent of x.
Additionally, the following constants are also provided.
math.pithe value of pi, 3.1415926535897931
math.ethe value of e, 2.7182818284590451, used for the
exp(x) and
log(x) functions.
The math module contains the following other functions for dealing with floating point numbers.
math.ceil (x ) →
numbernext larger whole number. math.ceil(5.1) == 6,
math.ceil(-5.1) == -5.0.
math.fabs (x ) →
numberabsolute value of the real x.
math.floor (x ) →
numbernext smaller whole number. math.floor(5.9) == 5,
math.floor(-5.9) == -6.0.
math.fmod (x,
y ) → numberfloating point remainder after division of
x/y. This depends on the
platform C library and may return a different result than the Python
x % y.
math.modf (x ) → (
number, number )creates a tuple with the fractional and integer parts of x. Both results carry the sign of x so that x can be reconstructed by adding them.
math.frexp (x ) → (
number, number )this function unwinds the usual base-2 floating point
representation. A floating point number is
m*2**e, where
m is always a fraction between 1/2 and 1, and
e is an integer power of 2. This function
returns a tuple with m and
e. The inverse is
ldexp(m,e).
math.ldexp (m,
e ) → numberm*2**e, the inverse
of frexp(x).
The random module is made available to your
program with:
import random
The random module contains the following
functions for working with simple distributions of random numbers. There
are numerous other, more sophisticated distributions available, but some
later exercises will only use these functions.
random.choice (sequence
) → valuechooses a random value from the sequence
sequence. Example: random.choice( ['red',
'black', 'green'] ).
random.random → numbera random floating point number, r, 0 ≤ r < 1.0.
random.randrange ([start,] stop
[,step] ) → integerchoose a random element from range
(start, stop,
step). 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.
random.uniform (a,
b ) → numbera random floating point number, r, a ≤ r < b.
The randrange has two optional values, making
it particularly flexible. Here's an example of some of the
alternatives.
Example 5.1. demorandom.py
#!/usr/bin/env python import random # Simple Range 0 <= r < 6 print random.randrange(6), random.randrange(6) # More complex range 1 <= r < 7 print random.randrange(1,7), random.randrange(1,7) # Really complex range of even numbers between 2 and 36 print random.randrange(2,37,2) # Odd numbers from 1 to 35 print random.randrange(1,36,2)
This demonstrates a number of ways of generating random numbers. It
uses the basic random.randrange with a variety of
different kinds of arguments.
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 )
Run demorandom.py. Run the demorandom.py script several
times and save the results. Then add the following statement to the
script and run it again several times. What happens when we set an
explicit seed?
#!/usr/bin/env python
import random
random.seed(1)
...everything else the same
Try the following variation, and see what it does.
#!/usr/bin/env python
import random, time
random.seed(time.clock())
...everything else the same
Wind Chill. Wind chill is 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.
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.
How Much Does The Atmosphere Weigh? From Slicing Pizzas, Racing Turtles, and Further Adventures in Applied Mathematics, [Banks02].
Air Pressure (at sea level) P0 = 1.01325×105 newtons/m2. A newton is 1 kg·m/sec2 or the force acting on a kg of mass.
Gravity acceleration (at sea level) g = 9.82m/sec2. This converts force from newtons to kg of mass.
Given the mass of air per square meter, we need to know how many square meters of surface to apply this mass to.
Radius of Earth R = 6.37×106m.
Check: somewhere around 1018kg.
How much does the atmosphere weigh? Part 2. From Slicing Pizzas, Racing Turtles, and Further Adventures in Applied Mathematics, [Banks02].
The exercise How Much Does The Atmosphere Weigh? assumes the earth to be an entirely flat sphere. The averge height of the land is actually 840m. We can use the ideal gas law to compute the pressure at this elevation and refine the number a little further.
molecular weight of air m = 28.96×10-3 kg/mol.
gas constant R = 8.314 joule/°Kmol.
gravity g = 9.82 m/sec2.
temperature (°K) T = 273°+°C (assume 15°C for temperature).
elevation z = 840 m.
This pressure can be used for the air over land, and the pressure computed in How Much Does The Atmosphere Weigh? can be used for the air over the oceans. How much land has this reduced pressure? Reference material gives the ocean area (Ao = 3.61×1014 m2) and the land area (Al = 1.49×1014 m2).
We've already seen the usual math operators: +, -, *, /, %, **; as
well as the abs(x) and
pow(x, y)
functions. There are several other operators available to us. Principally,
these are for manipulating the individual bits of an integer value.
The unary ~ operator flops all the bits in a plain or long integer. 1's become 0's and 0's become 1's. Since most hardware uses a technique called 2's complement, this is mathematically equivalent to adding 1 and switching the number's sign.
>>>print ~0x12345678-305419897
There are binary bit manipulation operators, also. These perform simple Boolean operations on all bits of the integer at once.
The binary & operator returns a 1-bit if the two input bits are both 1.
>>>print 0&0, 1&0, 1&1, 0&10 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.
>>>print 3&51
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
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.
>>>print 3^56
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.
The binary | operator returns a 1-bit if either of the two inputs is 1. This is sometimes called the inclusive or. Sometimes this is written and/or.
>>>print 3|57>>>
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.
There are also bit shifting operations. These are mathematically equivalent to multiplying and dividing by powers of two. Often, machine hardware can execute these operations faster than the equivalent multiply or divide.
The << is the left-shift operator. The left argument is the bit pattern to be shifted, the right argument is the number of bits.
>>>print 0xA << 240
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 >> 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.
>>>print 80 >> 310
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.
There are some other operators available, but, strictly speaking, they're not arithmetic operators, they're logic operations. We'll return to them in Chapter 7, Truth, Comparison and Conditional Processing.
In general, the data type of an expresion depends on the types of the arguments. This rule meets our expectations for most operators: when we add two integers, the result should be an integer. However, this doesn't work out well for division because there are two different 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.
The classical Python definition of / depended entirely
on the arguments. 685/252 was 2 because both arguments where integers.
However, 685./252. was 2.7182539682539684 because the arguments were
floating point.
This definition often caused problems for applications where data types were used that the author hadn't expected. For example, a simple program doing Celsius to Fahrenheit conversions will produce different answers depending on the input. If one user provides 18 and another provides 18.0, the answers were different, even though all of the inputs all had the equal numeric values.
>>>print 18*9/5+3264>>>print 18.0*9/5 + 3264.4>>>18 == 18.0True>>>
This unexpected inaccuracy was generally due to the casual use of
integers where floating-point numbers were more appropriate. (This can
also occur using integers where complex numbers were implictly expected.)
An explicit conversion function (like
float(x)) can help prevent this.
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
data type.
Starting with Python 2.2, a new division operator was added to
clarify what is required: / and //. The
/ operator should return floating-point results; the
// operator, will return rounded-down results. In Python 2.5
and 2.6, this distinction is turned off by default. In Python 3.0, this
will be turned on.
To help with the transition, two tools were made available. These
tools allow the division operator, /, to follow the old rules
or the new rules. This gives programmers a way to keep older applications
running; it also gives them a way to explicitly declare that their program
uses the newer operator definition. There are two parts to this: a
statememt that can be placed in a program, as well as a command-line
option that can be used when starting the Python interpreter.
Program Statements. To ease the transition from older to newer language features,
there is a __future__ module available. This
module includes a division definition that
changes the definition of the / operator from classical to
future. You can include the following from statement
to state that your program depends on the future definition of division.
We'll look at the import statement in depth in Part IV, “Components, Modules and Packages”.
from __future__ import division print 18*9/5+32 print 18*9//5+32
This produces the following output. The first line shows the new use
of the / operator to produce floating point results, even if
both arguments are integers. The second line shows the //
operator, which produces rounded-down results.
64.4 64
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.5 that will work correctly with all future versions. By version 3.0, this import statement will no longer be necessary, and these will have to be removed from the few modules that used them.
Command Line Options. Another tool to ease the transition is a command-line option used
when running the Python interpreter. This can force old-style
interpretation of the / operator or to warn about old-style
use of the / operator between integers. It can also force
new-style use of the / operator and report on all
potentially incorrect uses of the / operator.
The Python interpreter command-line option of -Q will
force the / operator to be treated classically
(“old”), or with the future (“new”) semantics.
If you run Python with -Qold, the / operator's
result depends on the arguments. If you run Python with
-Qnew, the / operator's result will be floating
point. In either case, the // operator returns a rounded-down
integer result.
You can use -Qold to force old modules and programs to
work with version 2.2 and higher. When Python 3.0 is released, however,
this transition will no longer be supported; by that time you should have
fixed your programs and modules.
To make fixing easier, the -Q command-line option can
take two other values: warn and warnall. If you
use -Qwarn, then the / operator applied to
integer arguments will generate a run-time warning. This will allow you to
find and fix situations where the // operator might be more
appropriate. If you use -Qwarnall, then all instances of the
/ operator generate a warning; this will give you a close
look at your programs.
You can include the command line option when you run the Python
interpreter. For Linux and MacOS users, you can also put this on the
#! line at the beginning of your script file.
#!/usr/local/bin/python -Qnew
Table of Contents
Variables hold the state of our program. In the section called “Variables” we'll introduce variables, then in the section called “The Assignment Statement” we'll cover the basic assignment statement for changing the value of a variable. This is followed by an exercise section that refers back to exercises from Chapter 4, Simple Numeric Expressions and Output. In the section called “Input Functions” we introduce some primitive interactive input functions that are built-in. This is followed by some simple exercises that build on those from section the section called “The Assignment Statement”. We'll cover the multiple assignment statement in the section called “Multiple Assignment Statement”. We'll round on this section with the del statement, for removing variables in the section called “The del Statement”.
As a multi-statement program makes progress from launch to completion, it does so by undergoing changes of state. The state of our program as a whole is the state of all of the program's variables. When one variable changes, the overall state has changed.
Variables are the names your program assigns to the results of an expression. Every variable is created with an initial value. Variables will change to identify new objects and the objects identified by a variable can change their internal state. These three kinds of state changes (variable creation, object assignment, object change) happen as inputs are accepted and our program evaluates expressions. Eventually the state of the variables indicates that we are done, and our program can exit.
A Python variable name must be at least one letter, and can have a
string of numbers, letters and _'s to any length. Names that
start with _ or __ have special significance.
Names that begin with _ are typically private to a module or
class. We'll return to this notion of privacy in Chapter 21, Classes and Chapter 28, Modules. Names
that begin with __ are part of the way the Python interpreter
is built.
Example variable names include a, pi,
aVeryLongName, a_name, __str__ and
_hidden.
Python creates new objects as the result of evaluating an expression. Python creates new variables with an assignment statement; it also assigns an object to the variable. Python removes variables with a del statement.
Some Consequences. A Python variable is little more than a name which refers to an object. The central issue is to recognize that the underlying object is the essential part of our program; a variable name is just a meaningful label. This has a number of important consequences.
One consequence of a variable being simple a label is that any number of variables can refer to the same object. In other languages (C, C++, Java) there are two kinds of values: primitive and objects, and there are distinct rules for handling the two kinds of values. In Python, every variable is a simple reference to an underlying object. When talking about simple immutable objects, like the number 3, multiple variables referring to a common object is functionally equivalent to having a distinct copy of a primitive value. When talking about mutable objects, like lists, mappings, or complex objects, distinct variable references can change the state of the common object.
Another consequences is that the Python object fully defines it's own type. The object's type defines the representation, the range of values and the allowed operations on the object. The type is established when the object is created. For example, floating point addition and long integer objects have different representations, operations of adding these kinds of numbers are different, the objects created by addition are of distinct types. Python uses the type information to choose which addition operation to perform on two values. In the case of an expression with mixed types Python uses the type information to coerce one or both values to a common type.
We've already worked with the four numeric types: plain integers, long integers, floating point numbers and complex numbers. We've touched on the string type, also. There are several other built-in types that we will look at in detail in Part II, “Data Structures”. Plus, we can use class definitions to define new types to Python, something we'll look at in Part III, “Data + Processing = Objects”.
We commonly say that a static language associates the type information with the variable. Only values of a certain type can be assigned to a given variable. Python, in contrast, is a dynamic language; a variable is just a label or tag attached to the object. Any variable can be associated with an object of any type.
The final consequence of variables referring to objects is that a variable's scope can be independent of the object itself. This means that variables which are in distinct namespaces can refer to the same object. When a function completes execution and the namespace is deleted, the variables are deleted, and the number of variables referring to an object is reduced. Additional variables may still refer to an object, meaning that the object will continue to exist. When only one variable refers to an object, then removing the last variable removes the last reference to the object, and the object can be removed from memory.
Also note that a expressions generally create new objects; if an object is not saved in a variable, it silently vanishes. We can safely ignore the results of a function.
Scope and Namespaces. A Python variable is a name which refers to an object. To be useful, each variable must have a scope of visibility. The scope is defined as the set of statements that can make use of this variable. A variable with global scope can be referenced anywhere. On the other hand, variable with local scope can only be referenced in a limited suite of statements.
This notion of scope is essential to being able to keep a intellectual grip on a program. Programs of even moderate complexity need to keep pools of variables with separate scopes. This allows you to reuse variable names without risk of confusion from inadvertantly changing the value of a variable used elsewhere in a program.
Python collects variables into pools called namespaces. A new namespace is created as part of evaluating the body of a function or module, or creating a new object. Additionally, there is one global namespace. This means that each variable (and the state that it implies) is isolated to the execution of a single function or module. By separating all locally scoped variables into separate namespaces, we don't have an endless clutter of global variables.
In the rare case that you need a global variable, the global statement is available to assign a variable to the global namespace.
When we introduce functions in Chapter 9, Functions, classes in Chapter 21, Classes and modules in Part IV, “Components, Modules and Packages”, we'll revisit this namespace technique for managing scope. In particular, see the section called “Functions and Namespaces” for a digression on this.
Assignment is fundamental to Python; it is how the objects created by an expression are preserved. We'll look at the basic assignment statement, plus the augmented assignment statement. Later, in Multiple Assignment Statement, we'll look at multiple assignment.
We create and change variables primarily with the assignment statement. This statement provides an expression and a variable name which will be used to label the value of the expression.
variable = expression
Here's a short script that contains some examples of assignment statements.
Example 6.1. example3.py
#!/usr/bin/env python # Computer the value of a block of stock shares= 150 price= 3 + 5.0/8.0 value= shares * price print value
We have an object, the number 150, which we
assign to the variable shares. We have an expression
3+5.0/8.0, which creates a floating-point number, which we
save in the variable price. We have another
expression, shares * price, which creates a floating-point
number; we save this in value so that we can print
it. This script created three new variables.
Since this file is new, we'll need to do the chmod +x example3.py once, after we create this file. Then, when we run this progam, we see the following.
$./example3.py543.75$
Any of the usual arithmetic operations can be combined with assignment to create an augmented assignment statement.
For example, look at this augmented assignment statement:
a += v
This statement is a shorthand that means the same thing as the following:
a = a + v
Here's a larger example
Example 6.2. portfolio.py
#!/usr/bin/env python # Total value of a portfolio made up of two blocks of stock portfolio = 0 portfolio += 150 * 2 + 1/4.0 portfolio += 75 * 1 + 7/8.0 print portfolio
First, we'll do the chmod +x portfolio.py on this file. Then, when we run this progam, we see the following.
$./portfolio.py376.125$
The other basic math operations can be used similarly, although the purpose gets obscure for some operations. These include -=, *=, /=, %=, &=, ^=, |=, <<= and >>=.
Here's a lengthy example. This is an extension of Craps Odds in the section called “Numeric Types and Expressions”.
In craps, the first roll of the dice is called the “come out roll”. This roll can be won immediately if one rolls 7 or 11. It can be lost immediately if one roll 2, 3 or 12. The remaining numbers establish a point and the game continues.
Example 6.3. craps.py
#!/usr/bin/env python # Compute the odds of winning on the first roll win = 0 win += 6/36.0 # ways to roll a 7 win += 2/36.0 # ways to roll an 11 print "first roll win", win # Compute the odds of losing on the first roll lose = 0 lose += 1/36.0 # ways to roll 2 lose += 2/36.0 # ways to roll 3 lose += 1/36.0 # ways to roll 12 print "first roll lose", lose # Compute the odds of rolling a point number (4, 5, 6, 8, 9 or 10) point = 1 # odds must total to 1 point -= win # remove odds of winning point -= lose # remove odds of losting print "first roll establishes a point", point
There's a 22.2% chance of winning, and a 11.1% chance of losing. What's the chance of establishing a point? One way is to figure that it's what's left after winning or loosing. The total of all probabilities always add to 1. Subtract the odds of winning and the odds of losing and what's left is the odds of setting a point.
Here's another way to figure the odds of rolling 4, 5, 6, 8, 9 or 10.
point = 0 point += 2*3/36.0 # ways to roll 4 or 10 point += 2*4/36.0 # ways to roll 5 or 9 point += 2*5/36.0 # ways to roll 6 or 8 print point
By the way, you can add the statement print win + lose +
point to confirm that these odds all add to 1. This means that we
have defined all possible outcomes for the come out roll in
craps.
As with many things Python, there is some additional subtlety to this, but we'll cover those topics later. For example, multiple-assignment statement is something we'll look into in more deeply in Chapter 13, Tuples.
Python provides two simplistic built-in functions to accept input and set the value of variables. These are not really suitable for a complete application, but will do for our initial explorations.
Typically, interactive programs which run on a desktop use a
complete graphic user interface (GUI),
often written with the Tkinter module or the
pyGTK module. Interactive programs which run over
the Internet use HTML forms. The primitive interactions we're showing with
input and raw_input are only
suitable for relatively simple programs.
Note that some IDE's buffer the program's output, making these functions appear to misbehave. For example, if you use Komodo, you'll need to use the "Run in a New Console" option. If you use BBEdit, you'll have to use the "Run in Terminal" option.
You can enhance these functions somewhat by including the statement
import readline. This module silently and automatically
enhances these input functions to give the user the ability to scroll
backwards and reuse previous inputs.
You can also import rlcompleter. This module allows you
to define sophisticated keyword auto-completion for these
functions.
The first way to get interactive input is the
raw_input([prompt]) function.
This function accepts a string parameter, which is the user's prompt,
written to standard output. The next line available on standard input is
returned as the value of the function.
The raw_input([prompt])
function reads from a file often called stdin. When
running from the command-line, this will be the keyboard, and what you
type will be echoed in the command window or
Terminal window. If you try, however, to run
these examples from Textpad, you'll see that Textpad doesn't have any
place for you to type any input. In BBEdit, you'll need to use the
item in the
menu.
Here's an example script that uses
raw_input([prompt]).
Example 6.4. rawdemo.py
#!/usr/bin/env python # show how raw_input works a= raw_input( "yes?" ) print a
When we run this script from the shell prompt, it looks like the following.
MacBook-3:Examples slott$python rawdemo.pyyes?why not?why not?$
This program begins by evaluating the
raw_input function. When
raw_input is applied to the parameter of
"yes?", it writes the prompt on standard output, and
waits for a line of input. We entered why not?. Once
that line was complete, the input string is returned as the value of the
function.
The raw_input function's value was assigned
to the variable a. The second statement printed that
variable.
If we want numeric input, we must convert the resulting string to a number.
Example 6.5. stock.py
#!/usr/bin/env python
# Compute the value of a block of stock
shares = int( raw_input("shares: ") )
price = float( raw_input("dollars: ") )
price += float( raw_input("eights: ") )/8.0
print "value", shares * price
We'll chmod +x stock.py this program; then we can run it as many times as we like to get results.
MacBook-3:Examples slott$./stock.pyshares:150dollars:24eights:3value 3656.25$
The raw_input mechanism is very limited. If
the string returned by raw_input is not suitable
for use by int, an exception is raised and the
program stops running. We'll cover exception handling in detail in Chapter 17, Exceptions.
Here's what it looks like.
MacBook-3:Examples slott$./stock.pyshares:a bunchTraceback (most recent call last): File "<stdin>", line 1, in ? File "stock.py", line 3, in ? shares = int( raw_input("shares: ") ) ValueError: invalid literal for int(): a bunchMacBook-3:Examples slott$
In addition to the raw_input function, which
returns the exact string of characters, there is the
input([prompt]) function. This
also accepts an optional parameter, which is the prompt. It writes the
prompt, then reads a line of input. It then applies the Python
eval(string) function to
evaluate the input. Typically, we expect to decode a string of digits as
an integer or floating point number. Actually, it will evaluate any
legal Python expression! Of course, illegal expressions will raise an
exception and the program will stop running.
The value of the input (p
) function is eval( raw_input(. Here's an example:p)
)
When we chmod +x inputdemo.py and run this program, we see the following.
$./inputdemo.pyshares:2+1/2.02.5$
In this case, the input function evaluated
the expression 2+1/2.0.
The input function is an unreliable tool. For
yourself, the author of the program, problems with
input are easily solved. For someone else, the
vagaries of what is legal and how Python responds to things that are not
legal can be frustrating. In Chapter 17, Exceptions, we'll
add some sophistication that will solve some of these problems.
The basic assignment statement does more than assign the result of a single expression to a single variable. The assignment satement also copes nicely with assigning multiple variables at one time. The left and right side must have the same number of elements. For example, the following script has several examples of multiple assignment.
Example 6.7. line.py
#!/usr/bin/env python # Compute line between two points. x1,y1 = 2,3 # point one x2,y2 = 6,8 # point two m,b = float(y1-y2)/(x1-x2), y1-float(y1-y2)/(x1-x2)*x1 print "y=",m,"*x+",b
When we run this program, we get the following output
MacBook-3:Examples slott$./line.pyy = 1.25 *x+ 0.5$
We set variables x1, y1,
x2 and y2. Then we computed
m and b from those four variables.
Then we printed the m and b.
The basic rule is that Python evaluates the entire right-hand side of the = statement. Then it matches values with destinations on the left-hand side. If the lists are different lengths, an exception is raised and the program stops.
Because of the complete evaluation of the right-hand side, the following construct works nicely to swap to variables. This is often quite a bit more complicated in other languages.
a,b = 1,4 b,a = a,b print a,b
We'll return to this in Chapter 13, Tuples, where we'll see additional uses for this feature.
An assignment statement creates or locates a variable and then assigns a new object to the variable. This change in state is how our program advances from beginning to termination. Python also provides a mechanism for removing variables, the del statement.
The del statement looks like this:
del 〈object,...〉
Each object is any kind of Python object.
Usually these are variables, but they can be functions, modules,
classes.
The del statement works by unbinding the name, removing it from the set of names known to the Python interpreter. If this variable was the last remaining reference to an object, the object will be removed from memory. If, on the other hand, other variables still refer to this object, the object won't be deleted.
The del statement is typically used only in rare, specialized cases. Ordinary namespace management and garbage collection are generally sufficient for most purposes.
When we first looked at interactive Python in the section called “Command-Line Interaction” we noted that Python executes assignment statements silently, but prints the results of an expression statement. Consider the following example.
>>>pi=355/113.0>>>area=pi*2.2**2>>>area15.205309734513278
The first two inputs are complete statements, so there is no response. The third input is just an expression, so there is a response.
It isn't obvious, but the value assigned to pi
isn't correct. Because we didn't see anything displayed, we didn't get any
feedback from our computation of pi.
Python, however, has a handy way to help us. When we type a simple
expression in interactive Python, it secretly assigns the result to a
temporary variable named _. This isn't a part of
scripting, but is a handy feature of an interactive session.
This comes in handy when exploring something rather complex.
Consider this interactive session. We evaluate a couple of expressions,
each of which is implicitly assigned to _. We can then
save the value of _ in a second variable with an
easier-to-remember name, like pi or
area.
>>>335/113.02.9646017699115044>>>355/113.03.1415929203539825>>>pi=_>>>pi*2.2**215.205309734513278>>>area=_
Note that we created a floating point object (2.964...), and Python
secretly assigned this object to _. Then, we computed a
new floating point object (3.141...), which Python assigned to
_. What happened to the first float, 2.964...? Python
garbage-collected this object, removing it from memory.
The second float that we created (3.141) was assigned to
_. We then assigned it to pi, also,
giving us two references to the object. When we computed another
floating-point value (15.205...), this was assigned to
_. Does this mean our second float, 3.141... was
garbage collected? No, it wasn't garbage collected; it was still
referenced by the variable pi.
Extend Previous Exercises. Rework the exercises in the section called “Numeric Types and Expressions”.
Each of the previous exercises can be rewritten to use variables instead of expressions using only constants. For example, if you want to tackle the Fahrenheit to Celsius problem, you might write something like this:
#!/usr/bib/env python # Convert 8 C to F C=8 F=32+C*float(9/5) print "celsius",C,"fahrenheit",F
You'll want to rewrite these exercises using variables to get ready to add input functions.
State Change. Is it true that all programs simply establish a state?
It can argued that a controller for a device (like a toaster or a cruise control) simply maintains a steady state. The notion of state change as a program moves toward completion doesn't apply because the software is always on. Is this the case, or does the software controlling a device have internal state changes?
For example, consider a toaster with a thermostat, a “browness” sensor and a single heating element. What are the inputs? What are the outputs? Are there internal states while the toaster is making toast?
Refer back to the exercises in the section called “Numeric Types and Expressions” for formulas and other details. Each of these can be rewritten to use variables and an input conversion. For example, if you want to tackle the Fahrenheit to Celsius problem, you might write something like this:
C = input('Celsius: ')
F = 32+C*float(9/5)
print "celsius",C,"fahrenheit",F
Stock Value. Input the number of shares, dollar price and number of 8th's. From these three inputs, compute the total dollar value of the block of stock.
Convert from °C to °F. Write a short program that will input °C and output °F. A second program will input °F and output °C.
Periodic Payment. Input the principal, annual percentage rate and number of payments. Compute the monthly payment. Be sure to divide rate by 12 and multiple payments by 12.
Surface Air Consumption Rate. Write a short program will input the starting pressure, final pressure, time and maximum depth. Compute and print the SACR.
A second program will input a SACR, starting pressure, final pressure and depth. It will print the time at that depth, and the time at 10 feet more depth.
Wind Chill. Input a temperature and a wind speed. Output the wind chill.
Force from a Sail. Input the height of the sail and the length. The surface area is 1/2×h×l. For a wind speed of 25 MPH, compute the force on the sail. Small boat sails are 25-35 feet high and 6-10 feet long.
Spaces are used sparingly in Python. It is common to put spaces around the assignment operator. The recommended style is
c = (f-32)*5/9
Do not take great pains to line up assignment operators vertically. The following has too much space, and is hard to read, even though it is fussily aligned.
a = 12 b = a*math.log(a) aVeryLongVariable = 26 d = 13
This is considered poor form because Python takes a lot of its look from natural languages and mathematics. This kind of horizontal whitespace is hard to follow: it can get difficult to be sure which expression lines up with which variable. Python programs are meant to be reasonably compact, more like reading a short narrative paragraph or short mathematical formula than reading a page-sized UML diagram.
Variable names are often given as mixedCase;
variable names typically begin with lower-case letters. The
lower_case_with_underscores style is also used, but is
less popular.
In addition, the following special forms using leading or trailing underscores are recognized:
single_trailing_underscore_: used to avoid
conflicts with Python keywords. For example: print_ =
42
__double_leading_and_trailing_underscore__:
used for special objects or attributes, e.g.
__init__, __dict__ or
__file__. These names are reserved; do not use
names like these in your programs unless you specifically mean a
particular built-in feature of Python.
Table of Contents
The elements of Python we've seen so far give us some powerful capabilities. We can write programs that implement a wide variety of requirements. State change is not always as simple as the examples we've seen in Chapter 6, Variables, Assignment and Input. When we run a script, all of the statements are executed unconditionally. Our programs can't handle alternatives or conditions. The other thing we can't do is write programs which do their processing “for all” pieces of data. For example, when we compute an average, we compute a sum for all of the values.
Python provides decision-making mechanisms similar to other programming languages. In the section called “Truth and Logic” we'll look at truth, logic and the logic operators. The exercises that follow examine some subtleties of Python's evaluation rules. In the section called “Comparisons” we'll look at the comparison operators. Then, the section called “Conditional Processing: the if Statement” describes the if statement. In the section called “The assert Statement” we'll introduce a handy diagnostic tool, the assert statement.
In the next chapter, Chapter 8, Looping, we'll look at looping constructs.
Many times the exact change in state that our program needs to make
depends on a condition. A condition is a Boolean expression; an expression
that is either True or False.
Generally conditions are on comparisons among variables using the
comparison operations.
We'll look at the essential definitions of truth, the logic operations and the comparison operations. This will allow us to build conditions.
Python represents truth and falsity in a variety of ways.
False. Also 0, the special value None,
zero-length strings "", zero-length lists
[], zero-length tuples (),
empty mappings {} are all treated as
False.
True. Anything else that is not equivalent to
False.
We try to avoid depending on relatively obscure rules for
determining True vs. False. We
prefer to use the two explicit keywords, True and
False. Note that a previous version of Python didn't
have the boolean literals, and some older open-source programs will
define these values.
Python provides a factory function to collapse these various forms of truth into one of the two explicit boolean objects.
bool (object) →
booleanReturns True when the argument
object is one the values equivalent to
truth, False otherwise.
Python provides three basic logic operators that work on this
Boolean domain. Note that this Boolean domain, with just two values,
True and False, and these three
operators form a complete algebraic system, sometimes called Boolean
algebra, after the mathemetician George Boole. The operators supported
by Python are not, and and
or. We can fully define these operators with rule
statements or truth tables.
This truth table shows the evaluation of not
x for both vales of
x.
print "x", "not x" print True, not True print False, not False
| x | not x |
|---|---|
| True | False |
| False | True |
This table shows the evaluation of
x and
y for all combination of
True and False.
print "x", "y", "x and y" print True, True, True and True print True, False, True and False print False, True, False and True print False, False, False and False
| x | y | x and y |
|---|---|---|
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
An important feature of and is that it does not
evaluate all of its parameters before it is applied. If the left-hand
side is False or one of the equivalent values, the
right-hand side is not evaluated, and the left-hand value is returned.
We'll look at some examples of this later.
For now, you can try things like the following.
print False and 23 print 23 and False
This will show you that the first false value is what Python returns for and.
This table shows the evaluation of
x or
y for all combination of
True and False.
| x | y | x or y |
|---|---|---|
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
Parallel with the and operator,
or does not evaluate the right-hand parameter if the
left-hand side is True or one of the equivalent
values.
As a final note, and is a high priority
operator (analogous to multiplication) and or is
lower priority (analogous to addition). When evaluating expressions like
a or b and c, the and operation is
evaluated first, followed by the or operation.
Logic Short-Cuts. We have several versions of false: False, 0, None, '', (), [] and {}. We'll cover all of the more advanced versions of false in Part II, “Data Structures”. For each of the following, work out the value according to the truth tables and the evaluation rules. Since each truth or false value is unique, we can see which part of the expression was evaluated.
False and None 0 and None or () and [] True and None or () and [] 0 or None and () or [] True or None and () or [] 1 or None and 'a' or 'b' We'll look at the basic comparison operators. We'll also look at the partial evaluation rules of the logic operators to show how we can build more useful expressions. Finally, we'll look at floating-point equality tests, which are sometimes done incorrectly.
We compare values with the comparison operators. These correspond to the mathematical functions of <, ≤, >, ≥, = and ≠. Conditional expressions are often built using the Python comparison operators: <, <=, >, >=, == and != for less than, less than or equal to, greater than, greater than or equal to, equal to and not equal to.
>>>p1=22./7.>>>p2=355/113.>>>p13.1428571428571428>>>p23.1415929203539825>>>p1 < p2False>>>p1 >= p2True
When applying a comparison operator, we see a number of steps.
Evaluate both argument values.
Apply the comparison to create a boolean result.
Convert both parameters to the same type. Numbers are converted to progressively longer types: plain integer to long integer to float to complex.
Do the comparison.
Return True or False.
We call out these three steps explicitly because there are some subtleties in comparison among unlike types of data; we'll come to this later when we cover sequences, mappings and classes in Part II, “Data Structures”. Generally, it doesn't make sense to compare unlike types of data. After all, you can't ask "Which is larger, the Empire State Building or the color green?"
Comparisons can be combined in Python, unlike most other
programming languages. We can ask: 0 <= a < 6 which
has the usual mathematical meaning. We're not forced to use the longer
form: 0 <= a and a < 6 .
>>>3 < p1 < 3.2True>>>3 < p1 and p1 < 3.2True
This is useful when a is actually some complex
expression that we'd rather not repeat.
Also note that the preceding example had a mixture of integers and floating-point numbers. The integers were coerced to floating-point in order to evaluate the expressions.
We can combine the logic operators, comparisons and math. This allows us to use comparisons and logic to prevent common mathematical blunders like attempting to divide by zero, or attempting to take the square root of a negative number.
For example, let's start with this program that will figure the average of 95, 125 and 132.
sum = 95 + 125 + 132 count = 3 average = float(sum)/count print average
Initially, we set the variables sum and
count. Then we compute the average
using sum and count.
Assume that the statement that computes the average
(average=...), is part of a long and complex program.
Sometimes that long program will try to compute the average of no
numbers at all. This has the same effect as the following short
example.
sum, count = 0, 0 average = float(sum)/count print average
In the rare case that we have no numbers to average we don't want to crash when we foolishly attempt to divide by zero. We'd prefer to have some more graceful behavior.
Recall from the section called “Truth and Logic” that the
and operator doesn't evaluate the right-hand side
unless the left-hand side is True. Stated the other
way, the and operator only
evaluates the right side if the left side is True. We
can guard the division like this:
average = count != 0 and sum/count print average
This is an example that can simplify certain kinds of complex
processing. If the count is non-zero, the left side is true and the
right side must be checked. If the count is zero, the left side is
False, the result of the complete
and operation is False.
This is a consequence of the meaning of the word
and. The expression a and b
means that a is true as well as b
is true. If a is false, the value of
b doesn't really matter, since the whole expression
is clearly false. A similar analysis holds for the word
or. The expression a or b
means that one of the two is true; it also means that neither of the two
is false. If a is true, then the value of
b doesn't change the truth of the whole
expression.
The statement “It's cold and rainy” is completely false when it is warm; rain doesn't matter to falsifying the whole statement. Similarly, “I'm stopping for coffee or a newspaper” is true if I've stopped for coffee, irrespective of whether or not I stop for a newspaper.
Exact equality between floating-point numbers is a dangerous concept. After a lengthy computation, round-off errors in floating point numbers may have infinitesimally small differences. The answers are close enough to equal for all practical purposes, but every single one of the 64 bits may not be identical.
The following technique is the appropriate way to do floating point comparisons.
abs(a-b)<0.0001
Rather than ask if the two floating point values are the same, we ask if they're close enough to be considered the same. For example, run the following tiny program.
Example 7.1. floatequal.py
#!/usr/bin/env python # Are two floating point values really completely equal? a,b = 1/3.0, .1/.3 print a,b,a==b print abs(a-b)<0.00001
When we run this program, we get the following output
$python floatequal.py0.333333333333 0.333333333333 FalseTrue$
The two values appear the same when printed. Yet, on most
platforms, the == test returns
False. They are not precisely the same. This is a
consequence of representing real numbers with only a finite amount of
binary precision. Certain repeating decimals get truncated, and these
truncation errors accumulate in our calculations.
There are ways to avoid this problem; one part of this avoidance is to do the algebra necessary to postpone doing division operations. Division introduces the largest number erroneous bits onto the trailing edge of our numbers. The other part of avoiding the problem is never to compare floating point numbers for exact equality.
Many times the program's exact change in state depends on a condition. Conditional processing is done by setting statements apart in suites with conditions attached to the suites. The Python syntax for this is an if statement.
The basic form of an if statement provides a condition and a suite of statements that are executed when the condition is true. It looks like this:
if expression : suite
The suite is an indented block of
statements. Any statement is allowed in the block, including indented
if statements. You can use either tabs or spaces for
indentation. The usual style is four spaces.
This is our first compound statement. See Python Syntax Rules for some additional guidance on syntax for compound statements.
The if statement evaluates the condition
expression first. When the result is
True, the suite of
statements is executed. Otherwise the suite is skipped.
For example, if two dice show a total of 7 or 11, the throw is a winner.
d1 and d2 are two dice
if d1+d2 == 7 or d1+d2 == 11:
print "winner", d1+d2
Here we have a typically complex expression. The
or operator evaluates the left side first. Python
evaluates and applies the high-precendence arithmetic operator before
the lower-precendence comparison operator. If the left side is true
(d1+d2 is 7), the
or expression is true, and the suite is executed. If
the left side is false, then the right side is evaluated. If it is true
(d1+d2 is 11), the
or expression is true, and the suite is executed.
Otherwise, the suite is skipped.
Often there are several conditions that need to be handled. This is done by adding elif clauses. This is short for “else-if”. We can add an unlimited number of elif clauses. The elif clause has almost the same syntax as the if clause.
elif expression : suite
Here is a somewhat more complete rule for the come out roll in a game of craps:
result= None
if d1+d2 == 7 or d1+d2 == 11:
result= "winner"
elif d1+d2 == 2 or d1+d2 == 3 or d1+d2 == 12:
result= "loser"
print result
First, we checked the condition for winning; if the first condition is true, the first suite is executed and the entire if statement is complete. If the first condition is false, then the second condition is tested. If that condition is true, the second suite is executed, and the entire if statement is complete. If neither condition is true, the if statement has no effect.
Python also gives us the capability to put a “catch-all” suite at the end for all other conditions. This is done by adding an else clause. The else clause has the following syntax.
else: suite
Here's the complete come-out roll rule, assuming two values
d1 and d2.
point= None
if d1+d2 == 7 or d1+d2 == 11:
print "winner"
elif d1+d2 == 2 or d1+d2 == 3 or d1+d2 == 12:
print "loser"
else:
point= d1+d2
print "point is", point
Here, we use the else: suite to handle all of the other possible rolls. There are six different values (4, 5, 6, 8, 9, or 10), a tedious typing exercise if done using or. We summarize this with the else: clause.
While handy in one respect, this else: clause is also dangerous. By not explicitly stating the condition, it is possible to overlook simple logic errors.
Consider the following complete if statement that checks for a winner on a field bet. A field bet wins on 2, 3, 4, 9, 10, 11 or 12. The payout odds are different on 2 and 12.
outcome= 0
if d1+d2 == 2 or d1+d2 == 12:
outcome= 2
print "field pays 2:1"
elif d1+d2==4 or d1+d2==9 or d1+d2==10 or d1+d2==11:
outcome= 1
print "field pays even money"
else:
outcome= -1
print "field loses"
Here we test for 2 and 12 in the first clause; we test for 4, 9, 10 and 11 in the second. It's not obvious that a roll of 3 is missing from the even money pay out. This fragment incorrectly treats 3, 5, 6, 7 and 8 alike in the else:. While the else: clause is used commonly as a catch-all, a more proper use for else: is to raise an exception because a condition was not matched by any of the if or elif clauses.
The pass statement does nothing. Sometimes we need a placeholder to fill the syntactic requirements of a compound statement. We use the pass statement to fill in the required suite of statements.
The syntax is trivial.
pass
Here's an example of using the pass statement.
if n%2 == 0:
pass # Ignore even values
else:
count += 1 # Count the odd valuesYes, technically, we can invert the logic in the if-clause. However, sometimes it is more clear to provide the explicit "do nothing" than to determine the inverse of the condition in the if statement.
As programs grow and evolve, having a pass statement can be a handy reminder of places where a program can be expanded.
An assertion is a condition that we're claiming should be true at this point in the program. Typically, it summarizes the state of the program's variables. Assertions can help explain the relationships among variables, review what has happened so far in the program, and show that if statements and for or while loops have the desired effect.
When a program is correct, all of the assertions are true no matter what inputs are provided. When a program has an error, at least one assertion winds up false for some combination of inputs.
Python directly supports assertions through an assert statement. There are two forms:
assert condition
assert 〈condition〉 〈 ,
expression〉
If the condition is
False, the program is in error; this statement raises
an AssertionError exception. If the
condition is True, the
program is correct, this statement does nothing more.
If the second form of the statement is used, and an
expression is given, an exception is raised
using the value of the expression. We'll cover exceptions in detail in
Chapter 17, Exceptions. If the expression is a string, it
becomes an the value associated with the
AssertionError exception.
There is an even more advanced feature of the
assert statement. If the expression evaluates to a
class, that class is used instead of
AssertionError. This is not widely used,
and depends on elements of the language we haven't covered yet.
Here's a typical example:
max= 0 if a < b: max= b if b < a: max= a assert (max == a or max == b) and max >= a and max >= b
If the assertion condition is true, the program continues. If the
assertion condition is false, the program raises an
AssertionError exception and stops, showing
the line where the problem was found.
Run this program with a equal to
b and not equal to zero; it will raise the
AssertionError exception. Clearly, the
if statements don't set max to the
largest of a and b when
a = b. There is a problem in the
if statements, and the presence of the problem is
revealed by the assertion.
There are situations where an expression involves a simple condition and a full-sized if statement is distracting syntatic overkill. Python has a handy logic operator that evalutes a condition, then returns either of two values depending on that condition.
Most arithmetic and logic operators have either one or two values.
An operation that applies to a single value is called
unary. For example -a and
abs(b) are examples of unary operations: unary negation and
unary absolute value. An operation that applies to two values is called
binary. For example, a*b shows the binary multiplication
operator.
The if-else operator trinary. It involves a conditional expression
and two alternative expressions. Consequently, it doesn't use a single
special character, but uses two keywords: if and
else.
The basic form of the operator is
. Python evaluates the
condition first. If the condition is expression if
condition else
expressionTrue, then the
left-hand expression is evaluated, and that's the value of the operation.
If the condition is False, then the else expression
is evaluated, and that's the value of the operation.
Here are a couple of examples.
average = sum/count if count != 0 else None
oddSum = oddSum + ( n if n % 2 == 1 else 0 )
The intent is to have an English-like reading of the statement. "The average is the sum divided by the count if the count is non-zero; otherwise the average is None".
The wordy alterative to the first example is the following.
if count != 0:
average= sum/count
else:
average= None
This seems like three extra lines of code to prevent an error in the rare situation of there being no values to average.
Similarly, the wordy version of the second example is the following:
if n % 2 == 0:
pass
else:
oddSum = oddSum + nFor this second example, the original statement registered our intent very clearly: we were summing the odd values. The long-winded if-statement tends to obscure our goal by making it just one branch of the if-statement.
Develop an “or-guard”. In the example above we showed the “and-guard” pattern:
average = count != 0 and float(sum)/count
Develop a similar technique using or.
Compare this with the if-else operator.
Come Out Win. Assume d1 and d2 have
the numbers on two dice. Assume this is the come out roll in Craps.
Write the expression for winning (7 or 11). Write the expression for
losing (2, 3 or 12). Write the expression for a point (4, 5, 6, 8, 9
or 10).
Field Win. Assume d1 and d2 have
the numbers on 2 dice. The field pays on 2, 3, 4, 9, 10, 11 or 12.
Actually there are two conditions: 2 and 12 pay at one set of odds
(2:1) and the other 5 numbers pay at even money. Write two two
conditions under which the field pays.
Hardways. Assume d1 and d2 have
the numbers on 2 dice. A hardways proposition is 4, 6, 8, or 10 with
both dice having the same value. It's the hard way to get the
number. A hard 4, for instance is d1+d2 == 4 and d1 ==
d2. An easy 4 is d1+d2 == 4 and d1 != d2.
You win a hardways bet if you get the number the hard way. You lose if you get the number the easy way or you get a seven. Write the winning and losing condition for one of the four hard ways bets.
Sort Three Numbers. This is an exercise in constructing if-statements. Using only simple variables and if statements, you should be able to get this to work; a loop is not needed.
Given 3 numbers (X,
Y, Z), assign
variables x, y,
z so that x ≤
y ≤ z and x,
y, and z are from
X, Y, and
Z. Use only a series of if-statements and
assignment statements.
Hint. You must define the conditions under which you choose
between x←X,
x←Y or
x←Z. You will do a
similar analysis for assigning values to y and
z. Note that your analysis for setting
y will depend on the value set for
x; similarly, your analysis for setting
z will depend on values set for
x and y.
Come Out Roll. Accept d1 and d2 as
input. First, check to see that they are in the proper range for
dice. If not, print a message.
Otherwise, determine the outcome if this is the come out roll. If the sum is 7 or 11, print winner. If the sum is 2, 3 or 12, print loser. Otherwise print the point.
Field Roll. Accept d1 and d2 as
input. First, check to see that they are in the proper range for
dice. If not, print a message.
Otherwise, check for any field bet pay out. A roll of 2 or 12 pays 2:1, print "pays 2"; 3, 4, 9, 10 and 11 pays 1:1, print "pays even"; everything else loses, print "loses"
Harways Roll. Accept d1 and d2 as
input. First, check to see that they are in the proper range for
dice. If not, print a message.
Otherwise, check for a hard ways bet pay out. Hard 4 and 10 pays 7:1; Hard 6 and 8 pay 9:1, easy 4, 6, 8 or 10, or any 7 loses. Everything else, the bet still stands.
Partial Evaluation. This partial evaluation of the and and or operators appears to violate the evaluate-apply principle espoused in The Evaluate-Apply Cycle. Instead of evaluating all parameters, these operators seem to evaluate only the left-hand parameter before they are applied. Is this special case a problem? Can these operators be removed from the language, and replaced with the simple if-statement? What are the consequences of removing the short-circuit logic operators?
Now that we have introduced compound statements, you may need to make an adjustment to your editor. Set your editor to use spaces instead of tabs. Most Python is typed using four spaces instead of the ASCII tab character (^I). Most editors can be set so that when you hit the Tab key on your keyboard, the editor inserts four spaces. IDLE is set up this way by default. A good editor will follow the indents so that once you indent, the next line is automatically indented.
We'll show the spaces explicitly as ␣'s in the following fragment.
if␣a␣>=␣b: ␣␣␣␣m␣=␣a if␣b␣>=␣a: ␣␣␣␣m␣=␣b
This is has typical spacing for a piece of Python programming.
Note that the colon (:) immediately follows the condition. This is the usual format, and is consistent with the way natural languages (like English) are formatted.
These if statements can be collapsed to one-liners, in which case they would look like this:
if␣a␣>=␣b:␣m␣=␣a if␣b␣>=␣a:␣m␣=␣b
It helps to limit your lines to 80 positions or less. You may need
to break long statements with a \at the end of a line. Also,
parenthesized expressions can be continued onto the next line without a \.
Some programmers will put in extra ()'s just to make line breaks
neat.
While spaces are used sparingly, they are always used to set off comparison operators and boolean operators. Other mathmatical operators may or may not be set off with spaces. This makes the comparisons stand out in an if statement or while statement.
if␣b**2-4*a*c␣<␣0: ␣␣␣␣print␣"no␣root"
This shows the space around the comparison, but not the other arithmetic operators.
Table of Contents
The elements of Python we've seen so far give us some powerful capabilities. We can write programs that implement a wide variety of requirements. State change is not always as simple as the examples we've seen in Chapter 6, Variables, Assignment and Input. When we run a script, all of the statements are executed unconditionally. Our programs can't handle alternatives or conditions. The other thing we can't do is write programs which do their processing “for all” pieces of data. For example, when we compute an average, we compute a sum for all of the values.
Python provides iteration (sometimes called looping) similar to other programming languages. In the section called “Iterative Processing: For All and There Exists” we'll describe the for and while statements. This is followed by some of the most interesting and challenging short exercises in this book. We'll add some iteration control in the section called “More Iteration Control: break and continue”, describing the break and continue statements. We'll conclude this chapter with a digression on the correct ways to develop iterative and conditional statements in the section called “A Digression”.
There are two common qualifiers used for logical conditions. These are sometimes called the universal and existential qualifiers. We can call the "for all" and "there exists". We can also call them the "all" and "any" qualifiers.
A program may involve a state that is best described as a “for all” state, where a number of repetitions of some task are required. For example, if we were to write a program to simulate 100 rolls of two dice, the terminating condition for our program would be that we had done the simulation for all 100 rolls.
Similary, we may have a condition that looks for existence of a single example. We might want to know if a file contains a line with "ERROR" in it. In this case, we want to write a program with a terminating condition would be that there exists an error line in the log file.
It turns out that All and Any are logical inverses. We can always rework a "for any" condition to be a "for all" condition. A program that determines if there exists an error line is the same as a program that determines that all lines are not error lines.
Any time we have a “for all” or "for any" condition, we have an iteration: we will be iterating through the set of values, evaluating the condition. We have a choice of two Python statements for expressing this iteration. One is the for statement and the other is the while statement.
The simplest for statement looks like this:
for variable in sequence : suite
The suite is an indented block of
statements. Any statement is allowed in the block, including indented
for statements.
The variable is a variable name. The
suite will be executed iteratively with the
variable set to each of the values in the given
sequence. Typically, the
suite will use the
variable, expecting it to have a distinct value
on each pass.
There are a number of ways of creating the necessary
sequence of values. The most common is to use
the range function to generate a suitable list. We
can also create the list manually, using a sequence display; we'll show
some examples here. We'll return to the details of sequences in Chapter 11, Sequences: Strings, Tuples and Lists.
The range function has 3 forms:
range (x) generates
x distinct values, from 0 to
x-1, incrementing by 1.
range (x,
y) generates
y-x distinct values from
x to y-1, incrementing
by 1.
range (x,
y, i) generates
values from x to y-1,
incrementing by i: [ x,
x+i,
x+2i, ...
x+ki
< y ]
A sequence display looks like this: [
expression, ... ]. It's a list of
expressions, usually simply numbers, separated by commas. The square
brackets are essential for marking a sequence.
This first example creates a sequence of 6 values from 0 to just
before 6. The for statement iterates through the
sequence, assigning each value to the local variable i.
The print statement has an expression that adds one to
i and prints the resulting value. Note that the suite
of statements in the body of the for statement is
simply a print statement, so we can combine it all on
one line.
for i in range(6): print i+1
The second example creates a sequence of 6 values from 1 to just
before 7. The for statement iterates through the
sequence, assigning each value to the local variable j.
The print statement prints the value.
for j in range(1,7):
print j
This example creates a sequence of 36/2=18 values from 1 to just
before 36 stepping by 2. This will be a list of odd values from 1 to 35.
The for statement iterates through the sequence,
assigning each value to the local variable o. The
print statement prints all 18 values.
for o in range(1,36,2):
print o
This example uses an explicit sequence of values. These are all of
the red numbers on a standard roulette wheel. It then iterates through the
sequence, assigning each value to the local variable r.
The print statement prints all 18 values followed by
the word "red".
for r in [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36]:
print r, "red"
Here's a more complex example, showing nested for
statements. This enumerates all the 36 outcomes of rolling two dice. The
outer for statement creates a sequence of 6 values, and
iterates through the sequence, assigning each value to the local variable
d1. For each value of d1, the inner
loop creates a sequence of 6 values, and iterates through that sequence,
assigning each value to d2. The
print statement will be executed 36 times.
for d1 in range(6):
for d2 in range(6):
print d1+1,d2+1,'=',d1+d2+2
Here's the example alluded to earlier, which does 100 simulations of
rolling two dice. The for statement creates the
sequence of 100 values, assigns each value to the local variable
i; note that the suite of statements never actually
uses the value of i. The value of i
marks the state changes until the loop is complete, but isn't used for
anything else.
import random
for i in range(100):
d1= random.randrange(6)+1
d2= random.randrange(6)+1
print d1+d2
There are a number of more advanced forms of the for statement, which we'll cover in the section on sequences in Chapter 11, Sequences: Strings, Tuples and Lists.
The while statement looks like this:
while expression : suite
The suite is an indented block of
statements. Any statement is allowed in the block, including indented
while statements.
As long as the expression is true, the
suite is executed. This allows us to construct
a suite that steps through all of the necessary tasks to reach a
terminating condition. It is important to note that the suite of
statements must include a change to at least one of the variables in the
while expression. When it is
possible to execute the suite of statements without changing any of the
variables in the while
expression, the loop will not terminate.
Let's look at some examples.
t, s = 1, 1
while t != 9:
t, s = t + 2, s + t
The loop is initialized with t and
s each set to 1. We specify that the loop continues
“while t ≠ 9”. In the body of the loop, we
increment t by 2, so that it will be an odd value; we
increment s by t, summing a sequence
of odd values.
When this loop is done, t is 9, and
s is the sum of odd numbers less than 9: 1+3+5+7. Also
note that the while condition depends on
t, so changing t is absolutely
critical in the body of the loop.
Here's a more complex example. This sums 100 dice rolls to compute an average.
s, r = 0, 0
while r != 100:
d1,d2=random.randrange(6)+1,random.randrange(6)+1
s,r = s + d1+d2, r + 1
print s/r
We initialize the loop with s and
r both set to zero. The while
statement specifies that during the loop r will not be
100; when the loop is done, r will be 100. The body of
the loop sets d1 and d2 to random
numbers; it increments s by the sum of those dice, and
it increments r by 1. When the loop is over,
s will be the sum of 100 rolls of two dice. When we
print, s/r we print the average
rolled on two dice. The loop condition depends on r, so
each trip through the loop must update r.
Python offers several statements for more subtle loop control. The point of these statements is to permit two common simplifications of a loop. In each case, these statements can be replaced with if statements; however, those if statement versions might be considered rather complex for expressing some fairly common situations.
The break statement terminates a loop prematurely. This allows a complex condition to terminate a loop. A break statement is always found within if statements within the body of a for or while loop. A break statement is typically used when the terminating condition is too complex to write as an expression in the while clause of a loop. A break statement is also used when a for loop must be abandoned before the end of the sequence has been reached.
The continue statement skips the rest of the loop's suite. Like a break statement, a continue statements is always found within an if statement within a for or while loop. The continue statement is used instead of deeply nested else clauses.
Examples break and continue. Here's an example that has a complex break condition. We are going to see if we get six odd numbers in a row, or spin the roulette wheel 100 times.
We'll look at this in some depth because it pulls a number of features together in one program. This program shows both break and continue constructs. Most programs can actually be simplified by eliminating the break and continue statements. In this case, we didn't simplify, just to show how the statements are used.
Note that we have a two part terminating condition: 100 spins
or six odd numbers in a row. The hundred spins is
relatively easy to define using the range function.
The six odd numbers in a row requires testing and counting and then,
possibly, ending the loop. The overall ending condition for the loop,
then, is the number of spins is 100 or the count of odd numbers in a row
is six.
Example 8.1. sixodd.py
import random
oddCount= 0
for s in range(100):
lastSpin= s
n= random.randrange(38)
# Zero
if n == 0 or n == 37: # treat 37 as 00
oddCount = 0
continue
# Odd
if n%2 == 1:
oddCount += 1
if oddCount == 6: break
continue
# Even
assert n%2 == 0 and 0 < n <= 36
oddCount = 0
print oddCount, lastSpin
![]() | We import the |
![]() | The for statement will assign 100
different values to |
![]() | Note that we save the current value of |
![]() | We'll treat 37 as if it were 00, which is like zero. In
Roulette, these two numbers are neither even nor odd. The
|
![]() | We check the value of |
![]() | We threw in an assert (see the next
section, the section called “The assert Statement”, for more
information) that the spin, |
At the end of the loop, lastSpin is the number of
spins and oddCount is the most recent count of odd
numbers in a row. Either oddCount is six or
lastSpin is 99. When lastSpin is 99,
that means that spins 0 through 99 were examined; there are 100 different
numbers between 0 and 99.
Greatest Common Divisor. The greatest common divisor is the largest number which will evenly divide two other numbers. Examples: GCD( 5, 10 ) = 5, the largest number that evenly divides 5 and 10. GCD( 21, 28 ) = 7, the largest number that divides 21 and 28.
GCD's are used to reduce fractions. Once you have the GCD of the numerator and denominator, they can both be divided by the GCD to reduce the fraction to simplest form. 21/28 reduces to 3/4.
Extracting the Square Root. This is a procedure for approximating the square root. It works by dividing the interval which contains the square root in half. Initially, we know the square root of the number is somewhere between 0 and the number. We locate a value in the middle of this interval and determine of the square root is more or less than this midpoint. We continually divide the intervals in half until we arrive at an interval which is small enough and contains the square root. If the interval is only 0.001 in width, then we have the square root accurate to 0.001
Procedure 8.2. Square Root of a number, n
Two Initial Guesses
g1 ← 0
g2 ← n
At this point, g1×g1 − n ≤ 0 ≤ g2×g2 − n
Loop. Loop until abs(g1×g1 − n)÷n < 0.001
Midpoint. mid ← (g1+g2)÷2
Midpoint Squared vs. Number. sqrt_mid ← mid × mid − number
Which Interval?
if sqrt_mid ≤ 0 then g1 ← mid
if sqrt_mid ≥ 0 then g2 ← mid
if sqrt_mid is zero, mid is the exact answer!
Result. Print g1
Sort Four Numbers. This is a challenging exercise in if-statement construction. For some additional insight, see [Dijkstra76], page 61.
Given 4 numbers (W, X, Y, Z)
Assign variables w, x,
y, z so that
w ≤ x ≤ y ≤
z and w, x,
y, z are from
W, X,
Y, and Z. Do not use an
array. One way to guarantee the second part of the above is to
initialize w, x,
y, z to W,
X, Y,
Z, and then use swapping to rearrange the
variables.
Hint: There are only a limited combination of out-of-order conditions among four variables. You can design a sequence of if statements, each of which fixes one of the out-of-order conditions. This sequence of if statements can be put into a loop. Once all of the out-of-order conditions are fixed, the numbers are in order, the loop can end.
Highest Power of 2. This can be used to determine how many bits are required to represent a number. We want the highest power of 2 which is less than or equal to our target number. For example 64 ≤ 100 < 128. The highest power of 2 ≤ 100 is 26.
Given a number n, find a number p such that 2p ≤ n < 2p+1.
This can be done with only addition and multiplication by 2.
Multiplication by 2, but the way, can be done with the << shift
operator. Do not use the pow function, or even
the ** operator, as these are too slow for our purposes.
Consider using a variable c, which you keep equal to 2p. An initialization might be p←1, c←2. When you increment p by 1, you also double c.
Develop your own loop. This is actually quite challenging, even though the resulting program is tiny. For additional insight, see [Gries81], page 147.
How Much Effort to Produce Software? The following equations are the basic COCOMO estimating model, described in [Boehm81]. The input, K, is the number of 1000's of lines of source, total source lines÷1000.
Where K is the number of 1000's of lines of source, E is effort in staff-months, D is duration in calendar months, S is the average staff size, R is the billing rate, C is the cost in dollars (assuming R $ per hour, and 152 working hours per staff-month).
Evaluate these functions for projects which range in size from 8,000 lines (K=8) to 64,000 lines (K=64) in steps of 8. Produce a table with lines of source, Effort, Duration, Cost and Staff size.
Wind Chill Table. Wind chill is 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. See Wind Chill in the section called “Numeric Types and Expressions” for more information.

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.
Evaluate this for all values of V (wind speed) from 0 to 40 mph in steps of 5, and all values of T (temperature) from -10 to 40 in steps of 5.
Celsius to Fahrenheit Conversion Tables. We'll make two slightly different conversion tables.
For values of Celsius from -20 to +30 in steps of 5, produce the equivalent Fahrenheit temperature. The following formula converts C (Celsius) to F (Fahrenheit).

For values of Fahrenheit from -10 to 100 in steps of 5, produce the equivalent Celsius temperatures. The following formula converts F (Fahrenheit) to C (Celsius).

Dive Planning Table. Given a surface air consumption rate, c, and the starting, s, and final, f, pressure in the air tank, a diver can determine maximum depths and times for a dive. For more information, see Surface Air Consumption Rate in the section called “Numeric Types and Expressions”.
Accept c, s and f from input, then evaluate the following for d from 30 to 120 in steps of 10. Print a table of t and d.
For each diver, c is pretty constant, and can be anywhere from 10 to 20, use 15 for this example. Also, s and f depend on the tank used, typical values are s=2500 and f=500.

Computing π. Each of the following series compute increasingly accurate values of π (3.1415926...)




Computing e. A logarithm is a power of some base. When we use logarithms,
we can effectively multiply numbers using addition, and raise to
powers using multiplication. Two Python built-in functions are
related to this: math.log and
math.exp. Both of these compute what are called
natural logarithms, that is, logarithms where the base is
e. This constant, e, is
available in the math module, and it has the following formal
definition:
For more information on the Σ operator, see the section called “Digression on The Sigma Operator”.
4!=4×3×2×1. By definition, 0! = 1.
If we add up the values 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + ... we get the value of e. Clearly, when we get to about 1/10!, the fraction is so small it doesn't contribute much to the total.
We can do this with two loops, an outer loop to sum up the 1/k!'s, and an inner loop to compute the k!'s.
However, if we have a temporary value of k!, each time through the loop we can multiply the temporary by k, and then add 1/temp to the sum.
You can check your work against math.e ~
2.71828... or math.exp
(1).
Hailstone Numbers. For additional information, see [Banks02].
Start with a small number, n, 1 ≤ n ≤ 30.
There are two transformation rules that we will use:
Perform a loop with these two transformation rules until you get to n = 1. You'll note that when n = 1, you get a repeating sequence of 1, 4, 2, 1, 4, 2, ...
You can test for oddness using the % (remainder) operation. If
n % 2 == 1, the number is odd, otherwise it is
even.
The two interesting facts are the “path length”, the number of steps until you get to 1, and the maximum value found during the process.
Tabulate the path lengths and maximum values for numbers 1..30. You'll need an outer loop that ranges from 1 to 30. You'll need an inner loop to perform the two steps for computing a new n until n == 1; this inner loop will also count the number of steps and accumulate the maximum value seen during the process.
Check: for 27, the path length is 111, and the maximum value is 9232.
As additional syntax, the for and while statements permits an else clause. This is a suite of statements that are executed when the loop terminates normally. This suite is skipped if the loop is terminated by a break statement. The else clause on a loop might be used for some post-loop cleanup. This is so unlike other programming languages, that it is hard to justify using it.
An else clause always raises a small problem when it is used. It's never perfectly clear what conditions lead to execution of an else clause. The condition that applies has to be worked out from context. For instance, in if statements, one explicitly states the exact condition for all of the if and elif clauses. The logical inverse of this condition is assumed as the else condition. It is, unfortunately, left to the person reading the program to work out what this condition actually is.
Similarly, the else clause of a while statement is the basic loop termination condition, with all of the conditions on any break statements removed. The following kind of analysis can be used to work out the condition under which the else clause is executed.
while not BB:
if C1: break
if C2: break
else:
assert BB and not C1 and not C2
assert BB or C1 or C2
Because this analysis can be difficult, it is best to avoid the use of else clauses in loop constructs.
For those new to programming, here's a short digression, adapted from chapter 8 of Edsger Dijkstra's book, A Discipline of Programming [Dijkstra76].
Let's say we need to set a variable, m, to the
larger of two input values, a and b.
We start with a state we could call “m
undefined”. Then we want to execute a statement after which we are
in a state of “(m==a or
m==b) and
m≥a and
m≥b”.
Clearly, we need to choose correctly between two different assignment statements. We need to do either m=a or m=b. How do we make this choice? With a little logic, we can derive the condition by taking each of these statement's effects out of the desired end-state.
For the statement m=a to be the right statement
to use, we show the effect of the statement by replacing
m with the value a, and examining
the end state: (a==a or
a==b) and
a≥a and
a≥b. Removing the parts that are
obviously true, we're left with a≥b.
Therefore, the assignment m=a is only useful when
a≥b.
For the statement m=b to be the right statement
to establish the necessary condition, we do a similar replacement of
b for m and examine the end state:
(b==a or
b==b) and
b≥a and
b≥b. Again, we remove the parts that
are obviously true and we're left with
b≥a. Therefore, the assignment
m=b is only useful when
b≥a.
Each assignment statement can be “guarded” by an appropriate condition.
if a>=b: m=a elif b>=a: m=b
Is the correct statement to set m to the larger
of a or b.
Note that the hard part is establishing the post condition. Once we have that stated correctly, it's relatively easy to figure the basic kind of statement that might make some or all of the post condition true. Then we do a little algebra to fill in any guards or loop conditions to make sure that only the correct statement is executed.
Successful Loop Design. There are several considerations when using the while statement. This list is taken from David Gries', The Science of Programming [Gries81].
While these conditions seem overly complex for something so simple as a loop, many programming problems arise from missing one of them.
Gries recommends putting comments around a loop showing the conditions before and after the loop. Since Python provides the assert statement; this formalizes these comments into actual tests to be sure the program is correct.
Designing a Loop. Let's put a particular loop under the microscope. This is a small
example, but shows all of the steps to loop construction. We want to
find the least power of 2 greater than or equal to some number greater
than 1, call it x. This power of 2 will tell us how
many bits are required to represent x, for
example.
We can state this mathematically as looking for some number,
n, such that
2n-1 <
x ≤ 2n.
This says that if x is a power of 2, for example 64,
we'd find 26. If x is
another number, for example 66, we'd find 26
< 66 ≤ 27, or 64 < 66 ≤ 128.
We can start to sketch our loop already.
assert x > 1 ... initialize ... ... some loop ... assert 2**(n-1) < x <= 2**n
We work out the initialization to make sure that the invariant
condition of the loop is initially true. Since x must
be greater than or equal to 1, we can set n to 1.
21-1=20=1 <
x. This will set things up to satisfy rule 1 and
2.
assert x > 1
n= 1
... some loop ...
assert 2**(n-1) < x <= 2**n
In loops, there must be a condition on the body that is invariant,
and a terminating condition that changes. The terminating condition is
written in the while clause. In this case, it is
invariant (always true) that 2**(n-1) <
x. That means that the other part of our final
condition is the part that changes.
assert x > 1
n= 1
while not ( x <= 2**n ):
n= n + 1
assert 2**(n-1) < x
assert 2**(n-1) < x <= 2**n
The next to last step is to show that when the
while condition is true, there are more than zero trips
through the loop possible. We know that x is finite and
some power of 2 will satisfy this condition. There's some
n such that n-1 < log2
(x) < = n that
limits the trips through the loop.
The final step is to show that each cycle through the loop reduces
the trip count. We can argue that increasing n gets us
closer to the upper bound of log2
(x).
We should add this information on successful termination as comments in our loop.
Table of Contents
The heart of programming is the evaluate-apply cycle, where function arguments are evaluated and then the function is applied to those argument values. We'll review this in the section called “Semantics”.
In the section called “Function Definition: The def and return Statements” we introduce the syntax for defining and using a function. We introduce some of the alternate argument forms available for handling optional parameters in the section called “More Features”. Then, in the section called “Providing Argument Values by Keyword” we show how Python can use keyword parameters as well as positional parameters.
In the section called “Object Method Functions” we will describe how to use method functions as a prelude to Part II, “Data Structures”; real details on method functions are deferred until Chapter 21, Classes.
Further sophistication in how Python handles parameters has to be deferred to the section called “Advanced Parameter Handling For Functions”, as it depends on a knowledge of dictionaries, introduced in Chapter 15, Mappings and Dictionaries.
We'll also defer examination of the yield statement until Chapter 18, Generators and the yield Statement. The yield statement creates a special kind of function, one that is most useful when processing complex data structures, something we'll look at in Part II, “Data Structures”.
A function, in a mathematical sense, is often described as a mapping from domain values to range values. Given a domain value, the function returns the matching range value. If we think of the square root function, it maps a positive number, n, to another number, s, such that s2 = n. If we think of multplication as a function, it maps a pair of values, a and b, to a new value, c, such that c is the product of a and b.
In Python, this narrow definition is somewhat relaxed. Python lets us create functions which do not need a domain value, but create new objects. It also allows us to have functions that don't return values, but instead have some other effect, like reading user input, or creating a directory, or removing a file.
What We Provide. In Python, we create a new function by providing three pieces of information: the name of the function, a list of zero or more variables, called parameters, with the domain of input values, and a suite of statements that creates the output values. This definition is saved for later use. We'll show this first in the section called “Function Definition: The def and return Statements”.
Typically, we create function definitions in script files because we don't want to type them more than once. Almost universally, we import a file with our function definitions so we can use them.
We use a function in an expression by following the function's name
with ()'s. The Python interpreter evaluates the argument
values in the ()'s, then applies the function. We'll show
this second in the section called “Function Use”.
Applying a function means that the interpreter first evaluates all of the argument values, then assigns the argument values to the function parameter variables, and finally evaluates the suite of statements that are the function's body. In this body, any return statements define the resulting range value for the function. For more information on this evaluate-apply cycle, see The Evaluate-Apply Cycle.
Namespaces and Privacy. Note that the parameter variables used in the function definition, as well as any variables in a function are private to that function's suite of statements. This is a consequence of the way Python puts all variables in a namespace. When a function is being evaluated, Python creates a temporary namespace. This namespace is deleted when the function's processing is complete. The namespace associated with application of a function is different from the global namespace, and different from all other function-body namespaces.
While you can change the standard namespace policy (see the section called “The global Statement”,) it generally will do you more harm than good. A function's interface is easiest to understand if it is only the parameters and return values and nothing more. If all other variables are local, they can be safely ignored.
Terminology: argument and parameter. We have to make a firm distinction between an argument value, an object that is created or updated during execution, and the defined parameter variable of a function. The argument is the object used in particular application of a function; it may be referenced by other variables or objects. The parameter is a variable name that is part of the function, and is a local variable within the function body.
We create a function with a def statement. This provides the name, parameters and the suite of statements that creates the function's result.
def name ( 〈parameter...〉 ): suite
The name is the name by which the
function is known. The parameters is a list of
variable names; these names are the local variables to which actual
argument values will be assigned when the function is applied. The
suite (which must be indented) is a block of
statements that computes the value for the function.
The first line of a function is expected to be a document string (generally a triple-quoted string) that provides basic documentation for the function. This is traditionally divided in two sections, a summary section of exactly one line and the detail section. We'll return to this style guide in the section called “Functions Style Notes”.
The return statement specifies the result value of the function. This value will become the result of applying the function to the argument values. This value is sometimes called the effect of the function.
return 〈expression〉
Let's look at a complete, although silly, example.
def odd( spin ):
"""Return true if this spin is odd."""
if spin % 2 == 1:
return True
return False
We name this function odd, and define it to
accept a single parameter, named spin. We provide a
docstring with a short description of the function. In the body of the
function, we test to see if the remainder of spin/2
is 1; if so, we return True. Otherwise, we return
False.
When Python evaluates
odd(n), first it evaluates
n; second, it assigns this argument value to the
local parameter of odd (named
spin); third, it applies odd, the
suite of statements is executed, ending with return 1 or return 0; fourth,
this result returned to the calling statement so that it can finish it's
execution.
We would use this function like this.
s = random.randrange(37)
# 0 <= s <= 36, single-0 roulette
if s == 0:
print "zero"
elif odd(s):
print s, "odd"
else:
print s, "even"
We evaluate a function named random.randrange to create a random
number, s. The if clause handles the
case where s is zero. The first elif
clause evaluates our odd function. To do this
evaluation, Python must set spin to the value of
s and execute the suite of statements that are the body
of odd. The suite of statements will return either
True or False. Since the
if and elif clauses handle zero and
odd cases, all that is left is for s to be even.
"Ordinary" Functions. Functions which follow the classic mathematical definitions map input argument values to a resulting value. These are, perhaps, the most common kind of functions, and don't have a special name. We'll look at prodedure and factory functions which are atypical in that they may lack a result or lack input values.
Procedure Functions. One common kind of function is one that doesn't return a result, but instead carries out some procedure. This function would omit any return statement. Or, if return statements are used to exit from the function, they would have no value to return. Carrying out an action is sometimes termed a side-effect of the function. The primary effect is always the value returned.
Here's an example of a function that doesn't return a value, but carries out a procedure.
def report( spin ):
"""Report the current spin."""
if spin == 0:
print "zero"
return
if odd(spin):
print spin, "odd"
return
print spin, "even"
This function, report, has a parameter named
spin, but doesn't return a value. Here, the
return statements exit the function but don't return
values.
This kind of function would be used as if it was a new Python language statement, for example:
for i in range(10):
report( random.randrange(37) )
Here we execute the report function as if it
was a new kind of statement. We don't evaluate it as part of an
expression.
There's actually no real subtlety to this distinction. Any expression can be used as a Python statement. A function call is an expression, and an expression is a statement. This greatly simplifies Python syntax. The docstring for a function will explain what kind of value the function returns, or if the function doesn't return anything useful.
The simple return statement, by the way, returns
the special value None. This default value means that
you can define your function like report, above, use
it in an expression, and everything works nicely because the function does
return a value.
for i in range(10):
t= report( random.randrange(37) )
print t
You'll see that t is
None.
Factory Functions. Another common form is a function that doesn't take a parameter.
This function is a factory which generates a value, often by accessing
some obscured object. Sometimes this object is encapsulated in a module
or class. In the following example, we'll access the random number
generator encapsulated in the random
module.
def spinWheel():
"""Return a string result from a roulette wheel spin."""
t= random.randrange(38)
if t == 37:
return "00"
return str(t)
This function's evaluate-apply cycle is simplified to just the apply phase. To make 0 (zero) distinct from 00 (double zero), it returns a string instead of a number.
Generators. A generator function contains the yield statement. These functions look like conventional functions, but they have a different purpose in Python. We will examine this in detail in Chapter 18, Generators and the yield Statement.
These functions have a persistent internal processing state; ordinary functions can't keep data around from any previous calls without resorting to global variables. Further, these functions interact with the for statement. Finally, these functions don't make a lot of sense until we've worked with sequences in Chapter 11, Sequences: Strings, Tuples and Lists.
Here's a big example of using the odd,
spinWheel and report
functions.
Example 9.1. functions.py
#!/usr/bin/env python
import random
def odd( spin ):
"""odd(number) -> boolean."""
return spin%2 == 1
def report( spin ):
"""Reports the current spin on standard output. Spin is a String"""
if int(spin) == 0:
print "zero"
return
if odd(int(spin)):
print spin, "odd"
return
print spin, "even"
def spinWheel():
"""Returns a string result from a roulette wheel spin."""
t= random.randrange(38)
if t == 37:
return "00"
return str(t)
for i in range(12):
n= spinWheel()
report( n )
![]() | We've defined a function named |
![]() | The function called |
![]() | The |
![]() | The “main” part of this program is the for loop
at the bottom, which calls For most of our exercises, this free-floating main script is acceptable. When we cover modules, in Part IV, “Components, Modules and Packages”, we'll need to change our approach slightly to something like the following. def main():
for i in range(12):
n= spinWheel()
report( n )
main()
This makes the main operation of the script clear by
packaging it as a function. Then the only free-floating statement
in the script is the call to |
On one hand we have interactive use of the Python interpreter: we type something and the interpreter responds immediately. We can do simple things, but when our statements get too long, this interaction can become a niusance. We introduced this first, in the section called “Command-Line Interaction”.
On the other hand, we have scripted use of the interpreter: we present a file as a finished program to execute. While handy for getting useful results, this isn't the easiest way to get a program to work in the first place. We described this in the section called “Script Mode”.
In between the interactive mode and scripted mode, we have a third operating mode, that we might call hacking mode. The idea is to write most of our script and then exercise portions of our script interactively. In this mode, we'll develop script files, but we'll exercise them in an interactive environment. This is handy for developing and debugging function definitions.
The basic procedure is as follows.
In our favorite editor, write a script with our function definitions. We often leave this editor window open. IDLE, for example, leaves this window open for us to look at.
Open a Python shell. IDLE, for example, always does this for us.
In the Python Shell, import the script file. In IDLE, this is effectively what happens when we run the module with F5.
In the Python Shell, test the function interactively. If it works, we're done.
If the functions in our module didn't work, we return to our editor window, make any changes and save the file.
In the Python Shell, clear out the old definition by restarting the shell. In IDLE, we can force this with F6. This happens automatically when we run the module using F5.
Go back to step 3, to import and test our definitions.
The interactive test results are often saved and put into the
docstring for the file with our function definitions. We usually copy the
contents of the Python Shell window and paste it into our module's or
function's docstring. This record of the testing can be validated using
the doctest module.
Example. Here's the sample function we're developing. If you look carefully, you might see a serious problem. If you don't see the problem, don't worry, we'll find it by doing some debugging.
In IDLE, we created the following file.
Example 9.2. function1.py Initial Version
# Some Function Or Other
def odd( number ):
"""odd(number) -> boolean
Returns True if the given number is odd.
"""
return number % 2 == "1"
We have two windows open: function1.py and Python Shell.
Here's our interactive testing session. In our function1.py window, we hit F5 to run the module. Note the line that shows that the Python interpreter was restarted; forgetting any previous definitions. Then we exercised our function with two examples.
Python 2.5.1 (r251:54863, Oct 5 2007, 21:08:09)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "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
>>> ================================ RESTART ================================
>>>
>>> odd(2)
False
>>> odd(3)
False
Clearly, it doesn't work, since 3 is odd. When we look at the original function, we can see the problem.
The expression number % 2 == "1" should be number
% 2 == 1. We need to fix function1.py. Once
the file is fixed, we need to remove the old stuff from Python, re-import
our function and rerun our test. IDLE does this
for us when we hit F5 to rerun the module. It shows this
with the prominent restart message.
If you are not using IDLE, you will need to restart Python to clear out the old definitions. Python optimizes import operations; if it's seen the module once, it doesn't import it a second time. To remove this memory of which modules have been imported, you will need to restart Python.
Python provides a mechanism for optional parameters. This allows us to create a single function which has several alternative forms. In other languages, like C++ or Java, these are called overloaded functions; they are actually separate function definitions with the same name but different parameter forms. In Python, we can write a single function that accepts several parameter forms.
Python has three mechanisms for dealing with optional parameters and a variable number of parameters. We'll cover the basics of optional parameters in this section. The other mechanisms for dealing with variable numbers of parameters will be deferred until the section called “Advanced Parameter Handling For Functions” because these mechanisms use some more advanced data structures.
Python functions can return multiple values. We'll look at this, also.
One way the we can handle optional parameters is by providing a default value for a parameter. If no argument is supplied for the parameter, the default value is used.
def report( spin, count=1 ):
print spin, count, "times in a row"
This silly function can be used in two ways:
report( n ) report( n, 2 )
The first form provides a default argument of 1 for the
count parameter. The second form has an explicit
argument value of 2 for the count
parameter.
If a parameter has no default value, it is not optional. If a parameter has a default value, it is optional. In order to disambiguate the assignment of arguments to parameters, Python uses a simple rule: all required parameters must be first, all optional parameters must come after the required parameters.
The int function does this. We can say
int("23") to do decimal conversion and
int("23",16) to do hexadecimal conversion. Clearly, the
second argument to int has a default value of
10.
When we look at the Python range function, we
see a more sophisticated version of this.
range (x) is the same as
range (0, x,
1)
range (x,
y) is the same as range
(x, y,
1)
It appears from these examples that the first
parameter is optional. The authors of Python use a pretty slick trick
for this that you can use also. The range function
behaves as though the following function is defined.
def range(x, y=None, z=None):
if y==None:
start, stop, step = 0, x, 1
elif z==None:
start, stop, step = x, y, 1
else:
start, stop, step = x, y, z
Real work is done with start, stop and step
By providing a default of None, the function
can determine whether a value was supplied or not supplied. This allows
for complex default handling within the body of the function.
Conclusion. Python must find a value for all parameters. The basic rule is that the values of parameters are set in the order in which they are declared. Any missing parameters will have their default values assigned. These are called positional parameters, since the position is the rule used for assigning argument values when the function is applied.
If a mandatory parameter (a parameter without a default value) is
missing, this is a basic TypeError. For
example.
When we run this example, we see the following.
$python badcall.pyTraceback (most recent call last): File "badcall.py", line 5, in ? hack(3) TypeError: hack() takes exactly 2 arguments (1 given)$
In addition to supplying argument values by position, Python also permits argument values to be specified by name. Using explicit keywords can make programs much easier to read.
First, we'll define a function with a simple parameter list:
import random
def averageDice( samples=100 ):
"""Return the average of a number of throws of 2 dice."""
s = 0
for i in range(samples):
d1,d2 = random.randrange(6)+1,random.randrange(6)+1
s += d1+d2
return float(s)/float(samples)
Next, we'll show three different kinds of arguments: keyword, positional, and default.
test1 = averageDice( samples=200 ) test2 = averageDice( 300 ) test3 = averageDice()
When the averageDice function is evaluated to
set test1, the keyword form is used. The second call
of the averageDice function uses the positional
form. The final example relies on a default for the parameter.
Conclusion. This gives us a number of variations including positional parameters and keyword parameters, both with and without defaults. Positional parameters work well when there are few parameters and their meaning is obvious. Keyword parameters work best when there are a lot of parameters, especially when there are optional parameters.
Good use of keyword parameters mandates good selection of keywords. Single-letter parameter names or obscure abbreviations do not make keyword parameters helpfully informative.
Here are the rules we've seen so far:
Supply values for all parameters given by name, irrespective of position.
Supply values for all remaining parameters by position; in the
event of duplicates, raise a
TypeError.
Supply defaults for any parameters that have defaults defined;
if any parameters still lack values, raise a
TypeError.
There are still more options available for handling variable numbers of parameters. It's possible for additional positional parameters to be collected into a sequence object. Further, additional keyword parameters can be collected into a dictionary object. We'll get to them when we cover dictionaries in the section called “Advanced Parameter Handling For Functions”.
One common desire among programmers is a feature that allows a
function to return multiple values. Python has some built-in functions
that have this property. For example, divmod
returns the divisor and remainder in division. We could imagine a
function, rollDice that would return two values
showing the faces of two dice.
In Python, it is done by returning a tuple.
We'll wait for Chapter 13, Tuples for complete
information on tuples. The following is a quick
example of how multiple assignment works with functions that return
multiple values.
Example 9.4. rolldice.py
import random
def rollDice():
return ( 1 + random.randrange(6), 1 + random.randrange(6) )
d1,d2=rollDice()
print d1,d2
This shows a function that creates a two-valued
tuple. You'll recall from the section called “Multiple Assignment Statement” that Python is perfectly happy with
multiple expressions on the right side of =, and
multiple destination variables on the left side. This is one reason why
multiple assignment is so handy.
Fast Exponentiation. This is the fastest way to raise a number to an integer power. It requires the fewest multiplies, and does not use logarithms.
Greatest Common Divisor. The greatest common divisor is the largest number which will evenly divide two other numbers. You use this when you reduce fractions. See Greatest Common Divisor in for an alternate example of this exercise's algorithm. This version can be slightly faster than the loop we looked at earlier.
Factorial Function. Factorial of a number n is the number of possible arrangements of 0 through n things. It is computed as the product of the numbers 1 through n. That is, 1×2×3×...×n. We touched on this in Computing e in the section called “Iteration Exercises”. This function defintion can simplify the program we wrote for that exercise.
Fibonacci Series. Fibonacci numbers have a number of interesting mathematical properties. The ratio of adjacent Fibonacci numbers approximates the golden ratio ((1+ √5)/2, about 1.618), used widely in art and architecture.
Ackermann's Function. An especially complex algorithm that computes some really big results. This is a function which is specifically designed to be complex. It cannot easily be rewritten as a simple loop. Further, it produces extremely large results because it describes extremely large exponents.
Compute the Maximum Value of Some Function. Given some integer-valued function
f(x), we want to know what
value of x has the largest value for
f(x) in some interval of
values. For additional insight, see
[Dijkstra76].
Imagine we have an integer function of an integer, call it
f(x). Here are some examples
of this kind of function.
def f1(x): return x
def f2(x): return -5/3*x-3
def f3(x): return -5*x*x+2*x-3
The question we want to answer is what value of
x in some fixed interval returns the largest
value for the given function? In the case of the first example,
def f1(x): return x, the largest value of
f1(x) in the interval 0 ≤
x < 10 occurs when x is
9. What about f3(x) in the
range (-10 ≤ x ≤ 10)
Integration Approximation. This is a simple rectangular rule for finding the area under a curve which is continuous on some closed interval.
We will define some function which we will integrate, call it
f (x). Here are some
examples.
def f1(x): return x*xdef f2(x): return 0.5 * x * xdef f3(x): return exp( x )def f4(x): return 5 * sin( x )When we specify y=f(x), we are specifying two dimensions. The y is given by the function's values. The x dimension is given by some interval. If you draw the function's curve, you put two limits on the x axis, this is one set of boundaries. The space between the curve and the y axis is the other boundary.
The x axis limits are a and b. We subdivide this interval into s rectangles, the width of each is h=(b−a)÷s. We take the function's value at the corner as the average height of the curve over that interval. If the interval is small enough, this is reasonably accurate.
Field Bet Results. In the dice game of Craps, the Field bet in craps is a winner when any of the numbers 2, 3, 4, 9, 10, 11 or 12 are rolled. On 2 and 12 it pays 2:1, on the other number, it pays 1:1.
Define a function win (dice,
num, pays ). If
the value of dice equals
num, then the value of
pays is returned, otherwise 0 is returned. Make
the default for pays a 1, so we don't have to
repeat this value over and over again.
Define a function field
(dice). This will call
win 7 times: once with each of the values for
which the field pays. If the value of dice is a 7, it returns -1
because the bet is a loss. Otherwise it returns 0 because the bet is
unresolved. It would start with
def field( dice ):
win( dice, 2, pays=2 )
win( dice, 3, pays=1 )
...
Create a function roll that creates two
dice values from 1 to 6 and returns their sum. The sum of two dice
will be a value from 2 to 12.
Create a main program that calls roll to
get a dice value, then calls field with the value
that is rolled to get the payout amount. Compute the average of
several hundred experiments.
range Function Keywords. Does the range function permit keywords for supplying argument
values? What are the keywords?
Optional First Argument. Optional parameters must come last, yet range fakes this out
by appearing to have an optional parameter that comes first. The
most common situation is range(5), and having to type
range(0,5) seems rather silly. In this case,
convenience trumps strict adherence to the rules. Is this a good
thing? Is strict adherence to the rules more or less important than
convenience?
We've seen how we can create functions and use those functions in programs and other functions. Python has a related technique called methods or method functions. The functions we've used so far are globally available. A method function, on the other hand, belongs to an object. The object's class defines what methods and what properties the object has.
We'll cover method functions in detail, starting in Chapter 21, Classes. For now, however, some of the Python data types we're going to introduce in Part II, “Data Structures” will use method functions. Rather than cover too many details, we'll focus on general principles of how you use method functions in this section.
The syntax for calling a method function looks like this:
someObject.aMethod (argument list
)
A single . separates the owning object
(someObject) from the method name
(aMethod). Some methods have no arguments, others
have complex arguments.
We glanced at a simple example with complex numbers. The complex conjugate function is actually a method function of the complex number object. The example is in the section called “Complex Numbers”.
In the next chapter, we'll look at various kinds of sequences.
Python defines some generic method functions that apply to any of the
various classes of sequences. The string and
list classes, both of which are special kinds of
sequences, have several methods functions that are unique to strings or
lists.
For example:
>>>"Hi Mom".lower()'hi mom'
Here, we call the lower method function,
which belongs to the string object "Hi Mom".
When we describe modules in Part IV, “Components, Modules and Packages”, we'll cover
module functions. These are functions that are imported with the module.
The array module, for example, has an
array function that creates
array objects. An array
object has several method functions. Additionally, an
array object is a kind of sequence, so it has all
of the methods common to sequences, also.
file objects have an interesting life cycle,
also. A file object is created with a built-in
function, file. A file object has numerous method
functions, many of which have side-effects of reading from and writing to
external files or devices. We'll cover files in Chapter 19, Files, listing most of the methods unique to file
objects.
The suite within a compound statement is typically indented four spaces. It is often best to set your text editor with tab stops every four spaces. This will usually yield the right kind of layout.
We'll show the spaces explicitly as ␣'s in the following fragment.
def␣max(a,␣b): ␣␣␣␣if␣a␣>=␣b: ␣␣␣␣␣␣␣␣m␣=␣a ␣␣␣␣if␣b␣>=␣a: ␣␣␣␣␣␣␣␣m␣=␣b ␣␣␣␣return m
This is has typical spacing for a piece of Python programming.
Also, limit your lines to 80 positions or less. You may need to
break long statements with a \ at the end of a line. Also,
parenthesized expressions can be continued onto the next line without a
\. Some programmers will put in extra ()'s just to make line
breaks neat.
Names. Function names are typically mixedCase.
However, a few important functions were done in
CapWords style with a leading upper case letter.
This can cause confusion with class names, and the recommended style is
a leading lowercase letter for function names.
In some languages, many related functions will all be given a common
prefix. Functions may be called inet_addr,
inet_network, inet_makeaddr,
inet_lnaof, inet_netof,
inet_ntoa, etc. Because Python has classes (covered
in Part III, “Data + Processing = Objects”) and modules (covered in Part IV, “Components, Modules and Packages”), this kind of function-name prefix is not used in
Python programs. The class or module name is the prefix. Look at the
example of math and random
for guidance on this.
Parameter names are also typically mixedCase.
In the event that a parameter or variable name conflicts with a Python
keyword, the name is extended with an _. In the following example, we want
our parameter to be named range, but this conflicts
with the builtin function range. We use a trailing _
to sort this out.
def integrate( aFunction, range_ ):
"""Integrate a function over a range."""
...
Blank lines are used sparingly in a Python file, generally to separate unrelated material. Typicaly, function definitions are separated by single blank lines. A long or complex function might have blank lines within the body. When this is the case, it might be worth considering breaking the function into separate pieces.
Docstrings. The first line of the body of a function is called a docstring. The recommended forms for docstrings are described in Python Extension Proposal (PEP) 257.
Typically, the first line of the docstring is a pithy summary of the function. This may be followed by a blank line and more detailed information. The one-line summary should be a complete sentence.
def fact( n ):
"""fact( number ) -> number
Returns the number of permutations of n things."""
if n == 0: return 1L
return n*fact(n-1L)
def bico( n, r ):
"""bico( number, number ) -> number
Returns the number of combinations of n things
taken in subsets of size r.
Arguments:
n -- size of domain
r -- size of subset
"""
return fact(n)/(fact(r)*fact(n-r))
The docsting can be retrieved with the help
function.
help (object)Type help for interactive help, or
help (object) for help
about object.
Here's an example, based on our fact shown
above.
>>>help(fact)Help on function fact in module __main__: fact(n) fact( number ) -> number Returns the number of permutations of n things.
Table of Contents
We cover some more advanced techniques available in Python in the section called “Returning Multiple Values”. In the section called “Functions and Namespaces” we'll describe some of the internal mechanisms Python uses for storing variables. We'll introduce the global statement in the section called “The global Statement”. We'll include a digression on the two common argument binding mechanisms: call by value and call by reference in the section called “Call By Value and Call By Reference”. Finally, we'll cover some aspects of functions as first-class objects in the section called “Function Objects”.
This is an overview of how Python determines the meaning of a name. We'll omit some details to hit the more important points. For more information, see section 4.1 of the Python Language Reference.
The important issue is that we want variables created in the body of a function to be private to that function. If all variables are global, then each function runs a risk of accidentally disturbing the value of a global variable. In the COBOL programming language (without using separate compilation or any of the moden extensions) all variables are globally declared in the data division, and great care is required to prevent accidental or unintended use of a variable.
To achieve privacy and separation, Python maintains several dictionaries of variables. These dictionaries define the context in which a variable name is understood. Because these dictionaries are used for resolution of variables, which name objects, they are called namespaces. A global namespace is available to all modules that are part of the currently executing Python script. Each module, class, function, lambda, or anonymous block of code given to the exec command has its own private namespace.
Names are resolved using the nested collection of namespaces that define an execution environment. The Python always checks the most-local dictionary first, ending with the global dictionary.
Consider the following script.
def deep( hi, mom ):
do some work
def shallow( hows, things ):
deep( hows, 1 )
deep( things, coffee )
hows="a"
coffee="b"
shallow( hows, coffee )
![]() | This is the main function, it executes in the global
namespace, where two variables are defined, along with two
functions, |
![]() | The |
![]() | The |
Built-in Functions. If you evaluate the function globals, you'll
see the mapping that contains all of the global variables Python knows
about. For these early programs, all of our variables are global.
If you simply evaluate locals, you'll see the
same thing. However, if you call locals from within
the body of a function, you'll be able to see the difference between local
and global variables.
The following example shows the creation of a gobal variable
a, and a global function, q. It
shows the local namespace in effect while the function is executing. In
this local namespace we also have a variable named
a.
>>>a=22.0>>>globals(){'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__d oc__': None, 'a': 22.0}>>>def q( x, y ):...a = x / y...print locals()...>>>locals(){'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'q': <function q at 0x007E5EF0>, '__doc__': None, 'a': 22.0}>>>globals(){'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'q': <function q at 0x007E5EF0>, '__doc__': None, 'a': 22.0}>>>q(22.0,7.0){'a': 3.1428571428571428, 'y': 7.0, 'x': 22.0}>>>
The function vars (context
) accepts a parameter which is the name of a specific local
context: a module, class, or object. It returns the local variables for
that specific context. The local variables are kept in a local variable
named __dict__. The vars function
retrieves this.
The dir (object )
function examines the __dict__ of a specific object to
locate all local variables as well as other features of the object.
Assignment statements, as well as def and class statements, create names in the local dictionary. The del statement removes a name from the local dictionary.
Some Consequences. Since each imported module exists in it's own namespace, all
functions and classes within that module must have their names qualified
by the module name. We saw this when we imported
math and random. To use
the sqrt function, we must say
math.sqrt, providing the module name that is used to
resolve the name sqrt.
This module namespace assures that everything in a module is kept separate from other modules. It makes our programs clear by qualifying the name with the module that defined the name.
The module namespace also allow a module to have relatively global variables. A module, for example, can have variables that are created when the module is imported. In a sense these are global to all the functions and classes in the module. However, because they are only known within the module's namespace, they won't conflict with variables in our program or other modules.
Having to qualify names within a module can become annoying when we are making heavy use of a module. Python has ways to put elements of a module into the global namespace. We'll look at these in Part IV, “Components, Modules and Packages”.
The suite of statements in a function definition executes with a local namespace that is different from the global namespace. This means that all variables created within a function are local to that function. When the suite finishes, these working variables are discarded.
The overall Python session works in the global namespace. Every other context (e.g. within a function's suite), there is a distinct local namespace. Python offers us the global statement to change the namespace search rule.
global name...
The global statement tells Python that the following names are part of the global namespace. The following example shows two functions that share a global variable.
ratePerHour= 45.50
def cost( hours ):
global ratePerHour
return hours * ratePerHour
def laborMaterials( hours, materials ):
return cost(hours) + materials
The global statement has a consequence of tightly coupling pieces of software. This can lead to difficulty in maintenance and enhancement of the program. Classes and modules provide better ways to assemble complex programs.
As a general policy, we discourage use of the global statement.
Beginning programmers can skip this section. This is a digression for experienced C and C++ programmers.
Most programming languages have a formal mechanism for determining if a parameter receives a copy of the argument (call by value) or a reference to the argument object (call by name or call by reference). The distinction is important because programming languages like C++ allow us to provide a reference to a global variable as input to a function and have that global variable updated by the function without an obvious assignment statement.
The following scenario is entirely hypothetical for Python
programmers, but a very real problem for C and C++ programmers. Imagine we
have a function to2, with this kind of definition in
C.
int to2( int *a ) {
/* set parameter a's value to 2 */
*a= 2;
return 0;
}
This function changes the value of the variable a
to 2. This would be termed a side-effect because it
is in addition to any value the function might return normally.
When we do the following in C
int x= 27; int z= to2( &x ); printf( "x=%i, z=%i", x, z );
We get the unpleasant side-effect that our function
to2 has changed the argument variable,
x, and the variable wasn't in an
assignment statement! We merely called a function,
using x as an argument. In C, the
& operator is a hint that a variable might be
changed. Further, the function definition should
contain the keyword const when the reference is
properly read-only. However, these are burdens placed on the programmer to
assure that the program compiles correctly.
Python does not permit this kind of call-by-reference problem in the
first place. The arguments to a function are always references to the
original underlying object, not the variable. In the Python version of the
above example, the variable x is a reference to an
integer object with a value of 27. The parameter variable in the
to2 function is a copy of the reference, and it is
local to the function's scope. The original variable,
x, cannot be changed by the function, and the original
argument object, the integer 27, is immutable, and can't be changed
either.
If an argument value is a mutable object, the parameter is a reference to that object, and the function has access to methods of that object. The methods of the object can be called, but the original object cannot be replaced with a new object.
Programmers intimate with the implementation details behind C know that manipulating a copy of a value directly can be far more efficient than working through references. This is true only when the language has some high-performance data types that would benefit from call by value processing. Unlike C or Java, Python has no data types that benefit from this kind of special case handling. All data elements are passed by reference in a simple, uniform manner.
It also means that, in general, all variable updates must be done explicitly via an assignment statement. This makes variable changes clear.
One interesting consequence of the Python world-view is that a
function is an object of the class function, a
subclass of callable. The common feature that all
callables share is that they have a very simple
interface: they can be called. Other callables
include the built-in functions, generator functions (which have the
yield statement instead of the
return statement) and things called lambdas.
Sometimes we don't want to call and evaluate a function. Sometimes
we want to do other things to or with a function. For example, the various
factory functions (int, long,
float, complex) can be used with
the isinstance function instead of being called to
create a new object.
For example, isinstance(2,int) has a value of
True. It uses the int function,
but doesn't apply the int function.
A function object is created with the def statement. Primarily, we want to evaluate the function objects we create. However, because a function is an object, it has attributes, and it can be manipulated to a limited extent.
From a syntax point of view, a name followed by ()'s is
a function call. You can think of the ()'s as the "call"
operator: they require evaluation of the arguments, then they apply the
function.
name (
arguments )
When we use a function name without ()'s, we are
talking about the function object. There are a
number of manipulations that you might want to do with a function
object.
Call The Function. By far, the most common