4.6. 定义函数

最后更新于:2022-04-01 00:47:39

我们可以创建一个用来生成指定边界的斐波那契数列的函数: ~~~ >>> def fib(n): # write Fibonacci series up to n ... """Print a Fibonacci series up to n.""" ... a, b = 0, 1 ... while a n: ... print(a, end=' ') ... a, b = b, a+b ... print() ... >>> # Now call the function we just defined: ... fib(2000) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 ~~~ 关键字 def 引入了一个函数 _定义_。在其后必须跟有函数名和包括形式参数的圆括号。函数体语句从下一行开始,必须是缩进的。 函数体的第一行语句可以是可选的字符串文本,这个字符串是函数的文档字符串,或者称为_docstring_。(更多关于 docstrings 的信息请参考 [_文档字符串_](http://www.pythondoc.com/pythontutorial3/controlflow.html#tut-docstrings)) 有些工具通过 docstrings 自动生成在线的或可打印的文档,或者让用户通过代码交互浏览;在你的代码中包含 docstrings 是一个好的实践,让它成为习惯吧。 函数 _调用_ 会为函数局部变量生成一个新的符号表。确切的说,所有函数中的变量赋值都是将值存储在局部符号表。变量引用首先在局部符号表中查找,然后是包含函数的局部符号表,然后是全局符号表,最后是内置名字表。因此,全局变量不能在函数中直接赋值(除非用 global 语句命名),尽管他们可以被引用。 函数引用的实际参数在函数调用时引入局部符号表,因此,实参总是 _传值调用_ (这里的 _值_ 总是一个对象 引用 ,而不是该对象的值)。[[1]](http://www.pythondoc.com/pythontutorial3/controlflow.html#id10) 一个函数被另一个函数调用时,一个新的局部符号表在调用过程中被创建。 一个函数定义会在当前符号表内引入函数名。函数名指代的值(即函数体)有一个被 Python 解释器认定为 _用户自定义函数_ 的类型。 这个值可以赋予其他的名字(即变量名),然后它也可以被当做函数使用。这可以作为通用的重命名机制: ~~~ >>> fib >>> f = fib >>> f(100) 0 1 1 2 3 5 8 13 21 34 55 89 ~~~ 如果你使用过其他语言,你可能会反对说:fib 不是一个函数,而是一个方法,因为它并不返回任何值。事实上,没有 return 语句的函数确实会返回一个值,虽然是一个相当令人厌烦的值(指 None )。这个值被称为 None (这是一个内建名称)。如果 None 值是唯一被书写的值,那么在写的时候通常会被解释器忽略(即不输出任何内容)。如果你确实想看到这个值的输出内容,请使用print() 函数: ~~~ >>> fib(0) >>> print(fib(0)) None ~~~ 定义一个返回斐波那契数列数字列表的函数,而不是打印它,是很简单的: ~~~ >>> def fib2(n): # return Fibonacci series up to n ... """Return a list containing the Fibonacci series up to n.""" ... result = [] ... a, b = 0, 1 ... while a n: ... result.append(a) # see below ... a, b = b, a+b ... return result ... >>> f100 = fib2(100) # call it >>> f100 # write the result [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] ~~~ 和以前一样,这个例子演示了一些新的 Python 功能: * return 语句从函数中返回一个值,不带表达式的 return 返回 None。过程结束后也会返回None。 * 语句 result.append(b) 称为链表对象 result 的一个 _方法_。方法是一个“属于”某个对象的函数,它被命名为 obj.methodename,这里的 obj 是某个对象(可能是一个表达式), methodename 是某个在该对象类型定义中的方法的命名。不同的类型定义不同的方法。不同类型可能有同样名字的方法,但不会混淆。(当你定义自己的对象类型和方法时,可能会出现这种情况,_class_ 的定义方法详见 [_类_](http://www.pythondoc.com/pythontutorial3/classes.html#tut-classes) )。示例中演示的 append() 方法由链表对象定义,它向链表中加入一个新元素。在示例中它等同于 result = result + [b],不过效率更高。
';