14.9 Part IV Exercises
We're going to start coding more sophisticated
programs in these exercises. Be sure to check solutions in Section B.4, and be sure to start writing your code in
module files. You won't want to retype these
exercises from scratch if you make a mistake.
The basics. At the Python interactive prompt,
write a function that prints its single argument to the screen and
call it interactively, passing a variety of object types: string,
integer, list, dictionary. Then try calling it without passing any
argument. What happens? What happens when you pass two arguments? Arguments. Write a function called
adder in a Python module file. The function
adder should accept two arguments and return the
sum (or concatenation) of its two arguments. Then add code at the
bottom of the file to call the function with a variety of object
types (two strings, two lists, two floating points), and run this
file as a script from the system command line. Do you have to print
the call statement results to see results on your screen? varargs. Generalize the adder
function you wrote in the last exercise to compute the sum of an
arbitrary number of arguments, and change the calls to pass more or
less than two. What type is the return value sum? (Hints: a slice
such as S[:0] returns an empty sequence of the
same type as S, and the type built-in function can
test types; but see the min examples in Chapter 13 for a simpler approach.) What happens if you
pass in arguments of different types? What about passing in
dictionaries? Keywords. Change the adder
function from Exercise 2 to accept and add three arguments:
def adder(good, bad, ugly). Now, provide default
values for each argument and experiment with calling the function
interactively. Try passing one, two, three, and four arguments. Then,
try passing keyword arguments. Does the call adder(ugly=1,
good=2) work? Why? Finally, generalize the new adder to
accept and add an arbitrary number of keyword arguments, much like
Exercise 3, but you'll need to iterate over a
dictionary, not a tuple. (Hint: the dict.keys( )
method returns a list you can step through with a
for or while.) Write a function called copyDict(dict) that copies
its dictionary argument. It should return a new dictionary with all
the items in its argument. Use the dictionary keys
method to iterate (or, in Python 2.2, step over a
dictionary's keys without calling
keys). Copying sequences is easy
(X[:] makes a top-level copy); does this work for
dictionaries too? Write a function called addDict(dict1, dict2) that
computes the union of two dictionaries. It should return a new
dictionary, with all the items in both its arguments (assumed to be
dictionaries). If the same key appears in both arguments, feel free
to pick a value from either. Test your function by writing it in a
file and running the file as a script. What happens if you pass lists
instead of dictionaries? How could you generalize your function to
handle this case too? (Hint: see the type built-in
function used earlier.) Does the order of arguments passed matter? More argument matching examples. First, define the following six
functions (either interactively, or in a module file that can be
imported): def f1(a, b): print a, b # Normal args
def f2(a, *b): print a, b # Positional varargs
def f3(a, **b): print a, b # Keyword varargs
def f4(a, *b, **c): print a, b, c # Mixed modes
def f5(a, b=2, c=3): print a, b, c # Defaults
def f6(a, b=2, *c): print a, b, c # Defaults and positional varargs Now, test the following calls interactively and try to explain each
result; in some cases, you'll probably need to fall
back on the matching algorithm shown in Chapter 13.
Do you think mixing matching modes is a good idea in general? Can you
think of cases where it would be useful? >>> f1(1, 2)
>>> f1(b=2, a=1)
>>> f2(1, 2, 3)
>>> f3(1, x=2, y=3)
>>> f4(1, 2, 3, x=2, y=3)
>>> f5(1)
>>> f5(1, 4)
>>> f6(1)
>>> f6(1, 3, 4) Primes revisited. Recall the code snippet we saw
in Chapter 10, which simplistically determines if a
positive integer is prime: x = y / 2 # For some y > 1
while x > 1:
if y % x == 0: # Remainder
print y, 'has factor', x
break # Skip else
x = x-1
else: # Normal exit
print y, 'is prime' Package this code as a reusable function in a module file, and add
some calls to your function at the bottom of your file. While
you're at it, replace the first
line's / operator with
//, to make it handle floating point numbers too,
and be immune to the "true"
division change planned for the / operator in
Python 3.0 as described in Chapter 4. What can you
do about negatives and 0 and 1? How about speeding this up? Your
outputs should look something like this: 13 is prime
13.0 is prime
15 has factor 5
15.0 has factor 5.0 List comprehensions. Write code to build a new
list containing the square roots of all the numbers in this list:
[2, 4, 9, 16, 25]. Code this as a
for loop first, then as a map
call, and finally as a list comprehension. Use the
sqrt function in the built-in
math module to do the calculation (i.e., import
math, and say math.sqrt(x)). Of
the three, which approach do you like best?
|