导图
函数
介绍
编程中的函数和数学中的函数有一定的相似之处.
栗子:初中学的正弦函数(y = sinx)
编程中的函数, 是一段可以被重复使用的代码片段
函数引入
分别求1-100,1-1000,300-400的总和
#求1-100的总数和 sum = 0 for i in range(1, 101): sum += i print(sum) #求1-1000的总数和 sum = 0 for i in range(1, 1001): sum += i print(sum) #求300-400的总数和 sum = 0 for i in range(300, 401): sum += i print(sum)
上面👆是我们之前所学过的知识
接着我们用函数替换掉上面代码
#定义函数 def calcSum(begin, end): sum = 0 for i in range(begin, end + 1): sum += i print(sum) #调用函数 calcSum(1, 100) calcSum(1, 1000) calcSum(300, 400)
代码解释及语法格式
关于函数的有关术语和规则
1、函数调用
函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次,如像上面调用了三次会执行三次
2、函数的定义和使用顺序
函数必须先定义,再使用,如看上图👆
3、函数参数
在函数定义的时候, 可以在 ( ) 中指定 "形式参数" (简称 形参), 然后在调用的时候, 由调用者把 "实际参数" (简称 实参) 传递进去.
这样就可以做到一份函数, 针对不同的数据进行计算处理.
函数的形参和实参就如同签合同的甲方和乙方一样
注:
①一个函数可以有一个形参, 也可以有多个形参, 也可以没有形参.
②一个函数的形参有几个, 那么传递实参的时候也得传几个. 保证个数要匹配.
③Python 是动态类型的编程语言, 函数的形参不必指定参数类型. 换句话说, 一个函数可以支持多种不同类型的参数.
4、函数的返回值
返回值的使用和作用
函数的参数可以视为是函数的 "输入",
则函数的返回值, 就可以视为是函数的 "输出" .
#定义函数 def calcSum(begin, end): sum = 0 for i in range(begin, end + 1): sum += i return sum #调用函数 result = calcSum(1, 100) print(result)使用return语句把结果返回给函数调用者,再由调用者打印
一般写函数用return语句返回
这种种写法则专注于做计算逻辑, 不负责和用户交互. 那么就很容易把这个逻辑搭配不同的用户交互代码, 来实现不同的效果.
在一个函数中返回值可以有多个
例如:用函数判断一个数是否为偶数
def isOld(sum): if sum % 2 == 0: return True else: return False result = isOld(7) print(result) result = isOld(10) print(result)注:执行到 return 语句, 函数就会立即执行结束, 回到调用位置
函数一次多个返回值的使用
①一个函数是可以一次返回多个返回值的. 使用 , 来分割多个返回值.
输出坐标轴上的点x和y
def getpoint(): x = 3 y = 6 return x, y a, b = getpoint() print(a, b)
有多个返回值忽略其中某一个返回值
②如果只想关注其中的部分返回值, 可以使用 _ 来忽略不想要的返回值
输出坐标轴上的点y
def getpoint(): x = 3 y = 6 return x, y _, b = getpoint() print(b)
链式调用
例如上面判断一个数是否为偶数
最后两句代码可以转换为
print(isOld(7))
像这样,把一个函数的返回值, 作为另一个函数的参数, 这种操作称为链式调用.
变量作用域
像上面代码函数getpoint中内部定义的 x, y 只是在函数内部生效. 一旦出了函数的范围, 这两个变量就不再生效了.
在函数内部的变量, 也称为"局部变量"
不在任何函数内部的变量, 也称为"全局变量"
①如果函数内部尝试访问的变量在局部不存在, 就会尝试去全局作用域中查找
x = 6#全局(外部) def test(): x = 10#局部(内部) print(f'x = {x}') test() print(f'x = {x}')
控制台输出
x = 10
x = 6
②如果是想在函数内部, 修改全局变量的值, 需要使用 global 关键字声明
x = 6#全局(外部) def test(): global x x = 10#局部(内部) print(f'x = {x}') test() print(f'x = {x}')
控制台输出
x = 10
x = 10
注:
if / while / for 等语句块不会影响到变量作用域
换而言之, 在 if / while / for 中定义的变量, 在语句外面也可以正常使用.
嵌套调用
函数内部还可以调用其他的函数, 这个动作称为 "嵌套调用"
def fun1(): print("函数 1") def fun2(): print("函数 2") fun1() def fun3(): print("函数 3") fun2() def fun4(): print("函数 4") fun3() fun4()
控制台输出
代码解释
函数之间的调用关系, 在 Python 中会使用一个特定的数据结构来表示, 称为函数调用栈 .
每次函数调用, 都会在调用栈里新增一个元素, 称为栈帧.
函数递归
递归是嵌套调用中的一种特殊情况, 即一个函数嵌套调用自己.
递归使用
例如:计算6的阶层( 6! )
def fac(n): if n == 1: return 1 return n * fac(n-1) result = fac(6) print(result)
注:
上述代码中, 就属于典型的递归操作. 在 fac 函数内部, 又调用了 factor 自身.
注意: 递归代码务必要保证存在递归结束条件.
比如
if n == 1 就是结束条件. 当 n 为 1 的时候, 递归就结束了.
每次递归的时候, 要保证函数的实参是逐渐逼近结束条件的.
如果上述条件不能满足, 就会出现 "无限递归" . 这是一种典型的代码错误
递归优缺点
递归的优点
①递归类似于 "数学归纳法" , 明确初始条件, 和递推公式, 就可以解决一系列的问题.
②递归代码往往代码量非常少.
递归的缺点
①递归代码往往难以理解, 很容易超出掌控范围
②递归代码容易出现栈溢出的情况
③递归代码往往可以转换成等价的循环代码.
并且通常来说循环版本的代码执行效率要略高于递归版本.
参数默认值
Python 中的函数, 可以给形参指定默认值.
带有默认值的参数, 可以在调用的时候不传参.
def Add(x, y, debug = False): if debug: print(f'x = {x},y = {y}') return x + y print(Add(3, 6)) print(Add(5, 9, True))
控制台结果输出
注
1、此处 debug=False 即为参数默认值. 当我们不指定第三个参数的时候, 默认 debug 的取值即为 False.
2、带有默认值的参数需要放到没有默认值的参数的后面
错误使用:
关键字参数
def Test(x, y): print(f'x = {x}') print(f'x = {y}') Test(x = 3, y = 7) Test(y = 7, x = 3)
最后两行代码就是关键字参数
在调用函数的时候, 需要给函数指定实参. 一般默认情况下是按照形参的顺序, 来依次传递实参的.
但是我们也可以通过关键字参数, 来调整这里的传参顺序, 显式指定当前实参传递给哪个形参.