Menu

Python 函数:def、return、默认参数和关键字参数

如何在 Python 中定义和使用函数:参数、返回值、默认参数、关键字参数,以及让代码保持可读的命名习惯。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

函数是有名字的一组步骤

每当你发现自己把同样的几行代码写了不止一次,或者想给一小段逻辑起个名字,就是时候写一个函数了。函数是在 Python 程序中管理复杂度的第一件真正的工具。

基本结构:

拆开来看:

  • def 是开始定义函数的关键字。
  • greet 是函数名。
  • (name) 是参数列表,也就是函数接收的输入。
  • 冒号结束函数头;下面缩进的代码块是函数体。
  • greet("Ada") 是一次调用。Python 会把 name 绑定为 "Ada",然后运行函数体。

函数在被调用之前一直处于休眠状态。定义函数并不会运行它,用 greet("Ada") 调用它才会。

形参和实参

形参(parameter)是函数定义中的名字。实参(argument)是调用时传入的值。日常交流中这个区别不太重要,但读错误信息时分清它们会有帮助。

这里 base 和 exponent 是形参,2 和 10 是实参。Python 按顺序绑定它们:第一个实参对应第一个形参,以此类推。

return:返回一个值

print 把内容写到屏幕上。return 把一个值交还给调用者,让调用者可以使用它:

没有 return 时,函数默认返回 None:

return 还会让函数立即退出。你会经常看到用提前返回在主要逻辑之前处理边界情况:

提前返回可以避免主体代码深深嵌套在 if/else 里。

默认参数

参数可以有默认值,在调用者没有提供时使用:

所有带默认值的参数都必须放在没有默认值的参数之后。def f(a, b=1, c): 是语法错误。

可变默认参数的陷阱

这是 Python 中最有名的坑。看下面的例子:

你可能以为每次调用都会从一个空列表开始。实际上,默认的列表在多次调用之间是共享的,元素会不断累积。Python 只在定义函数时对默认值求值一次,之后一直重复使用那同一个列表。

安全的写法是用 None 作为默认值,然后在函数内部创建列表:

现在,每次没有传入 items 的调用都会得到一个新列表。这条规则适用于列表、字典、集合等所有可变对象。

关键字参数

你可以按名字而不是按位置传入参数。这样可以跳过中间的参数,也能让很长的调用更易读:

位置参数和关键字参数可以混用,但位置参数必须放在前面:

当一个函数有三四个以上的参数时,优先使用关键字参数会让调用代码易读得多。

仅限位置参数和仅限关键字参数

Python 允许你把某些参数标记为只能按位置传入(用 /),或只能按关键字传入(用 *):

刚开始学的时候用不到它们。等你设计 API、想要限定调用者使用函数的方式时,它们就派上用场了。

文档字符串和命名

函数内部的第一行可以是文档字符串(docstring),即 Python 当作文档的三引号字符串:

help()、IDE 的悬停提示和文档生成器等工具会自动读取文档字符串。哪怕只写一行,也比什么都不写好得多。

另外,请认真考虑命名:

  • 函数名应该是动词:fetch_profile、compute_total、is_valid。
  • 使用 lower_snake_case。
  • 返回布尔值的函数通常以 is_、has_ 或 can_ 开头。

好的名字能让调用处一目了然,不需要额外注释。

纯函数更容易理解

纯函数对相同的输入总是返回相同的输出,并且没有副作用:它不修改全局状态,不向 stdout 打印内容(调试除外),也不写文件。

两者都有用武之地,但在你想要复用和测试的代码中,尽量多写纯函数。

一个能运行的小例子

一个结合了默认参数、关键字参数和 return 的简短函数:

下一篇:灵活的参数列表

有时你不知道一个函数会被传入多少个参数,或者你想把收到的参数原样转交给另一个函数。*args 和 **kwargs 就是用来处理这种情况的,这是下一页的内容。

常见问题

Python 中怎么定义函数?

使用 def 关键字,后面跟函数名、放参数的括号和一个冒号。下面缩进的代码块就是函数体。例如:def greet(name): print(f'Hi, {name}')。

Python 中的 return 有什么作用?

return 把一个值返回给调用这个函数的地方。没有显式 return 的函数会自动返回 None。return 一旦执行,函数就会立即退出,同一代码块中它后面的代码都会被跳过。

Python 中的默认参数是什么?

默认参数让一个参数拥有预设的值,调用者没有提供时就使用它。def greet(name='friend'): 意味着不带参数调用 greet() 时会使用 'friend'。永远不要用 [] 这样的可变对象作为默认值,更安全的写法见下文。

Coddy 编程语言插图

和 Coddy 一起学编程

开始