欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python笔记 | 递归函数/回调函数/闭包函数/匿名函数

程序员文章站 2024-02-24 14:52:28
...

一、递归函数

????递归是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象。在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知。
????递归函数就是定义了一个函数,然后在函数内,自己调用了自己这个函数。
????递归函数内必须要有结束,不然就会一直调用下去,直到调用的层数越来越多,栈溢出。
????递归函数是一层一层的进入,再一层一层的返回。

举例

例①:

# 初步认识递归函数  3 2 1 0
def digui(num):
    print(num) # 3 2 1 0
    if num > 0:        # 检测当前的值是否到了零
        digui(num-1)   # 调用函数本身
    print(num) # 0 1 2 3  不写这行就只会输出3210

digui(3)

'''
解析当前递归函数的执行过程:
digui(3) ==> 3 
    digui(3-1) ==> 2
        digui(2-1) ==> 1
            digui(1-1) ==> 0
            digui(0) ==> 0
        digui(1) ==> 1
    gidui(2) ==>2
digui(3) ==> 3
'''
'''
例子:
        就像是以前上学一样,你坐在最后面一排,最前面有个漂亮的妹子,你想要要的电话,这时怎么办?
        你去拍一拍前面同学的肩膀,让他帮我问问前面妹子的电话,于是这个同学继续拍一拍前面同学的肩膀
        让他问问前面妹子的电话,之后一直从后向前传递这个信息,一只在重复这个过程,
        直到最后一个通过拍了最前面妹子的肩膀,要到了电话之后一层层的返回到最开始的同学手中
'''

例②:阶乘:

def  factorial(n):
    if n == 1:
        return 1
    else:
        return n* factorial(n-1)

res =  factorial(7)
print(res)  #运行结果:5040

例③:斐波那契数列:

def fib(n):
    if n == 1 or n == 2:
        return 1
    else:
        print(n-1,n-2)
        return fib(n-1) + fib(n-2)

res = fib(6)
print(res)

'''
运行结果:
5 4
4 3
3 2
2 1
2 1
3 2
2 1
8

'''

二、回调函数

函数中的参数可以是任意类型的,那参数能不能是一个函数呢?

????如果在一个函数中要求传递的参数是一个函数作为参数,并且在函数中使用了传递进来的函数,那么这个函数我们就可以称为是一个回调函数(callback)
????回调函数是一个通过函数指针调用的函数。把函数的指针(地址)作为参数传递给另一个函数时,这个指针被用来调用其所指向的函数。

map() sorted() filter()  reduce()等

定义一个函数,函数中的一个参数要求是另一个函数

例①:

# 带有回调函数参数的函数
def func(f):
	print(f,type(f))
	f()  # 在函数中调用了传递进来的行参函数

# 回调函数
def love():
	print('123')

func(love)  #返回123

例②:

def func(x,y,f):
    '''
    当前这个函数接收两个数值,并把这两个数值传递给第三个参数进行运算
    x,y  int
    f     function
    :return:
    '''
    print(f(x,y))

func(2,3,pow)   #返回8  pow:计算幂次方,pow(x,y)表示计算x的y次方
#func(2,3,sum)  #返回5  对应f([x,y]),sum要加[]

三、闭包函数

???? 在一个函数内返回了一个内函数, 并且这个返回的内函数还使用了外函数中的局部变量,就是闭包函数。
????闭包(Closure),顾名思义,就是一个封闭的包裹,里面包裹着*变量,如在类里面定义的属性值一样,*变量的可见范围随同包裹一起,哪里可以访问到这个包裹,哪里就可以访问到这个*变量。
????可以将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成:外函数和内函数。在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
????闭包在python中很常见。比如python中的装饰器Decorator,假如需要写一个带参数的装饰器,那么一般都会生成闭包

为什么要使用闭包?
闭包避免了使用全局变量,此外闭包允许将函数与其所操作的某些数据(环境)关联起来。

1.特点:

(1)在外函数中定义了局部变量,并且在内部函数中使用了这个局部变量

(2)在外函数中返回了内函数,返回的内函数就是闭包函数

2.作用:

​ ⚠主要在于保护了外函数中的局部变量,既可以被使用,又不会被破坏

3.检测一个函数是否为闭包函数:

​ 可以使用 函数名.__closure__,如果是闭包函数返回 cell

4.伪代码

def 外层函数(参数):
	def 内层函数():
		print('内层函数执行',参数)
	return 内层函数

内层函数的引用 = 外层函数('传入参数')
内层函数的引用()

5.举例:

def outer(a):  #outer是外函数
	def inner(b):  #inner是内函数
		print(a+b) #在内函数中用到了外函数临时变量
	return inner #外函数的返回值是内函数的引用
res = outer(5) #res = inner
res(10) #15,res存了外函数的返回值,也就是内函数的引用,这里相当于执行inner函数

原始函数:

# 钱包
money = 0

# 工作
def work():
    global money
    money += 100

# 加班
def overtime():
    global money
    money += 200

# 购物
def buy():
    global money
    money -= 50

# # 工作3次加班1次购物1次:
# work()
# work()
# work()
# overtime()
# buy()
# # 银行垮台了,没钱了,即money强行改成0
# money = 0 
# work()
# print(money)

改造:

# 定义一个函数
def person():
    money = 0     # 函数中定义了一个局部变量
    def work():    # 工作 定义的内函数
        nonlocal money   # 在内函数中使用了外函数的临时变量
        money += 100
        print(money)
    return work     # 在外函数中返回了内函数,这个内函数就是闭包函数

res = person() # return work , res = work
res() # res() == work()
res() #200
res() #300
res() #400
# 此时就不能在全局中对局部变量money进行任何操作了,

四、匿名函数 lambda表达式

????在python中使用lambda表达式来定义匿名函数
????当我们需要做一些简单的事情并且希望快速完成工作而不是正式命名函数时,匿名函数是理想的选择
???? lambda是一个表达式,不能写太复杂的逻辑,因此不适合具有控制流语句的函数

????注意:lambda表达式仅仅是一个表达式,不是一个代码块,所以lambda又称为一行代码的函数

​ ???? lambda表达式也有行参,并且不能访问除了自己的行参之外的任何数据,包括全局变量

1.语法

lambda [参数列表]:返回值

lambda 参数列表: 真区间 if 表达式判断 else 假区间

2.举例:

①封装一个函数做加法运算

# 普通函数
def sum(x,y):
    return x+y
print(sum(2,3))   #返回5

# 改成lambda表达式来封装
res = lambda x,y:x+y
print(res(2,3))

②带有分支结构的lambda 表达式

res = lambda x: True if x**2>=10 else False
print(res(3))  #返回False
print(res(8))  #返回True

③和其他函数一起使用

dict={'X':1,'Y':2,'Z':3}
sorted(dict,key=lambda dict[i]%3)   #返回['Z', 'X', 'Y']