This appendix contains solutions to the exercises that appear at the end of each chapter.
Interaction. Assuming your Python is configured properly, you should participate in an interaction that looks something like this:
%python
copyright information lines... >>>"Hello World!"
'Hello World!' >>> # <Ctrl-D or Ctrl-Z to exit>
Programs. Here’s what your code (i.e., module) file and shell interactions should look like:
%cat module1.py
print 'Hello module world!' %python module1.py
Hello module world!
Modules. The following interaction listing illustrates running a module file by importing it. Remember that you need to reload it to run again without stopping and restarting the interpreter. The bit about moving the file to a different directory and importing it again is a trick question: if Python generates a module1.pyc file in the original directory, it uses that when you import the module, even if the source code file (.py) has been moved to a directory not on Python’s search path. The .pyc file is written automatically if Python has access to the source file’s directory and contains the compiled bytecode version of a module. We look at how this works in more detail in Chapter 5.
%python
>>>import module1
Hello module world! >>>
Scripts. Assuming
your platform supports the #!
trick, your solution
will look like the following (though your #!
line
may need to list another path on your machine):
%cat module1.py
#!/usr/local/bin/python (or #!/usr/bin/env python) print 'Hello module world!' %chmod +x module1.py
%module1.py
Hello module world!
Errors. The
interaction below demonstrates the sort of error messages you get if
you complete this exercise. Really, you’re triggering Python
exceptions; the default exception handling
behavior terminates the running Python program and prints an error
message and stack trace on the screen. The stack trace shows where
you were at in a program when the exception occurred (it’s not
very interesting here, since the exceptions occur at the top level of
the interactive prompt; no function calls were in progress). In Chapter 7, you will see you can catch exceptions using
try
statements and process them arbitrarily;
you’ll also see that Python includes a full-blown source-code
debugger for special error detection requirements. For now, notice
that Python gives meaningful messages when programming errors occur
(instead of crashing silently):
%python
>>>1 / 0
Traceback (innermost last): File "<stdin>", line 1, in ? ZeroDivisionError: integer division or modulo >>> >>>x
Traceback (innermost last): File "<stdin>", line 1, in ? NameError: x
Breaks. When you type this code:
L = [1, 2] L.append(L)
you create a cyclic data-structure in Python. In
Python releases before Version 1.5.1, the Python printer wasn’t
smart enough to detect cycles in objects, and it would print an
unending stream of [1,
2,
[1,
2,
[1,
2,
[1,
2,
and so on, until you hit the break key combination on your machine
(which, technically, raises a keyboard-interrupt exception that
prints a default message at the top level unless you intercept it in
a program). Beginning with Python Version 1.5.1, the printer is
clever enough to detect cycles and prints [[...]]
instead.
The reason for the cycle is subtle and requires information
you’ll gain in Chapter 2. But in short,
assignment in Python always generates references to objects (which
you can think of as implicitly followed pointers). When you run the
first assignment above, the name L
becomes a named
reference to a two-item list object. Now, Python lists are really
arrays of object references, with an append
method
that changes the array in-place by tacking on another object
reference. Here, the append
call adds a reference
to the front of L
at the end of
L
, which leads to the cycle illustrated in Figure 3.1. Believe it or not, cyclic data structures can
sometimes be useful (but not when printed!).