← 学习库 Think Python (2e) · 中英对照 目录

Chapter 3  Functions 第 3 章 函数

本页译自 Think Python 2e(Allen B. Downey)· Chapter 3 Functions。代码块保留英文原文不翻译;正文段段对照,中文块可用右下角按钮隐藏。

3.1 Function calls 3.1 函数调用

In the context of programming, a function is a named sequence of statements that performs a computation. When you define a function, you specify the name and the sequence of statements. Later, you can “call” the function by name. We have already seen one example of a function call:

在编程的语境里,函数是一段具名的语句序列,用来完成某项计算。定义函数时,你要指定它的名字和语句序列。之后,你可以用名字来「调用」这个函数。我们已经见过一个函数调用的例子:
>>> type(32)
<type 'int'>

The name of the function is type. The expression in parentheses is called the argument of the function. The result, for this function, is the type of the argument.

这个函数的名字是 type。括号里的表达式称为函数的实参。对这个函数的调用结果,就是该实参的类型。

It is common to say that a function “takes” an argument and “returns” a result. The result is called the return value.

通常我们说一个函数「接受」一个实参并「返回」一个结果。这个结果称为返回值

3.2 Type conversion functions 3.2 类型转换函数

Python provides built-in functions that convert values from one type to another. The int function takes any value and converts it to an integer, if it can, or complains otherwise:

Python 提供了一些内置函数,用来把值从一种类型转换成另一种类型。int 函数会接收任意值,并尽可能把它转换成整数,否则就报错:
type00009

int can convert floating-point values to integers, but it doesn’t round off; it chops off the fraction part:

int 能把浮点数转换成整数,但它不会做四舍五入,而是直接砍掉小数部分:
type00012

type0 converts integers and strings to floating-point numbers:

type0 把整数和字符串转换成浮点数:
type00015

Finally, int converts its argument to a string:

最后,int 把它的实参转换成一个字符串:
type00018

3.3 Math functions 3.3 数学函数

Python has a math module that provides most of the familiar mathematical functions. A module is a file that contains a collection of related functions.

Python 带有一个 math 模块,提供了大多数常用的数学函数。模块就是一个文件,里面装着一组相关的函数。

Before we can use the module, we have to import it:

在使用这个模块之前,必须先导入它:
type00019

This statement creates a module object named math. If you print the module object, you get some information about it:

这条语句会创建一个名为 math 的模块对象。如果你把这个模块对象打印出来,会看到一些关于它的信息:
type00020

The module object contains the functions and variables defined in the module. To access one of the functions, you have to specify the name of the module and the name of the function, separated by a dot (also known as a period). This format is called dot notation.

模块对象里装着模块中定义的函数和变量。要访问其中的某个函数,必须同时写出模块名和函数名,中间用一个点(也就是句号)隔开。这种写法称为点记号
type00021

The first example uses type0 to compute a signal-to-noise ratio in decibels (assuming that type00023 and type00024 are defined). The math module also provides int, which computes logarithms base e.

第一个例子用 type0 计算以分贝为单位的信噪比(假定 type00028 和 type00029 都已定义)。math 模块还提供 int,用来计算以 e 为底的对数。

The second example finds the sine of type000. The name of the variable is a hint that int and the other trigonometric functions (int, int, etc.) take arguments in radians. To convert from degrees to radians, divide by 360 and multiply by 2 π:

第二个例子求 type000 的正弦。这个变量的名字提示我们,int 以及其它三角函数(intint 等等)接受的实参是以弧度表示的。要把角度转换成弧度,先除以 360,再乘以 2π:
type00040

The expression type000 gets the variable e0 from the math module. The value of this variable is an approximation of π, accurate to about 15 digits.

表达式 type000 从 math 模块中取出变量 e0。这个变量的值是对 π 的近似,精确到大约 15 位数字。

If you know your trigonometry, you can check the previous result by comparing it to the square root of two divided by two:

如果你还记得三角学,可以把它和「根号二除以二」比较,来验证上面的结果:
type00045

3.4 Composition 3.4 组合

