Python中函数的用法非常多,80%的用法不常用,20%的用法常用。大家不要把精力浪费在背完所有用法上,而要把主要精力放到最常用的20%的用法和代码逻辑上,至于另外80%不常用的用法,边用边查就行。
1. 函数基础
Python中一个典型的函数定义包括以下部分:关键字def
、函数名称、由0个或多个形参组成的列表以及函数体。
1.1 编写函数
我们来编写一个求阶乘的函数。例如:
1 | def fact(n): |
函数名称是fact
,给它传入一个n
,会返回n
的阶乘。return
语句负责结束函数并返回res
的值。
1.2 调用函数
1 | print("我们要计算5的阶乘,答案是:") |
函数的调用完成两项工作:
- 用实参初始化函数对应的形参
- 将控制权转移给被调用的函数
此时,代码原本的执行顺序被暂时中断,被调函数开始执行。等被调用函数执行完后,再继续执行之前的代码。
1.3 形参和实参
实参指调用函数时传入的变量或常量,形参指定义函数时参数列表里的变量。
形参列表可以为空,例如:
1 | def f(): |
1.3.1 形参的初始化方式
调用函数时会用实参去初始化形参,初始化的顺序有两种:
第一种是用位置实参来初始化形参。顾名思义,实参会按位置关系来初始化形参,第一个实参初始化第一个形参,第二个实参初始化第二个形参,依此类推。形参和实参的个数必须匹配。例如:
1 | def f(a, b, c, d): |
第二种是用关键字实参来初始化形参。此时实参不再按位置关系来初始化形参,而是按变量名初始化。例如:
1 | # f()的定义如上所述 |
两种方式也可以混合使用,但是位置实参一定要放到关键字实参之前。例如:
1 | # f()的定义如上所述 |
1.3.2 带默认值的形参
形参也可以设置默认值,但所有带默认值的形参必须是最后几个。当某些形参没有被初始化时,这些形参会使用默认值。例如:
1 | def f(a, b, c=3, d="Python"): |
1.3.3 其它参数写法
其它参数写法用得不多,想了解的同学可以参考函数定义详解。
1.4 变量的作用域
函数内定义的变量为局部变量,只能在函数内部使用。
当需要修改用全局变量时,需要用global
关键字在函数内声明全局变量。例如:
1 | x = 1 |
1.5 嵌套定义函数
函数内部也可以定义函数。例如:
1 | def f(): |
1.6 pass
语句
当函数定义完但还不想实现时,可以用pass
占位符,来避免出现语法错误。例如:
1 | def f(): |
2. 参数传递
2.1 值传递
int
、float
、bool
、字符串等采用值传递。
将实参的初始值拷贝给形参。此时,对形参的改动不会影响实参的初始值。例如:
1 | def f(y): |
2.2 引用传递
列表采用引用传递。
将实参的引用传给形参,此时对形参的修改会影响实参的初始值。例如:
1 | def f(b): |
3.return
语句
return语句终止当前正在执行的函数并将控制权返回到调用该函数的地方,并返回结果。例如:
1 | def f(x): |
4.lambda
表达式
lambda关键字可以创建匿名函数,目的是为了简化代码。可以对比下面两种写法,会发现lambda表达式的写法更短一些。
常与sort()函数配合使用,例如:
1 | pairs = [[1, "one"], [2, "two"], [3, "three"], [4, "four"]] |
等价于下面的写法:
1 | pairs = [[1, "one"], [2, "two"], [3, "three"], [4, "four"]] |
5. 函数递归
在一个函数内部,也可以调用函数自身。这种写法被称为递归。
写递归函数可以从集合的角度来思考。理解递归函数的执行顺序可以用树的形式来思考。
例如,求解斐波那契数列第 nn 项可以采用如下写法:
1 | def fib(n): |