文章目录
- 1.形参和实参
- 2.关键字参数
- 3.默认参数
- 4.收集参数(可变参数)
- 5.函数与过程
- 6.局部变量与全局变量
- 7.函数嵌套和闭包
- 8.lambda表达式
- 9.递归
1.形参和实参
- 函数文档:对参数和返回值有介绍
'函数定义过程中的name是叫形参’是函数文档,其功能与下面额注释是一样的
>>> def MyFirstFunction(name):
'函数定义过程中的name是叫形参'
#因为Ta只是一个形式,表示占据一个参数位置
print('传递进来的' + name + '叫做实参,因为Ta是具体的参数值!')
>>> MyFirstFunction('小甲鱼')
- 函数文档的使用方法
类似的可以查看print函数的函数文档
2.关键字参数
- 关键字参数,用在调用函数的实参的位置,其目的就是给形参下一个定义,这样的话,python会按照关键字去索引,而不是用顺序去索引
3.默认参数
- 默认参数(即形参中给定默认值,则在未给实参时会以默认值输出)
4.收集参数(可变参数)
- print本身就使用了可变参数,print(xxx,xxx,xxx),用逗号隔开,会将其打包成元组,放到*objects中去
- 测试1
- 测试2,若收集参数后面还有自己其他的定制的参数,那么在调用函数的时候就应该使用关键字参数来定制,否则python会将所有实参作为收集参数的范畴了
- 测试3:函数中有可变参数,但是后面还有其他参数,建议将其他参数设置为默认参数
5.函数与过程
- 过程procedure是简单,特殊且没有返回值的
- 函数是有返回值的
python的所有函数都有返回值:如果有返回值,函数则返回对应值;如果没有,则返回None - python返回单个值,可以是一个int类型
python返回多个值,既可以用list,也可以用tuple,默认是tuple元组
6.局部变量与全局变量
- 局部变量:在局部生效如在函数中定义的变量
- 全局变量:作用于整个模块。函数内若试图修改全局变量,Python会新建一个同名局部变量用于存储修改值,原全局变量的值不变。不要在函数内部去修改全局变量。
7.函数嵌套和闭包
- 函数中使用global
- 嵌套函数(内部函数)
- 闭包closure,函数式编程lsp
若在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被仍为是闭包。
return FunY直接返回函数对象 - x=5对于Fun2()来讲是非全局变量的局部变量,在Fun2()中试图对x修改,则外部的x则会被屏蔽起来,对于Fun2()来说x是局部变量,根本就没有定义,具体看报错
- 由于列表不存放在栈里面,所以可以做如下的修改:
- 使用nonlocal,声明x不是局部变量,也可以
8.lambda表达式
- lambda表达式用法。lambda表达式是匿名函数,没有名字def
lambda x : 2 * x +1
x是参数,2* x +1是表达式
返回值是函数对象
- 测试:
- lambda表达式的作用
1)Python写一些执行脚本时,使用lambda就可以省下定义函数的过程,比如说我们只是需要写一个简单的脚本来管理服务器时间,我们就不需要专门定义一个函数然后再写调用,使用lambda就可以使得代码更加精简。
2)对于一些比较抽象并且整个程序执行下来只需要调用一两次的函数,有时候我们个函数起个名字也是比较头疼的问题,使用lambda就不需要考虑命名问题。
3)简化代码的可读性,由于普通的函数阅读经常要跳到开头def定义部分,使用lambda函数可以省去这样的步骤。 - 两个重要的BIF
1)过滤器filter(function or None,iterable):两个参数为函数和可迭代的序列,函数定义了过滤的规则,默认过滤出真的部分。
2)map(function or None,iterable):同filter()的两个参数相同,这个内置函数的作用是:将序列的每一个元素作为函数的参数进行运算加工,直到可迭代序列的每个元素都加工完毕,返回所有加工后的元素构成的新序列。
从help文档中可以看到filter需要接收2个参数 - 测试:
使用None,将非True的内容过滤掉 - 使用函数
9.递归
- 设置递归深度
sys.setrecursionlimit(1000000)
100层是py3的保护,1000是py2的保护
- 递归必须满足哪两个基本条件
(1)函数调用自己;
(2)函数设置了正确的返回值。 - eg:•写一个求阶乘的函数
正整数阶乘指从1乘以2乘以3乘以4一直乘到所要求的数。
例如所给的数是5,则阶乘式是1×2×3×4×5,得到的积是120,所以120就是4的阶乘。
假设我们n的值传入是5,那么:
非递归方式
def factorial(n):
result = n
for i in range(1, n):
result *= i
return result
number = int(input('请输入一个正整数:'))
result = factorial(number)
print("%d 的阶乘是:%d" % (number, result))#格式化为整数类型
递归方式:
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
number = int(input('请输入一个正整数:'))
result = factorial(number)
print("%d 的阶乘是:%d" % (number, result))
- 测试:
- 斐波那契数列的迭代实现
坑爹的兔子:我们都知道兔子繁殖能力是惊人的,如下图:
我们可以用数学函数来定义:
求:们需要求出经历了20个月后,总共有多少对小兔崽子?(迭代 vs 递归)
迭代:
def fab(n):
n1 = 1
n2 = 1
n3 = 1
if n < 1:
print('输入有误!')
return -1
while (n-2) > 0:
n3 = n2 + n1
n1 = n2
n2 = n3
n -= 1
return n3
result = fab(20)
if result != -1:
print('总共有%d对小兔崽子诞生!' % result)
递归:
def fab(n):
if n < 1:
print('输入有误!')
return -1
if n == 1 or n == 2:
return 1
else:
return fab(n-1) + fab(n-2)
result = fab(35)
if result != -1:
print('总共有%d对小兔崽子诞生!' % result)
- 测试:
- 汉诺塔
n代表要移动的盘子数量,x,y,z代表三个针 - •对于游戏的玩法,我们可以简单分解为三个步骤
–将前63个盘子从X移动到Y上。
–将最底下的第64个盘子从X移动到Z上。
–将Y上的63个盘子移动到Z上。
•问题一:将X上的63个盘子借助Z移到Y上;
•问题二:将Y上的63个盘子借助X移到Z上。 - eg:
def hanoi(n, x, y, z):
if n == 1:
print(x, ' --> ', z)
else:
hanoi(n-1, x, z, y) # 将前n-1个盘子从x移动到y上
print(x, ' --> ', z) # 将最底下的最后一个盘子从x移动到z上
hanoi(n-1, y, x, z) # 将y上的n-1个盘子移动到z上
n = int(input('请输入汉诺塔的层数:'))
hanoi(n, 'X', 'Y', 'Z')
- 测试:
- 参考:第十七课:函数:Python的乐高积木,小甲鱼零基础入门学习python笔记,第十八课:函数:灵活即强大,第十九课:函数:我的地盘听我的,第二十一课:函数:lambda表达式,第二十二课:函数:递归,第二十三、二十四课:函数:这帮小兔崽子和汉诺塔