So far, we have looked at the elements of a program—variables, expressions, and statements—in isolation, without talking about how to combine them.

到目前为止,我们都是孤立地看待程序的各个组成部分——变量、表达式和语句——还没有讨论如何把它们组合起来。

One of the most useful features of programming languages is their ability to take small building blocks and compose them. For example, the argument of a function can be any kind of expression, including arithmetic operators:

编程语言最有用的特性之一,就是能够把一个个小积木组合起来。例如,函数的实参可以是任何类型的表达式,包括算术运算符:
type00046

And even function calls:

甚至还可以是函数调用:
type00047

Almost anywhere you can put a value, you can put an arbitrary expression, with one exception: the left side of an assignment statement has to be a variable name. Any other expression on the left side is a syntax error (we will see exceptions to this rule later).

几乎在你能放一个值的地方,都可以放任意表达式,只有一个例外:赋值语句的左边必须是一个变量名。左边放其它任何表达式都是语法错误(这个规则的例外我们以后会看到)。
type00048

3.5 Adding new functions 3.5 添加新函数

So far, we have only been using the functions that come with Python, but it is also possible to add new functions. A function definition specifies the name of a new function and the sequence of statements that execute when the function is called.

到目前为止,我们一直只用 Python 自带的函数,但其实也可以添加新函数。函数定义会指定新函数的名字,以及该函数被调用时要执行的语句序列。

Here is an example:

下面是一个例子:
type00049

int is a keyword that indicates that this is a function definition. The name of the function is type00051. The rules for function names are the same as for variable names: letters, numbers and some punctuation marks are legal, but the first character can’t be a number. You can’t use a keyword as the name of a function, and you should avoid having a variable and a function with the same name.

int 是一个关键字,表明这是一个函数定义。函数名叫 type00053。函数名的取名规则和变量名一样:字母、数字以及一些标点符号都是合法的,但第一个字符不能是数字。不能用关键字作函数名,而且应当避免让变量和函数同名。

The empty parentheses after the name indicate that this function doesn’t take any arguments.

名字后面那对空括号表示这个函数不接收任何实参。

The first line of the function definition is called the header; the rest is called the body. The header has to end with a colon and the body has to be indented. By convention, the indentation is always four spaces (see Section 3.14). The body can contain any number of statements.

函数定义的第一行称为函数头,其余部分称为函数体。函数头必须以冒号结尾,函数体必须缩进。按照惯例,缩进总是四个空格(见 3.14 节)。函数体里可以包含任意多条语句。

The strings in the print statements are enclosed in double quotes. Single quotes and double quotes do the same thing; most people use single quotes except in cases like this where a single quote (which is also an apostrophe) appears in the string.

print 语句里的字符串用双引号括起来。单引号和双引号作用相同;大多数人用单引号,除非像这里这样,字符串里本身就出现了单引号(也就是撇号)。

If you type a function definition in interactive mode, the interpreter prints ellipses (...) to let you know that the definition isn’t complete:

如果你在交互模式里输入一个函数定义,解释器会打印省略号(...)来提示你定义还没写完:
type00054

To end the function, you have to enter an empty line (this is not necessary in a script).

要结束这个函数定义,你必须输入一个空行(在脚本里不需要这么做)。

Defining a function creates a variable with the same name.

定义一个函数会创建一个同名的变量。
type00055

The value of type00056 is a function object, which has type type00057.

type00058 的值是一个函数对象,它的类型是 type00059。

The syntax for calling the new function is the same as for built-in functions:

调用这个新函数的语法,和调用内置函数一模一样:
type00060

Once you have defined a function, you can use it inside another function. For example, to repeat the previous refrain, we could write a function called type00061:

一旦定义了函数,就可以在另一个函数里使用它。比如,为了把刚才那段副歌重复一遍,我们可以写一个叫 type00062 的函数:
type00063

And then call type00064:

然后再调用 type00065:
type00066

But that’s not really how the song goes.

不过,这首歌本来可不是这么唱的。

3.6 Definitions and uses 3.6 定义与使用

