(首页)开始编程之旅 翻译自Lee Harr的Start Programming

本文是使用pygsear+pygame作为开发环境,以初级用户角度来分步分阶段学习PYTHON基本概念,并以小游戏开发项目为具体案例,介绍的十分详细。编写风格清新朴实,没有象一般教科书那样枯燥,极其适合初级用户来激发兴趣时使用。

1. StartProgramming-1-6 函数Functions

Loops are useful for performing a set of steps repeatedly, but what if you want to repeat the entire loop over and over again -- maybe with different parameters.

循环在做一套反复的操作是非常有用,但是你想要一遍又一遍重复的究竟是什么 -- 也许会有不同的参数吧。

For instance, maybe you want to draw a lot of squares all on different parts of the screen.

举个例子,也许你想在屏幕四处画许多正方形。

attachfile:many_squares.png

Using functions we can save a piece of code so that we can use it again later.

用函数我们能够保存一部分代码,等到下一次的时候再用它。

A function is sort of like a mini program inside of your program.

在你的程序中,一个函数好像一个迷你程序一样。

When we use the function, we say that we call it, almost like you might call the time service on your phone.

当我们要用一个函数,我们说要调用它,就像在手机中调用报时服务一样。

Functions can either return some value or object to your main program (like the current time), or they can perform some action (like setting the time) without returning a value. A function which does not return a value is sometimes called a procedure.

函数可以或者返回一些值或对象到你的主程序(好比现在),或者他们能够执行一些操作(比方说设置时间)但不返回任何值。当一个函数没有返回值时,我们通常称它为一个 过程。

Let's make a function which, when called, will draw a square, starting wherever pete happens to be at the time:

让我们做一个函数,调用它时,不管什么时候在什么地方pete都能画出一个正方形来:

   1 def square():
   2     for side in 1, 2, 3, 4:
   3         forward(100)
   4         right(90)

square is a function object. square 是一个函数对象。

Notice that the body of the function, just like the body of the loop before, is indented, and since there is a loop inside of our function, the body of the loop is indented again. The first indent should be 4 spaces, the second indent is 4 more for a total of 8 spaces.

注意这个函数的 内容 ,刚好和前面的循环一样是缩进的。并且之后在我们的函数里也有一个循环,循环的内容再次缩进。第一次缩进是4个空格,第二次缩进又加了4个总共是8个空格。

To call our new function, use this:

要调用我们的新函数,用:

square()

To see why we might want to make functions, try a combination of a loop which calls our function:

想要知道我们为什么要做一个函数,可以试试结合一个循环调用我们的函数:

   1 for side in 1, 2, 3, 4:
   2     forward(125)
   3     square()
   4     left(90)

Loop in progress...

正在循环中……

If you had done that by hand, or tried to figure out how to put all those loops together, it would have taken a long time, and it would have been very easy to make a mistake. With functions, you can think in terms of larger pieces. This loop says: "Set side equal to 1, go forward, make a square, turn left, set side equal to 2, go forward, etc..."

如果你手工完成这些,或者尝试统计出总共循环了多少次,这将花费你很长的时间,并且很容易发生错误。用函数,你可以从整体上来考虑。这个循环的意思是:“设置 side 等于 1,前进,画一个正方形,左转,设置 side 等于 2,前进, 等等……”

Remember that "Set side equal to 1" has nothing to do with the length of the side. It is just counting.

记住“设置side等于1”并不会改变正方形的边长。这只不过是个计数器。

1.1. 参数Parameters

square() is fine as it is. It makes a square on the screen just as you asked it to, but what if all your squares are not the same size?

square() 表现得很好。它按照你的要求在屏幕上画正方形,但是怎样才能让你的正方形边长不相等呢?

Let's make a function which is a bit more general purpose:

让我们给函数来一点通用性:

   1 def generalSquare(length):
   2     for side in 1, 2, 3, 4:
   3         forward(length)
   4         right(90)

generalSquare takes one parameter -- the length

generalSquare 有一个参数 -- 是 length

This time, our function takes a parameter (also called an argument) the length of a side of the square, and when moving forward, instead of using the value 100, it uses the value of the length.

