This chapter covers
- Surveying Python
- Using built-in data types
- Controlling program flow
- Creating modules
- Using object-oriented programming
The purpose of this chapter is to give you a basic feeling for the syntax, semantics, capabilities, and philosophy of the Python language. It has been designed to provide you with an initial perspective or conceptual framework on which you’ll be able to add details as you encounter them in the rest of the book.
On an initial read, you needn’t be concerned about working through and understanding the details of the code segments. You’ll be doing fine if you pick up a bit of an idea about what is being done. The subsequent chapters of this book will walk you through the specifics of these features and won’t assume prior knowledge. You can always return to this chapter and work through the examples in the appropriate sections as a review after you’ve read the later chapters.
Python has a number of built-in data types such as integers, floats, complex numbers, strings, lists, tuples, dictionaries, and file objects. These can be manipulated using language operators, built-in functions, library functions, or a data type’s own methods.
Programmers can also define their own classes and instantiate their own class instances. These can be manipulated by programmer-defined methods as well as the language operators and built-in functions for which the programmer has defined the appropriate special method attributes.
1 The Python documentation and this book use the term object to refer to instances of any Python data type, not just what many other languages would call class instances. This is because all Python objects are instances of one class or another.
Python provides conditional and iterative control flow through an if-elif-else construct along with while and for loops. It allows function definition with flexible argument-passing options. Exceptions (errors) can be raised using the raise statement and caught and handled using the try-except-else construct.
Variables don’t have to be declared and can have any built-in data type, user-defined object, function, or module assigned to them.
Python has several built-in data types, from scalars like numbers and Booleans, to more complex structures like lists, dictionaries, and files.
Python’s four number types are integers, floats, complex numbers, and Booleans:
- Integers—1, –3, 42, 355, 888888888888888, –7777777777
- Floats—3.0, 31e12, –6e-4
- Complex numbers—3 + 2j, –4- 2j, 4.2 + 6.3j
- Booleans—True, False
You can manipulate them using the arithmetic operators: + (addition), – (subtraction), * (multiplication), / (division), ** (exponentiation), and % (modulus).
The following examples use integers:
Division of integers with / results in a float (new in Python 3.x), and division of integers with // results in truncation. Note that integers are of unlimited size ; they will grow as large as you need them to.
These examples work with floats, which are based on the doubles in C:
>>> x = 4.3 ** 2.4
>>> 3.5e30 * 2.77e45
>>> 1000000001.0 ** 3
Next, the following examples use complex numbers:
Complex numbers consist of both a real element and an imaginary element, suffixed with a j. In the preceding code, variable x is assigned to a complex number . You can obtain its “real” part using the attribute notation x.real.
Several built-in functions can operate on numbers. There are also the library module cmath (which contains functions for complex numbers) and the library module math (which contains functions for the other three types):
Built-in functions are always available and are called using a standard function calling syntax. In the preceding code, round is called with a float as its input argument .
The functions in library modules are made available using the import statement. At , the math library module is imported, and its ceil function is called using attribute notation: module.function(arguments).
The following examples use Booleans:
Python has a powerful built-in list type:
A list can contain a mixture of other types as its elements, including strings, tuples, lists, dictionaries, functions, file objects, and any type of number .
A list can be indexed from its front or back. You can also refer to a subsegment, or slice, of a list using slice notation:
Index from the front using positive indices (starting with 0 as the first element). Index from the back using negative indices (starting with -1 as the last element). Obtain a slice using [m:n] , where m is the inclusive starting point and n is the exclusive ending point (see table 3.1). An [:n] slice starts at its beginning, and an [m:] slice goes to a list’s end.
The size of the list increases or decreases if the new slice is bigger or smaller than the slice it’s replacing .
Some built-in functions (len, max, and min), some operators (in, +, and *), the del statement, and the list methods (append, count, extend, index, insert, pop, remove, reverse, and sort) will operate on lists:
The operators + and * each create a new list, leaving the original unchanged . A list’s methods are called using attribute notation on the list itself: x.method(arguments).
A number of these operations repeat functionality that can be performed with slice notation, but they improve code readability.
Tuples are similar to lists but are immutable—that is, they can’t be modified after they have been created. The operators (in, +, and *) and built-in functions (len, max, and min), operate on them the same way as they do on lists, because none of them modify the original. Index and slice notation work the same way for obtaining elements or slices but can’t be used to add, remove, or replace elements. There are also only two tuple methods: count and index. A major purpose of tuples is for use as keys for dictionaries. They’re also more efficient to use when you don’t need modifiability.
A one-element tuple needs a comma. A tuple, like a list, can contain a mixture of other types as its elements, including strings, tuples, lists, dictionaries, functions, file objects, and any type of number .
>>> x = [1, 2, 3, 4]
(1, 2, 3, 4)
Conversely, a tuple can be converted to a list using the built-in function list:
>>> x = (1, 2, 3, 4)
[1, 2, 3, 4]
String processing is one of Python’s strengths. There are many options for delimiting strings:
"A string in double quotes can contain 'single quote' characters."
'A string in single quotes can contain "double quote" characters.'
'''\This string starts with a tab and ends with a newline character.\n'''
"""This is a triple double quoted string, the only kind that can
contain real newlines."""
Strings can be delimited by single (' '), double (" "), triple single (''' '''), or triple double (""" """) quotations and can contain tab (\t) and newline (\n) characters.
Strings are also immutable. The operators and functions that work with them return new strings derived from the original. The operators (in, +, and *) and built-in functions (len, max, and min) operate on strings as they do on lists and tuples. Index and slice notation works the same for obtaining elements or slices but can’t be used to add, remove, or replace elements.
Strings have several methods to work with their contents, and the re library module also contains functions for working with strings:
The re module provides regular expression functionality. It provides more sophisticated pattern extraction and replacement capability than the string module.
The print function outputs strings. Other Python data types can be easily converted to strings and formatted:
Python’s built-in dictionary data type provides associative array functionality implemented using hash tables. The built-in len function returns the number of key-value pairs in a dictionary. The del statement can be used to delete a key-value pair. As is the case for lists, a number of dictionary methods (clear, copy, get, has_key, items, keys, update, and values) are available.
Keys must be of an immutable type . This includes numbers, strings, and tuples. Values can be any kind of object, including mutable types such as lists and dictionaries. The dictionary method get optionally returns a user-definable value when a key isn’t in a dictionary.
A set in Python is an unordered collection of objects, used in situations where membership and uniqueness in the set are the main things you need to know about that object. You can think of sets as a collection of dictionary keys without any associated values:
You can create a set by using set on a sequence, like a list . When a sequence is made into a set, duplicates are removed . The in keyword is used to check for membership of an object in a set.
The open statement creates a file object. Here the file myfile in the current working directory is being opened in write ("w") mode. After writing two lines to it and closing it , we open the same file again, this time in the read ("r") mode. The os module provides a number of functions for moving around the file system and working with the pathnames of files and directories. Here, we move to another directory . But by referring to the file by an absolute pathname , we are still able to access it.
A number of other input/output capabilities are available. You can use the built-in input function to prompt and obtain a string from the user. The sys library module allows access to stdin, stdout, and stderr. The struct library module provides support for reading and writing files that were generated by or are to be used by C programs. The Pickle library module delivers data persistence through the ability to easily read and write the Python data types to and from files.
Python has a full range of structures to control code execution and program flow, including common branching and looping structures.
Python has several ways of expressing Boolean values; the Boolean constant False, 0, the Python nil value None, and empty values (for example, the empty list [ ] or empty string "") are all taken as False. The Boolean constant True and everything else are considered True.
You can create comparison expressions using the comparison operators (<, <=, ==, >, >=, !=, is, is not, in, not in) and the logical operators (and, not, or), which all return True or False.
The block of code after the first true condition (of an if or an elif) is executed. If none of the conditions is true, the block of code after the else is executed:
The elif and else clauses are optional , and there can be any number of elif clauses. Python uses indentation to delimit blocks . No explicit delimiters such as brackets or braces are necessary. Each block consists of one or more statements separated by newlines. These statements must all be at the same level of indentation.
The output here would be 5 0 10.
The while loop is executed as long as the condition (which here is x > y) is true:
This is a shorthand notation. Here, u and v are assigned a value of 0, x is set to 100, and y obtains a value of 30 . This is the loop block . It’s possible for it to contain break (which ends the loop) and continue statements (which abort the current iteration of the loop).
The output here would be 60 40.
The for loop is simple but powerful because it’s possible to iterate over any iterable type, such as a list or tuple. Unlike in many languages, Python’s for loop iterates over each of the items in a sequence, making it more of a foreach loop. The following loop finds the first occurrence of an integer that is divisible by 7:
x is sequentially assigned each value in the list . If x isn’t an integer, then the rest of this iteration is aborted by the continue statement . Flow control continues with x set to the next item from the list. After the first appropriate integer is found, the loop is ended by the break statement .
The output here would be
found an integer divisible by seven: 49
Python provides flexible mechanisms for passing arguments to functions:
Functions are defined using the def statement . The return statement is what a function uses to return a value. This value can be of any type. If no return statement is encountered, Python’s None value is returned. Function arguments can be entered either by position or by name (keyword). Here z and y are entered by name . Function parameters can be defined with defaults that are used if a function call leaves them out . A special parameter can be defined that will collect all extra positional arguments in a function call into a tuple . Likewise, a special parameter can be defined that will collect all extra keyword arguments in a function call into a dictionary .
Exceptions (errors) can be caught and handled using the try-except-finally-else compound statement. This statement can also catch and handle exceptions you define and raise yourself. Any exception that isn’t caught will cause the program to exit. Listing 3.1 shows basic exception handling.
Here we define our own exception type inheriting from the base Exception type . If an IOError or EmptyFileError occurs during the execution of the statements in the try block, the associated except block is executed . This is where an IOError might be raised . Here we raise the EmptyFileError . The else clause is optional . It’s executed if no exception occurs in the try block (note that in this example, continue statements in the except blocks could have been used instead). The finally clause is optional . It’s executed at the end of the block whether an exception was raised or not.
It’s easy to create your own modules, which can be imported and used in the same way as Python’s built-in library modules. The example in listing 3.2 is a simple module with one function that prompts the user to enter a filename and determines the number of times words occur in this file.
Documentation strings are a standard way of documenting modules, functions, methods, and classes . Comments are anything beginning with a # character . read returns a string containing all the characters in a file , and split returns a list of the words of a string “split out” based on whitespace. You can use a \ to break a long statement across multiple lines . This allows the program to also be run as a script by typing python wo.py at a command line .
If you place a file in one of the directories on the module search path, which can be found in sys.path, then it can be imported like any of the built-in library modules using the import statement:
This function is called using the same attribute syntax as used for library module functions.
>>> import imp
For larger projects, there is a generalization of the module concept called packages. This allows you to easily group a number of modules together in a directory or directory subtree and import and hierarchically refer to them using a package.subpackage.module syntax. This entails little more than the creation of a possibly empty initialization file for each package or subpackage.
Python provides full support for OOP. Listing 3.3 is an example that might be the start of a simple shapes module for a drawing program. It’s intended mainly to serve as reference if you’re already familiar with object-oriented programming. The callout notes relate Python’s syntax and semantics to the standard features found in other languages.
Classes are defined using the class keyword . The instance initializer method (constructor) for a class is always called __init__ . Instance variables x and y are created and initialized here . Methods, like functions, are defined using the def keyword . The first argument of any method is by convention called self. When the method is invoked, self is set to the instance that invoked the method. Class Circle inherits from class Shape . This is similar to but not exactly like a standard class variable . A class must, in its initializer, explicitly call the initializer of its base class . The __str__ method is used by the print function . Other special attribute methods permit operator overloading or are employed by built-in methods such as the length (len) function.
Importing this file makes these classes available:
The initializer is implicitly called, and a circle instance is created . The print function implicitly uses the special __str__ method . Here we see that the move method of Circle’s parent class Shape is available . A method is called using attribute syntax on the object instance: object.method(). The first (self) parameter is set implicitly.
This ends our overview of Python. Don’t worry if some parts were confusing. You need an understanding of only the broad strokes at this point. The chapters in part 2 and part 3 won’t assume prior knowledge of their concepts and will walk you through these features in detail. You can also think of this as an early preview of what your level of knowledge will be when you’re ready to move on to the chapters in part 4. You may find it valuable to return here and work through the appropriate examples as a review after we cover the features in subsequent chapters.
If this chapter was mostly a review for you, or there were only a few features you would like to learn more about, feel free to jump ahead, using the index, the table of contents, or the appendix. You can always slow down if anything catches your eye. You probably should have an understanding of Python to the level that you have no trouble understanding most of this chapter before you move on to the chapters in part 4.