Pulling together the code fragments from the previous section, the whole program looks like this:

把上一节的代码片段拼到一起,整个程序是这样的:
type00067

This program contains two function definitions: type00068 and type00069. Function definitions get executed just like other statements, but the effect is to create function objects. The statements inside the function do not get executed until the function is called, and the function definition generates no output.

这个程序包含两个函数定义:type00070 和 type00071。函数定义和其它语句一样会被执行,但它的作用是创建函数对象。函数内部的语句要等到函数被调用时才执行,而且函数定义本身不会产生任何输出。

As you might expect, you have to create a function before you can execute it. In other words, the function definition has to be executed before the first time it is called.

正如你所料,必须先创建函数,才能执行它。换句话说,函数定义必须在它被第一次调用之前执行。

Exercise 1

习题 1

Move the last line of this program to the top, so the function call appears before the definitions. Run the program and see what error message you get.

把程序的最后一行移到最上面,让函数调用出现在定义之前。运行程序,看看你会得到什么错误信息。

Exercise 2

习题 2

Move the function call back to the bottom and move the definition of type00072 after the definition of type00073. What happens when you run this program?

把函数调用移回底部,并把 type00074 的定义移到 type00075 的定义之后。运行这个程序会发生什么?

3.7 Flow of execution 3.7 执行流程

In order to ensure that a function is defined before its first use, you have to know the order in which statements are executed, which is called the flow of execution.

为了保证函数在第一次使用前已经被定义,你必须知道语句被执行的先后顺序,这称为执行流程

Execution always begins at the first statement of the program. Statements are executed one at a time, in order from top to bottom.

执行总是从程序的第一条语句开始。语句一条接一条地、从上往下地执行。

Function definitions do not alter the flow of execution of the program, but remember that statements inside the function are not executed until the function is called.

函数定义本身不会改变程序的执行流程,但要记住:函数内部的语句在函数被调用之前都不会执行。

A function call is like a detour in the flow of execution. Instead of going to the next statement, the flow jumps to the body of the function, executes all the statements there, and then comes back to pick up where it left off.

函数调用就像是执行流程中的一个岔路。流程不会去执行下一条语句,而是跳到函数体内,把里面的语句全部执行完,再回到原来离开的地方继续往下走。

That sounds simple enough, until you remember that one function can call another. While in the middle of one function, the program might have to execute the statements in another function. But while executing that new function, the program might have to execute yet another function!

这听起来挺简单,可别忘了:一个函数还能调用另一个函数。正当程序执行到某个函数中间时,它可能又得去执行另一个函数里的语句;而执行那个新函数时,说不定还得再去执行别的函数!

Fortunately, Python is good at keeping track of where it is, so each time a function completes, the program picks up where it left off in the function that called it. When it gets to the end of the program, it terminates.

好在 Python 很擅长记住自己身在何处,所以每完成一个函数,程序就会回到调用它的那个函数里、刚才离开的地方继续。等走到程序的尽头,程序就终止了。

What’s the moral of this sordid tale? When you read a program, you don’t always want to read from top to bottom. Sometimes it makes more sense if you follow the flow of execution.

这番啰嗦的讲述想说明什么?读程序的时候,你不必总是一行行从上读到下。有时候,顺着执行流程去读反而更清楚。

3.8 Parameters and arguments 3.8 形参与实参

Some of the built-in functions we have seen require arguments. For example, when you call type0007 you pass a number as an argument. Some functions take more than one argument: type0007 takes two, the base and the exponent.

我们见过的一些内置函数需要实参。比如,调用 type0007 时要传一个数字作实参。有些函数接收不止一个实参:type0007 要两个,分别是底数和指数。

Inside the function, the arguments are assigned to variables called parameters. Here is an example of a user-defined function that takes an argument:

在函数内部,实参会被赋给一些变量,这些变量称为形参。下面是一个接收实参的用户自定义函数示例:
type00080

This function assigns the argument to a parameter named type0. When the function is called, it prints the value of the parameter (whatever it is) twice.