这次,我们的函数有了一个 参数 (也叫做变元) 是正方形一个边的长度并且前进的时候,我们用 length 的值来代替 100的值。

Now, to make a square with a side of length 20, we will call:

现在,想要画一个边长是20的正方形,我们可以调用:

generalSquare(20)

When this function gets called, the variable length is given the value we put in the parentheses. Then any time python sees length in the body of the function, it substitutes that value.

当这个函数被调用时,变量 length 就会被赋予我们在括号内所给的值。然后任何时候python在函数的语句中看到 length ,都会用那个值来代替它。

This generalized square method is so useful, that it is built-in to all Penguin objects. In interact.py you can use it like this:

这个通用的 square 方法是如此的有用,它已经被内健到所有的 Penguin 对象中了。在 interact.py 中你可以像这样来用:

pete.square(20)

In fact, there is also another type of square built-in which is centered on the penguin's present location:

实际上,这里还有另外一种类型的正方形被内建在当前的企鹅中:

pete.cSquare(50)

will draw a 50-pixel square with pete right in the middle.

将画一个pete正好在中央的50像素的正方形。

How might we use the squares? Let's try this:

我们怎样来利用这些正方形?让我们试试着个:

   1 width = 5
   2 
   3 while width < 200:
   4     set_color('random')
   5     pete.square(width)
   6     width += 2
   7     left(65)

That's pretty neat. Let's make that in to a function too...

这个是相当的整洁漂亮,让我们把它也定义到一个函数中……

   1 def flow(angle, grow=2):
   2     width = 5
   3 
   4     while width < 200:
   5         set_color('random')
   6         pete.square(width)
   7         width += grow
   8         left(angle)

square, turn, square, turn, square, etc...

正方形,转,正方形,转,正方形,等等……

As you can see, functions can also take more than one parameter. flow takes two parameters: the angle to turn between squares, and the amount to grow between squares. Also, grow uses a default value of 2.

正如你所见,函数可以拥有不止一个参数。flow 拥有两个参数:angle 是正方形之间的夹角, grow 是正方形的增值。另外, grow 用 2 作为初始值。

So, we can call flow with 2 parameters:

因此,我们用两个参数调用 flow:

flow(4, 1)

or, if the default value is ok, then we can call it with just the one parameter:

或者,如果同意用缺省值,我们可以用一个参数调用它:

flow(14)

and it will be the same as if we had called flow(14, 2)

这和调用 flow(14, 2) 是一样的

1.2. 更通用的More General

All of these squares might make you wonder if you can draw some other shape. Maybe you want to make an even more general function. Try this:

如果你能够画出其他的形状,所有这些正方形会使你感到惊奇。也许你想做一个更加通用的函数。试试这个:

   1 def lineTurn(length, angle):
   2     for side in 1, 2, 3, 4:
   3         forward(length)
   4         right(angle)

Two parameters, no default values.

两个参数,没有缺省值。

and call it like this:

并且像这样来调用它:

   1 lineTurn(150, 90)
   2 lineTurn(200, 120)
   3 lineTurn(50, 72)

Notice that I did not give it a name that mentions square at all, since what lineTurn() makes will not always be a square.

注意我命名时,根本没有提到 square ,因为 lineTurn() 不会总是画出一个正方形来。

Give those three function calls a try and see what you get.

尝试调用这三个函数,看看你得到了什么。

The first call is fine. It is just as if we called generalSquare(150). The second call succeeds in making a triangle, but it is a bit wasteful as it draws over one of the sides twice.

第一次调用很好,它就像我们调用 generalSquare(150)一样。第二个调用成功的画出了一个三角形,不过它把一条边画了2次有点浪费。

What happens on the last call though? It gets most of the way through a pentagon and stops.

可是最后一次调用发生了什么?它画出了大部分的五角形却停止了。

It is close to being a complete pentagon... You could finish it up by just typing forward(50) but it would be nice if the function could do that on its own.

它终止了完成一个五角星…… 你可以键入 forward(50) 来完成它,但是如果函数自己能那样做的话会更好。

In the next section, we will do just that.

在下一节里,我们再那样做。