We’re going to start coding more sophisticated programs in this session. Be sure to check Appendix C if you get stuck, and be sure to start writing your code in module files. You won’t want to retype some of these exercises from scratch if you make a mistake.
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.
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 the 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.) 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
dictionary.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. 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 an importable module file):
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 + 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 earlier in this chapter. Do you think mixing matching modes is a good idea in general? Can you think of cases where it would be useful anyhow?
>>>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)