PyCDS 04 Functions
PyCDS 04 Functions
Functions
4 Introduction
4.1 Q1: Which of the following statements is false?
a. Experience has shown that the best way to develop and maintain a large
program is to construct it from a small number of large, proven pieces—this
technique is called divide and conquer.
b. Using existing functions as building blocks for creating new programs is a key
aspect of software reusability—it’s also a major benefit of object-oriented
programming.
c. Packaging code as a function allows you to execute it from various locations in
your program just by calling the function, rather than duplicating the possibly
lengthy code.
d. When you change a function’s code, all calls to the function execute the
updated version.
Answer: a. Experience has shown that the best way to develop and
maintain a large program is to construct it from a small number of large,
proven pieces—this technique is called divide and conquer. Actually,
experience has shown that the best way to develop and maintain a large
program is to construct it from smaller, more manageable pieces—this
technique is called divide and conquer.
4 Defining Functions
4.2 Q1: Which of the following statements is false?
a. Each function should perform a single, well-defined task.
b. The following code calls function square twice. We’ve replaced each of the
output values with ???. The first call produces the int value 49 and the second
call produces the int value 6:
In [1]: def square(number):
...: """Calculate the square of number."""
...: return number ** 2
...:
In [2]: square(7)
Out[2]: ???
In [3]: square(2.5)
Out[3]: ???
c. The statements defining a function are written only once, but may be called
“to do their job” from many points in a program and as often as you like.
d. Calling square with a non-numeric argument like 'hello' causes a
TypeError because the exponentiation operator (**) works only with numeric
values.
Answer: b). The following code calls function square twice. We’ve replaced
each of the output values with ???. The first call produces the int value 49
and the second call produces the int value 6:
In [1]: def square(number):
...: """Calculate the square of number."""
...: return number ** 2
...:
In [2]: square(7)
Out[2]: ???
In [3]: square(2.5)
Out[3]: ???
Actually, the second call produces the float value 6.25.
4 Random-Number Generation
4.4 Q1: Which of the following statements is false?
a. You can introduce the element of chance via the Python Standard Library’s
random module.
b. The following code produces 10 random integers in the range 1–6 to simulate
rolling a six-sided die:
import random
d. In the following session, snippets [2] and [5] produce the same results
purely by coincidence:
In [1]: random.seed(32)
c. Python does not have constants, so even though pi and e are real-world
constants, you must not assign new values to them, because that would change
their values.
d. To help distinguish “constants” from other variables, the Python style guide
recommends naming your custom constants with a leading underscore (_) and a
trailing underscore.
Answer: d. To help distinguish "constants" from other variables, the
Python style guide recommends naming your custom constants with a
leading underscore (_) and a trailing underscore. Actually, the Python
style guide recommends naming your custom constants with all capital
letters.
4.9 Q2: Assuming the following function definition, which of the following
statements is false?
def rectangle_area(length=2, width=3):
"""Return a rectangle's area."""
return length * width
a. You specify a default parameter value by following a parameter’s name with
an = and a value.
b. Any parameters with default parameter values must appear in the parameter
list to the right of parameters that do not have defaults.
c. For the following call, the interpreter passes the default parameter value 3 for
the width as if you had called rectangle_area(3, 10):
rectangle_area(10)
d. The following call to rectangle_area has arguments for both length and
width, so IPython- ignores the default parameter values:
rectangle_area(10, 5)
Answer: c. For the following call, the interpreter passes the default
parameter value 3 for the width as if you had called rectangle_area(3,
10):
rectangle_area(10)
Actually, interpreter passes the default parameter value 3 for the width as
if you had called rectangle_area(10, 3).
4 Keyword Arguments
4.10 Q1: Based on the following function definition:
def rectangle_area(length, width):
"""Return a rectangle's area."""
return length * width
Which of the following statements based on this function definition is false?
a. Each keyword argument in a call has the form parametername=value.
b. The following call shows that the order of keyword arguments matters—they
need to match the corresponding parameters’ positions in the function
definition:
rectangle_area(width=5, length=10)
c. In each function call, you must place keyword arguments after a function’s
positional arguments—that is, any arguments for which you do not specify the
parameter name. Such arguments are assigned to the function’s parameters left-
to-right, based on the argument’s positions in the argument list.
d. Keyword arguments can improve the readability of function calls, especially
for functions with many arguments.
Answer: b. The following call shows that the order of keyword arguments
matters—they need to match the corresponding parameters’ positions in
the function definition:
rectangle_area(width=5, length=10)
Actually, the call shows that the order of keyword arguments does not
matter—they do not need to match the corresponding parameters’
positions in the function definition.
4.11 Q2: Based on the following function definition that can receive an arbitrary
number of arguments:
In [1]: def average(*args):
...: return sum(args) / len(args)
...:
which of the following statements is false?
a. The parameter name args is used by convention, but you may use any
identifier.
b. If the function has multiple parameters, the *args parameter must be the
leftmost one.
c. The following session calls average several times confirming that it works
with arbitrary argument lists of different lengths:
In [2]: average(5, 10)
Out[2]: 7.5
In [3]: s.upper()
Out[3]: 'HELLO'
c. After the preceding session, s contains 'HELLO'.
d. All of the above statements are true.
Answer: c. After the preceding session, s contains 'HELLO'. Actually, the
calls to lower and upper do not modify the original string so s still
contains 'Hello'.
4 Scope Rules
4.13 Q1: Which of the following statements is false?
a. Each identifier has a scope that determines where you can use it in your
program. For that portion of the program, the identifier is said to be “in scope.”
b. A local variable’s identifier has local scope. It’s “in scope” only from its
definition to the end of the program. It “goes out of scope” when the function
returns to its caller.
c. A local variable can be used only inside the function that defines it.
d. All of the above statements are correct.
Answer: b. A local variable’s identifier has local scope. It’s “in scope” only
from its definition to the end of the program. It “goes out of scope” when
the function returns to its caller. Actually, a local variable’s identifier has
local scope. It’s “in scope” only from its definition to the end of the
function’s block. It “goes out of scope” when the function returns to its
caller.
c. Identifiers with global scope can be used in a .py file or interactive session
anywhere after they’re defined.
d. All of the above statements are true.
Answer: a. Identifiers defined outside any function (or class) have script
scope—these may include functions, variables and classes. Actually,
identifiers defined outside any function (or class) have global scope—
these may include functions, variables and classes.
In [3]: e
Out[3]: 2.718281828459045
Answer: d. The following session is a safe use of a wildcard import:
In [1]: e = 'hello'
In [3]: e
Out[3]: 2.718281828459045
© Copyright 19922020 by Pearson Education, Inc. All Rights Reserved.
14 Chapter 4: Functions
Actually, this session is a classic example of why you should not use
wildcard imports. Initially, we assign the string 'hello' to a variable
named e. After executing snippet [2] though, the variable e is replaced,
possibly by accident, with the math module’s constant e, representing the
mathematical floating-point value e.
In [3]: stats.mean(grades)
Out[3]: 80.6
b. import…as is frequently used to import Python libraries with convenient
abbreviations, like stats for the statistics module.
c. The numpy module is typically imported with
import numpy as npy
d. Typically, when importing a module, you should use import or import…as
statements, then access the module through the module name or the
abbreviation following the as keyword, respectively. This ensures that you do
not accidentally import an identifier that conflicts with one in your code.
Answer: c. The numpy module is typically imported with
import numpy as npy
Actually, the numpy module is typically imported with
import numpy as np
4 Function-Call Stack
4.16 Q1: Which of the following statements is false?
a. For each function call, the interpreter pushes a stack frame onto the stack.
This entry contains the return location that the called function needs so it can
return control to its caller. When the function finishes executing, the interpreter
pops the function’s stack frame, and control- transfers to the return location
that was popped.
© Copyright 19922020 by Pearson Education, Inc. All Rights Reserved.
16 Chapter 4: Functions
b. The top stack frame always contains the information the currently executing
function needs to return control to its caller.
c. If before a function returns it makes a call to another function, the interpreter
pushes a stack frame for that function call onto the stack. Thus, the return
address required by the newly called function to return to its caller is now on
top of the stack.
d. All of the above statements are true.
Answer: d. All of the above statements are true.
4 Functional-Style Programming
4.17 Q1: Which of the following statements is false?
a. Like other popular languages, such as Java and C#, Python is a purely
functional language.
b. Functional-style programs can be easier to parallelize to get better
performance on today’s multi-core processors.
c. You’ve already used list, string and built-in function range iterators with the
for statement, and several reductions (functions sum, len, min and max).
d. All of the above statements are true.
Answer: a. Like other popular languages, such as Java and C#, Python is a
purely functional language. Actually, like other popular languages, such as
Java and C#, Python is not a purely functional language—rather, it offers
“functional-style” features that help you write code which is less likely to
contain errors, more concise and easier to read, debug and modify.
In [2]: sum(values)
Out[2]: 6
In [4]: values
Out[4]: [1, 2, 3]
d. Functions are objects that you can pass to other functions as data.
Answer: b. Pure functions can have side effects—for example, if you pass a
mutable list to a pure function, the list can contain different values before
and after the function call. Actually, pure functions do not have side effects.
For example, even if you pass a mutable list to a pure function, the list will
contain the same values before and after the function call.
dispersion (that is, spread) there is between the values and the mean.
Actually, the smaller the variance and standard deviation are, the closer
the data values are to the mean and the less overall dispersion (that is,
spread) there is between the values and the mean.