一、递归
递归就是函数调用自身的过程,先递推,然后回归得到目标结果。
注意:使用递归必须要有终止条件,否则函数会不停地调用本身无法停止。
接下来会具体举一些栗子证明递归在函数使用过程中可以简化代码:
1.递归可以有循环的效果
def fun(x): #x为整数
if x>0:
print(x,end=" ")
x-=1
fun(x)
n = int(input())
fun(n)
2.迭代和递归实现阶乘
1).用迭代实现阶乘
def t(n):
if n == 1 or n == 0:
return 1
else:
return n*t(n-1)
n = int(input())
print(t(n))
2).用递归实现阶乘
原理:当n=1或n=0时阶乘为1;n大于1时阶乘就等于n*factRecur(n-1)
def factRecur(n):
if n == 1 or n == 0:
return 1
else:
return n*factRecur(n-1)
n = int(input())
print(factRecur(n))
完成回归过程
3).经典递归问题:汉诺塔
第一步:n=1时,直接把盘子从A移到C。而n>1时需要用递归解决先把盘子分为两部分,第一部分为1个,第二部分为n-1个看为一个整体。
第二步:n>1时,递推过程:第一次调用函数先把n-1个盘子当为整体从A借助C移动到B,输出打印本次过程剩下最后一个盘子从A移动到C。
第三步:n>1时,回归过程:第二次调用函数先把n-1个盘子当为整体从B借助A移动到C。
在第二步和第三步执行时不用在代码里写出移动每个盘子的过程,用递归这种方法简化过程,由电脑自己推出过程。如果不用递归解决汉诺塔问题那么就需要更加复杂的程序(比如用栈堆的方式解决问题)。
count = 0
def hanoi(n,a,b,c):
global count
if n > 0:
hanoi(n-1,a,c,b)
print("Moving %s to %s"%(a,c))
hanoi(n-1,b,a,c)
count += 1
n = int(input("请输入一个正整数:"))
hanoi(n,'A','B','C')
print(count)
#递归特点:1.不断调用自己的函数 2.结束函数(一定条件下)
很多时候用递归解决问题,会简化程序,但是递归有递推的过程会占用大量空间。
二、lambda函数
lambda 参数1,参数2,...,参数n : 表达式 (lambda函数相当于是一个化简后的函数)
1). lambda也可以当作函数调用
s = lambda x:x**2
n = int(input())
re = s(n)
print(re)
2).lambda和sort()或sorted()应用
lambda函数的作用是让整个l重新排列的依据是按每个人的成绩从低到高排序
l = [{"name": "Alice", "grade": 80},{"name": "Charlie", "grade": 70},{"name": "Bob", "grade": 90}]
l.sort(key=lambda x:x["grade"])
print(l)
lambda函数的作用先把列表里所有元素转化为int类型相互之间可以比较大小,然后是按数字大小从低到高排序
r = ["9","1","4","5","3","0"]
re = sorted(r,key=lambda x:int(x))
print(re)
三、闭包
函数中的局部变量(函数内部创建的变量),在函数执行完成后,这个局部变量就会自动销毁。如下:函数执行完后,从外部读取局部变量,这个时候却显示它没有被定义。
闭包特点:
1.嵌套函数的外层具有记忆功能(外层函数中表达式或局部变量)。
2.内层函数作为返回值返回给外层函数。
但是有一个方法可以延长函数中局部变量的“性命”,就是闭包函数。闭包是一种函数,它是由另一个函数返回的内部函数,并且这个内部函数引用了外部函数的变量,即使外部函数已经执行完毕,内部函数仍然可以访问外部函数的变量。这个被内部函数引用的外部函数的变量称为自由变量。
def outer_function(x):
def inner_function(y):
return x+y
return inner_function
c = outer_function(10)
print(c)
print("-------------")
print("result=",c(5))
代码解释:
outer_function
:
1.接受一个参数x。
2.定义了 inner_function,这个内部函数接受一个参数y,并将x和y相加。
3.最后返回 inner_function。
创建闭包:
1. 调用 outer_function(10) 时,它会返回 inner_function,同时 inner_function 会记住 x 的值为 10。这个返回的 inner_function 就是一个闭包,因为它记住了 x 的值。
2.当调用c(5)时,实际上是调用inner_function(5),由于闭包的特性,它会将之前记住的x(即 10)和y(即5)相加,得到 15。
闭包的应用:
1.数据隐藏和封装:保护函数内部数据不被外部访问。
2.函数功能多样化:写一个函数框架实现多种功能。
函数闭包里可以用nonlocal关键字在内部函数修改外部函数的变量。
def outer():
x = 10
def inner():
# 错误写法
# x += 1
# 正确写法
nonlocal x
x += 1
return x
return inner
closure = outer()
print(closure())
7.总结
1).闭包是由另一个函数返回的内部函数,内部函数引用了外部函数的变量。
2).闭包可以用于数据隐藏、封装、函数工厂等场景。
3).在内部函数中修改外部函数的变量时,需要使用nonlocal关键字。
闭包可以用于保持状态,以及代码简洁性是 Python 函数式编程的重要概念,通过合理使用闭包,可以写出简洁、优雅和功能强大的代码,同时能够更好地管理函数的状态和变量。
四、装饰器
函数也可以作为参数传给另外一个函数,这时候就要用到装饰器了。装饰器可以用于记录函数执行的时间、在不改变原函数的情况下,为函数增加额外的功能、可以在类中使用...
装饰器特点:多个装饰器在一起时,执行程序是从下到上。
没有用装饰器:
import time
def time_(fun):
start_time = time.time()
fun()
end_time = time.time()
print(f"一共耗费时间执行fun(x,y)函数时间为:{end_time-start_time}秒")
def fun():
time.sleep(1)
print("Hello World!")
time_(fun)
使用装饰器:
import time
def time_(fun):
def t():
start_time = time.time()
fun()
end_time = time.time()
print(f"一共耗费时间执行fun(x,y)函数时间为:{end_time-start_time}秒")
return t
@time_
def myfun():
time.sleep(1)
print("Hello World!")
myfun()