这个函数把实参赋给一个名为 type0 的形参。函数被调用时,它会把形参的值(无论是什么)打印两遍。

This function works with any value that can be printed.

这个函数对任何一种可打印的值都管用。
type00083

The same rules of composition that apply to built-in functions also apply to user-defined functions, so we can use any kind of expression as an argument for type00084:

适用于内置函数的组合规则,同样适用于用户自定义函数,所以我们可以把任意类型的表达式作为 type00085 的实参:
type00086

The argument is evaluated before the function is called, so in the examples the expressions type00087 and type00088 are only evaluated once.

实参在函数被调用之前先求值,所以在这些例子里,表达式 type00089 和 type00090 都只会被计算一次。

You can also use a variable as an argument:

你也可以用变量作为实参:
type00091

The name of the variable we pass as an argument (type000) has nothing to do with the name of the parameter (type0). It doesn’t matter what the value was called back home (in the caller); here in type00094, we call everybody type0.

我们用作实参的变量名(type000)和形参的名字(type0)毫无关系。这个值的「本名」(在调用者那里叫什么)无关紧要;在 type00098 里,我们管谁都叫 type0。

3.9 Variables and parameters are local 3.9 变量与形参是局部的

When you create a variable inside a function, it is local, which means that it only exists inside the function. For example:

当你在函数内部创建一个变量时,它是局部的,也就是说它只存在于函数内部。例如:
type00100

This function takes two arguments, concatenates them, and prints the result twice. Here is an example that uses it:

这个函数接收两个实参,把它们拼接起来,然后把结果打印两遍。下面是一个使用它的例子:
type00101

When type00102 terminates, the variable int is destroyed. If we try to print it, we get an exception:

type00104 结束时,变量 int 就被销毁了。如果我们试图打印它,就会得到一个异常:
type00106

Parameters are also local. For example, outside type00107, there is no such thing as type0.

形参也是局部的。例如,在 type00109 之外,根本不存在 type0 这个东西。

3.10 Stack diagrams 3.10 栈图

To keep track of which variables can be used where, it is sometimes useful to draw a stack diagram. Like state diagrams, stack diagrams show the value of each variable, but they also show the function each variable belongs to.

为了搞清楚哪些变量能在哪些地方使用,有时画一张栈图很有用。和状态图一样,栈图会显示每个变量的值,但它还显示了每个变量所属的函数。

Each function is represented by a frame. A frame is a box with the name of a function beside it and the parameters and variables of the function inside it. The stack diagram for the previous example is shown in Figure 3.1.

每个函数由一个栈帧表示。栈帧是一个方框,旁边写着函数名,框里装着该函数的形参和变量。上例的栈图如 3.1 图所示。

Figure 3.1: Stack diagram.

图 3.1:栈图。(原书插图未收录)

The frames are arranged in a stack that indicates which function called which, and so on. In this example, type00111 was called by type00112, and type00113 was called by type0011, which is a special name for the topmost frame. When you create a variable outside of any function, it belongs to type0011.

这些栈帧在栈里由下往上排列,表明是谁调用了谁。在这个例子中,type00116 是 type00117 调用的,而 type00118 是 type0011 调用的,type0012 是最顶层栈帧的特称。当你在任何函数之外创建变量时,它属于 type0012。

Each parameter refers to the same value as its corresponding argument. So, type0 has the same value as type0, type0 has the same value as type0, and type0 has the same value as int.

每个形参都和它对应的实参指向同一个值。所以,type0 和 type0 的值相同,type0 和 type0 的值相同,type0 和 int 的值相同。

If an error occurs during a function call, Python prints the name of the function, and the name of the function that called it, and the name of the function that called that, all the way back to type0013.

如果函数调用过程中出错,Python 会打印出函数名、调用它的函数名、以及调用那个函数的函数名,一路回溯到 type0013。

For example, if you try to access int from within type00137, you get a type00138:

例如,如果你在 type00139 内部试图访问 int,就会得到一个 type00141:
type00142

This list of functions is called a traceback. It tells you what program file the error occurred in, and what line, and what functions were executing at the time. It also shows the line of code that caused the error.

