4.6. 定义函数

我们可以创建一个输出任意范围内 Fibonacci 数列的函数:

  1. >>> def fib(n): # write Fibonacci series up to n
  2. ... """Print a Fibonacci series up to n."""
  3. ... a, b = 0, 1
  4. ... while a < n:
  5. ... print(a, end=' ')
  6. ... a, b = b, a+b
  7. ... print()
  8. ...
  9. >>> # Now call the function we just defined:
  10. ... fib(2000)
  11. 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

关键字 def 引入一个函数 定义。它必须后跟函数名称和带括号的形式参数列表。构成函数体的语句从下一行开始,并且必须缩进。

函数体的第一个语句可以(可选的)是字符串文字;这个字符串文字是函数的文档字符串或 docstring 。(有关文档字符串的更多信息,请参阅 文档字符串 部分)有些工具使用文档字符串自动生成在线或印刷文档,或者让用户以交互式的形式浏览代码;在你编写的代码中包含文档字符串是一种很好的做法,所以要养成习惯。

函数的 执行 会引入一个用于函数局部变量的新符号表。 更确切地说,函数中所有的变量赋值都将存储在局部符号表中;而变量引用会首先在局部符号表中查找,然后是外层函数的局部符号表,再然后是全局符号表,最后是内置名称的符号表。 因此,全局变量和外层函数的变量不能在函数内部直接赋值(除非是在 global 语句中定义的全局变量,或者是在 nonlocal 语句中定义的外层函数的变量),尽管它们可以被引用。

在函数被调用时,实际参数(实参)会被引入被调用函数的本地符号表中;因此,实参是通过 按值调用 传递的(其中 始终是对象 引用 而不是对象的值)。1 当一个函数调用另外一个函数时,将会为该调用创建一个新的本地符号表。

函数定义会将函数名称与函数对象在当前符号表中进行关联。 解释器会将该名称所指向的对象识别为用户自定义函数。 其他名称也可指向同一个函数对象并可被用来访问访函数:

  1. >>> fib
  2. <function fib at 10042ed0>
  3. >>> f = fib
  4. >>> f(100)
  5. 0 1 1 2 3 5 8 13 21 34 55 89

如果你学过其他语言,你可能会认为 fib 不是函数而是一个过程,因为它并不返回值。事实上,即使没有 return 语句的函数也会返回一个值,尽管它是一个相当无聊的值。这个值称为 None (它是内置名称)。一般来说解释器不会打印出单独的返回值 None ,如果你真想看到它,你可以使用 print()

  1. >>> fib(0)
  2. >>> print(fib(0))
  3. None

写一个返回斐波那契数列的列表(而不是把它打印出来)的函数,非常简单:

  1. >>> def fib2(n): # return Fibonacci series up to n
  2. ... """Return a list containing the Fibonacci series up to n."""
  3. ... result = []
  4. ... a, b = 0, 1
  5. ... while a < n:
  6. ... result.append(a) # see below
  7. ... a, b = b, a+b
  8. ... return result
  9. ...
  10. >>> f100 = fib2(100) # call it
  11. >>> f100 # write the result
  12. [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

此示例中,像往常一样,演示了一些新的 Python 功能:

  • return 语句会从函数内部返回一个值。 不带表达式参数的 return 会返回 None。 函数执行完毕退出也会返回 None

  • result.append(a) 语句调用了列表对象 result方法 。方法是“属于”一个对象的函数,它被命名为 obj.methodname ,其中 obj 是某个对象(也可能是一个表达式), methodname 是由对象类型中定义的方法的名称。不同的类型可以定义不同的方法。不同类型的方法可以有相同的名称而不会引起歧义。(可以使用 定义自己的对象类型和方法,请参阅 )示例中的方法 append() 是为列表对象定义的;它会在列表的最后添加一个新的元素。在这个示例中它相当于 result = result + [a] ,但更高效。