各位CSDN的uu们你们好呀,今天小雅兰的内容是Python中的函数,其实距离上一篇Python的函数的时间很长了,小雅兰会通过这篇博客回忆起来曾经学过的知识,现在,让我们进入函数的世界吧
函数(上)——“Python”_认真学习的小雅兰.的博客-CSDN博客
函数的链式调用和嵌套调用
局部变量和函数栈帧
函数递归
函数形参的默认值
函数的关键字参数
函数的链式调用和嵌套调用
链式调用
把一个函数的返回值, 作为另一个函数的参数, 这种操作称为链式调用。
# 判定是否是奇数 def isOdd(num): if num % 2 == 0: return False else: return True result = isOdd(10) print(result)
# 判定是否是奇数 def isOdd(num): if num % 2 == 0: return False else: return True def add(x,y): return x+y print(isOdd(add(5,5)))
链式调用的时候,也不要嵌套的层次太深!!!非常影响可读性!!!
嵌套调用
函数内部还可以调用其他的函数, 这个动作称为 "嵌套调用" .
def test(): print("执行函数内部代码") print("执行函数内部代码") print("执行函数内部代码")
test 函数内部调用了 print 函数, 这里就属于嵌套调用.
嵌套调用层次也可以有很多层!!!
一个函数里面可以嵌套调用任意多个函数.
函数嵌套的过程是非常灵活的.
def a(): print("函数 a") def b(): print("函数 b") a() def c(): print("函数 c") b() def d(): print("函数 d") c() d()
如果把代码稍微调整, 打印结果则可能发生很大变化.
def a(): print("函数 a") def b(): a() print("函数 b") def c(): b() print("函数 c") def d(): c() print("函数 d") d()
上述过程仍然可以使用调试器来分析!!!
局部变量和函数栈帧
函数之间的调用关系, 在 Python 中会使用一个特定的数据结构来表示, 称为函数调用栈 。每次函数调用,都会在调用栈里新增一个元素, 称为栈帧.
可以通过 PyCharm 调试器看到函数调用栈和栈帧.
在调试状态下, PyCharm 左下角一般就会显示出函数调用栈.
每个函数的局部变量, 都包含在自己的栈帧中
def a(): num1=10 print("函数 a") def b(): num2=20 a() print("函数 b") def c(): num3=30 b() print("函数 c") def d(): num4=40 c() print("函数 d") d()
选择不同的栈帧, 就可以看到各自栈帧中的局部变量.
思考: 上述代码, a, b, c, d 函数中的局部变量名各不相同. 如果变量名是相同的, 比如都是 num , 那么 这四个函数中的 num 是属于同一个变量, 还是不同变量呢?
def a(): num=10 print("函数 a") def b(): num=20 a() print("函数 b") def c(): num=30 b() print("函数 c") def d(): num=40 c() print("函数 d") d()
函数递归
递归是嵌套调用中的一种特殊情况, 即一个函数嵌套调用自己.
下面,来看一个具体的例子:
写一个函数,来求n的阶乘(n是正整数)
先使用循环的方式来求解:
def factor(n): result=1 for i in range(1,n+1): result*=i return result print(factor(5))
下面,来使用递归的方式来求解:
n!=n*(n-1)!
def factor(n): if n == 1: return 1 return n * factor(n - 1) result = factor(5) print(result)
上述代码中, 就属于典型的递归操作. 在 factor 函数内部, 又调用了 factor 自身.
注意:
- 递归代码务必要保证存在递归结束条件. 比如 if n == 1 就是结束条件. 当 n 为 1 的时候, 递归就结束了.
- 每次递归的时候, 要保证函数的实参是逐渐逼近结束条件的.
如果上述条件不能满足, 就会出现 "无限递归" . 这是一种典型的代码错误.
def factor(n): return n * factor(n - 1) result = factor(5) print(result)
如前面所描述, 函数调用时会在函数调用栈中记录每一层函数调用的信息.
但是函数调用栈的空间不是无限大的. 如果调用层数太多, 就会超出栈的最大范围, 导致出现问题.
递归的优点
递归类似于 "数学归纳法" , 明确初始条件, 和递推公式, 就可以解决一系列的问题.
递归代码往往代码量非常少.
递归的缺点
递归代码往往难以理解, 很容易超出掌控范围
递归代码容易出现栈溢出的情况
递归代码往往可以转换成等价的循环代码. 并且通常来说循环版本的代码执行效率要略高于递归版本.
实际开发的时候, 使用递归要慎重!
函数形参的默认值
Python 中的函数, 可以给形参指定默认值.
带有默认值的参数, 可以在调用的时候不传参.
代码示例: 计算两个数字的和
def add(x, y, debug=False): if debug: print(f'调试信息: x={x}, y={y}') return x + y print(add(10, 20)) print(add(10, 20, True))
此处 debug=False 即为参数默认值. 当我们不指定第三个参数的时候, 默认 debug 的取值即为 False.
带有默认值的参数需要放到没有默认值的参数的后面
def add(x, debug=False, y): if debug: print(f'调试信息: x={x}, y={y}') return x + y print(add(10, 20))
函数的关键字参数
在调用函数的时候, 需要给函数指定实参. 一般默认情况下是按照形参的顺序, 来依次传递实参的.
但是我们也可以通过 关键字参数, 来调整这里的传参顺序, 显式指定当前实参传递给哪个形参。
def test(x, y): print(f'x = {x}') print(f'y = {y}') test(x=10, y=20) test(y=100, x=200)
形如上述 test(x=10, y=20) 这样的操作, 即为 关键字参数.
小结
函数是编程语言中的一个核心语法机制. Python 中的函数和大部分编程语言中的函数功能都是基本类似的.
我们当下最关键要理解的主要就是三个点:
函数的定义
函数的调用
函数的参数传递
我们在后续的编程中, 会广泛的使用到函数.
好啦,小雅兰今天的内容就到这里啦,还要继续加油学习呀!!!