这个函数的列表称为回溯。它告诉你错误发生在哪个程序文件、哪一行,以及当时正在执行哪些函数。它还显示出引发错误的那行代码。

The order of the functions in the traceback is the same as the order of the frames in the stack diagram. The function that is currently running is at the bottom.

回溯中函数的顺序,和栈图中栈帧的顺序一致。当前正在运行的函数在最下面。

3.11 Fruitful functions and void functions 3.11 有返回值的函数与无返回值的函数

Some of the functions we are using, such as the math functions, yield results; for lack of a better name, I call them fruitful functions. Other functions, like type00143, perform an action but don’t return a value. They are called void functions.

我们用到的一些函数(比如数学函数)会产生结果;一时找不到更好的名字,我把它们称为有返回值的函数。另一些函数,比如 type00144,执行某个动作却不返回任何值。它们称为无返回值函数

When you call a fruitful function, you almost always want to do something with the result; for example, you might assign it to a variable or use it as part of an expression:

调用有返回值的函数时,你几乎总是想对结果做点什么;比如,把它赋给一个变量,或者当作表达式的一部分来使用:
type00145

When you call a function in interactive mode, Python displays the result:

在交互模式里调用函数时,Python 会显示出结果:
type00146

But in a script, if you call a fruitful function all by itself, the return value is lost forever!

但在脚本里,如果你单独调用一个有返回值的函数,返回值就永远丢失了!
type00147

This script computes the square root of 5, but since it doesn’t store or display the result, it is not very useful.

这个脚本算出了 5 的平方根,但它既不保存也不显示结果,所以没什么用处。

Void functions might display something on the screen or have some other effect, but they don’t have a return value. If you try to assign the result to a variable, you get a special value called type.

无返回值函数也许会在屏幕上显示点什么,或者产生其它副作用,但它们没有返回值。如果你试图把结果赋给一个变量,你会得到一个叫 type 的特殊值。
type00150

The value type is not the same as the string type00. It is a special value that has its own type:

type 和字符串 type00 不是一回事。它是一个特殊的值,拥有自己的类型:
type00155

The functions we have written so far are all void. We will start writing fruitful functions in a few chapters.

到目前为止我们写的函数都是无返回值的。再过几章,我们就会开始写有返回值的函数。

3.12 Why functions? 3.12 为什么要用函数

It may not be clear why it is worth the trouble to divide a program into functions. There are several reasons:

把一个程序拆成若干个函数,费这番功夫到底图什么,也许并不一目了然。原因有几条:

3.13 Importing with type 3.13 用 from 导入

Python provides two ways to import modules; we have already seen one:

Python 提供两种导入模块的方式;我们已经见过第一种:
type00157

If you import type, you get a module object named type. The module object contains constants like e0 and functions like int and int.

如果用 type00163,你会得到一个名为 type 的模块对象。这个模块对象里装着像 e0 这样的常量,以及 intint 这样的函数。

But if you try to access e0 directly, you get an error.

但如果你试图直接访问 e0,就会出错。
type00170

As an alternative, you can import an object from a module like this:

另一种办法是,像这样从一个模块里导入某个对象:
type00171

Now you can access e0 directly, without dot notation.

现在你可以不使用点记号,直接访问 e0。
type00174

Or you can use the star operator to import everything from the module:

或者,你可以用星号运算符,把模块里的所有东西都导入进来:
type00175

The advantage of importing everything from the math module is that your code can be more concise. The disadvantage is that there might be conflicts between names defined in different modules, or between a name from a module and one of your variables.

从 math 模块一次性导入所有东西的好处是,代码可以更简洁。坏处是,不同模块里定义的名字之间可能产生冲突,或者模块里的名字和你自己的某个变量撞车。

3.14 Debugging 3.14 调试

If you are using a text editor to write your scripts, you might run into problems with spaces and tabs. The best way to avoid these problems is to use spaces exclusively (no tabs). Most text editors that know about Python do this by default, but some don’t.

如果你用文本编辑器来写脚本,可能会碰到空格和制表符的问题。避免这些麻烦的最好办法是只使用空格(不用制表符)。大多数懂 Python 的文本编辑器默认会这么做,但也有一些不会。

Tabs and spaces are usually invisible, which makes them hard to debug, so try to find an editor that manages indentation for you.

制表符和空格通常是看不见的,所以很难调试,尽量找一个能帮你管理缩进的编辑器。

Also, don’t forget to save your program before you run it. Some development environments do this automatically, but some don’t. In that case the program you are looking at in the text editor is not the same as the program you are running.

还有,运行之前别忘了保存程序。有些开发环境会自动保存,有些则不会。那样的话,你在文本编辑器里看到的东西,和你实际运行的东西就不是同一个程序了。

Debugging can take a long time if you keep running the same, incorrect, program over and over!

如果你一遍遍运行的始终是那份错误的程序,调试会花上老长时间!

Make sure that the code you are looking at is the code you are running. If you’re not sure, put something like type00176 at the beginning of the program and run it again. If you don’t see type0, you’re not running the right program!

务必确认你正在看的代码就是正在运行的代码。如果没把握,就在程序开头加一句像 type00178 这样的代码再运行一次。如果没看到 type0,那你跑的就不是正确的程序!

3.15 Glossary 3.15 术语表

function:
A named sequence of statements that performs some useful operation. Functions may or may not take arguments and may or may not produce a result.
function definition:
A statement that creates a new function, specifying its name, parameters, and the statements it executes.
function object:
A value created by a function definition. The name of the function is a variable that refers to a function object.
header:
The first line of a function definition.
body:
The sequence of statements inside a function definition.
parameter:
A name used inside a function to refer to the value passed as an argument.
function call:
A statement that executes a function. It consists of the function name followed by an argument list.
argument:
A value provided to a function when the function is called. This value is assigned to the corresponding parameter in the function.
local variable:
A variable defined inside a function. A local variable can only be used inside its function.
return value:
The result of a function. If a function call is used as an expression, the return value is the value of the expression.
fruitful function:
A function that returns a value.
void function:
A function that doesn’t return a value.
module:
A file that contains a collection of related functions and other definitions.
import statement:
A statement that reads a module file and creates a module object.
module object:
A value created by an type00 statement that provides access to the values defined in a module.
dot notation:
The syntax for calling a function in another module by specifying the module name followed by a dot (period) and the function name.
composition:
Using an expression as part of a larger expression, or a statement as part of a larger statement.
flow of execution:
The order in which statements are executed during a program run.
stack diagram:
A graphical representation of a stack of functions, their variables, and the values they refer to.
frame:
A box in a stack diagram that represents a function call. It contains the local variables and parameters of the function.
traceback:
A list of the functions that are executing, printed when an exception occurs.
函数 function:
一段具名的语句序列,完成某项有用的运算。函数可以接收实参,也可以不接收;可以产生结果,也可以不产生。
函数定义 function definition:
创建一个新函数的语句,指定其名称、形参,以及它要执行的语句。
函数对象 function object:
由函数定义创建的一个值。函数名是一个指向该函数对象的变量。
函数头 header:
函数定义的第一行。
函数体 body:
函数定义内部的语句序列。
形参 parameter:
函数内部用来引用作为实参传入的那个值的名字。
函数调用 function call:
执行一个函数的语句。它由函数名后跟一个实参列表组成。
实参 argument:
调用函数时提供给函数的值。该值被赋给函数内对应的形参。
局部变量 local variable:
在函数内部定义的变量。局部变量只能在其所在函数内部使用。
返回值 return value:
函数的结果。如果函数调用被用作表达式,返回值就是该表达式的值。
有返回值的函数 fruitful function:
返回值的函数。
无返回值函数 void function:
不返回值的函数。
模块 module:
一个文件,里面装着一组相关的函数及其它定义。
导入语句 import statement:
读取模块文件并创建模块对象的语句。
模块对象 module object:
type00 语句创建的值,提供对模块内所定义值的访问。
点记号 dot notation:
通过「模块名 + 点(句号)+ 函数名」来调用另一模块中函数的语法。
组合 composition:
把一个表达式作为更大表达式的一部分,或把一个语句作为更大语句的一部分。
执行流程 flow of execution:
程序运行期间语句被执行的顺序。
栈图 stack diagram:
对函数栈、它们的变量以及它们所引用的值的图形化表示。
栈帧 frame:
栈图中的一个方框,代表一次函数调用。它包含该函数的局部变量和形参。
回溯 traceback:
发生异常时打印出来的、正在执行的函数列表。

3.16 Exercises 3.16 习题

Exercise 3

习题 3

Python provides a built-in function called int that returns the length of a string, so the value of type00183 is 5.

Python 提供了一个内置函数 int,返回字符串的长度,所以 type00185 的值是 5。

Write a function named type00186 that takes a string named e as a parameter and prints the string with enough leading spaces so that the last letter of the string is in column 70 of the display.

写一个名叫 type00188 的函数,它接收一个名为 e 的字符串作形参,打印该字符串时在其前面补足够的空格,使字符串的最后一个字母落在显示器第 70 列。
type00190

Exercise 4

习题 4

A function object is a value you can assign to a variable or pass as an argument. For example, type0019 is a function that takes a function object as an argument and calls it twice:

函数对象是一种值,可以赋给变量,也可以作为实参传递。例如,type0019 是一个函数,它接收一个函数对象作实参,并把它调用两次:
type00193

Here’s an example that uses type0019 to call a function named type00195 twice.

下面是一个例子,用 type0019 把名为 type00197 的函数调用两次。
type00198
  1. Type this example into a script and test it.
  2. Modify type0019 so that it takes two arguments, a function object and a value, and calls the function twice, passing the value as an argument.
  3. Write a more general version of type00200, called type00201, that takes a string as a parameter and prints it twice.
  4. Use the modified version of type0020 to call type00203 twice, passing type00 as an argument.
  5. Define a new function called type002 that takes a function object and a value and calls the function four times, passing the value as a parameter. There should be only two statements in the body of this function, not four.
  1. 把这个例子敲进一个脚本里并测试它。
  2. 修改 type0020,让它接收两个实参:一个函数对象和一个值,并把该函数调用两次,每次都把那个值作为实参传入。
  3. 写一个更通用的 type00207 版本,名叫 type00208,它接收一个字符串作形参,并把字符串打印两遍。
  4. 用修改过的 type0020,把 type00210 调用两次,传入 type00 作实参。
  5. 定义一个新的函数 type002,它接收一个函数对象和一个值,把该函数调用四次,每次都把那个值作为形参传入。这个函数的函数体里只能有两条语句,而不是四条。

Solution: type00213.

参考答案:type00214。

Exercise 5

习题 5

This exercise can be done using only the statements and other features we have learned so far.

只用我们目前学过的语句和特性,就能完成这道习题。
  1. Write a function that draws a grid like the following: type00215 Hint: to print more than one value on a line, you can print a comma-separated sequence: type00216 If the sequence ends with a comma, Python leaves the line unfinished, so the value printed next appears on the same line. type00217 The output of these statements is type0. A type0 statement all by itself ends the current line and goes to the next line.
  2. Write a function that draws a similar grid with four rows and four columns.
  1. 写一个函数,画出如下所示的网格: type00220 提示:要在一行里打印多个值,可以打印一个用逗号分隔的序列: type00221 如果序列以逗号结尾,Python 会让这一行保持不结束,于是接下来打印的值会出现在同一行。 type00222 这些语句的输出是 type0。 单独一个 type0 语句会结束当前行并换到下一行。
  2. 写一个函数,画出类似的、四行四列的网格。

Solution: type00225. Credit: This exercise is based on an exercise in Oualline, Practical C Programming, Third Edition, O’Reilly Media, 1997.

参考答案:type00226。致谢:本题改编自 Oualline 所著《Practical C Programming, Third Edition》(O’Reilly Media,1997)中的一道练习。