python闭包&装饰器

1.递归函数:

1.1含义:

如果一个函数在内部不调用其他函数,而是调用它本身的话,这个函数就是递归函数

1.2条件:

1.必须有一个明确的结束条件--递归出口

2.每进行更深一层的递归,问题规模相比上次递归都要有所减少

3.相邻两次重复之间有紧密的联系

1.计算1+2+3+...+100的和

def add(n):
    if n == 1:
        return 1
    else:
        return n+add(n-1)

print(add(100))

2.计算斐波那契数列(1,1,2,3,5,8...)

def funa(n):
    if n==1 or n==2:
        return 1
    return funa(n-1)+funa(n-2)

print(funa(7))

1.3优点:简洁,逻辑清晰,解题更具有思路 

1.4缺点:使用递归函数的时候,需要反复调用函数,耗内存,运行效率低

2.闭包

含义:在嵌套函数的前提下,内部函数使用了外部函数的变量,而且外部函数返回了内部函数,我们就把使用了外部函数变量的内部函数称为闭包

2.1条件:

1.嵌套函数(函数里面在定义函数)

2.内层函数使用外层函数的局部变量

3.外层函数的返回值是内层函数的函数名(注意:返回函数名,而不是inner(),是因为inner函数里参数比较多或者说受到限制时,写法不太规范)

def outer():
    n = 10
    def inner():
        print(n)
    return inner

print(outer())   #<function outer.<locals>.inner at 0x000002405D04B0D8>  返回内部函数的地址
#调用内函数的第一种写法
outer()()   #10
#调用的第二种写法
ot = outer()  #调用外函数
ot()          #调用内函数

带参数的情况

def outer(m):
    n = 10
    def inner(o):
        print(m+n+o)
    return inner

outer(20)(10)

ot = outer(20)
ot(10)

2.2函数引用

函数名里保存了函数所在位置的引用(就是地址)

a = 1  #a只不过是一个变量名,存的1这个数值所在的地址,就是a里面存了数值1的引用
print(a)       #1
print(id(a))   #140719332688144
print(id(1))   #140719332688144

a = 2          #修改a,生成新的值从新赋给变量a
print(id(a))   #140719332688176内存地址发生了改变

def test(): #test也只不过是一个函数名,里面存了这个函数所在位置的引用
    print('这是test函数')
test()
print(test)    #内存地址(引用)<function test at 0x0000017B51DC2F78>
te = test
te()           #通过引用调用函数

2.3每次开启内函数都在使用同一份闭包变量

总结:使用闭包的过程中,一但外函数被调用一次,返回了内函数的引用,虽然每次调用内函数,会开启一个函数,执行后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量。

def outer(m):
    print("outer函数中的值",m)
    def inner(n):
        print("inner函数中的值",n)
        return m+n
    return inner

ot = outer(10)
print(ot(20))    #30
print(ot(50))    #60
print(ot(80))    #90

3.装饰器

3.1.含义:

装饰器本质上是一个闭包函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

3.2.作用:在不改变原有代码情况下给函数添加额外的功能

3.3.条件:

1.不修改源程序或函数的代码

2.不改变函数或程序的调用方法

不用装饰器的方式添加新的功能1.直接添加,2.引入参数

def test1(fn):
    print("读书")
    print("吃饭")
    fn()
def test2():
    print("看电视")
test1(test2)

3.4标准版装饰器

将原有函数名重新定义为以原函数为参数的闭包

#被修饰的函数
def send():
    print("发短信")

def outer(fn):    #外层函数,fn是形参

    def inner():   #内函数
        print("登录")
        fn()    #send() 执行被修饰的函数
    return inner

print(outer(send))   #内层函数地址
outer(send)()        #调用内层函数

3.5语法糖

格式:@装饰器名称

def outer(fn):    #外层函数,fn是形参
    def inner():   #内函数
        print("登录")
        fn()    #send() 执行被修饰的函数
    return inner

@outer   #注意装饰器名称后面不要加上(),前者是引用,后者是返回该函数要返回的值(最好顶格写不要空行)
def send():
    print("发短信")
send()      #登录     发短信

@outer
def send2():
    print("刷抖音")
send2()     #登录      刷抖音

3.6被装饰的函数有参数

3.6.1标准版:

def outer(fn):    #外层函数,fn是形参

    def inner(name):   #内函数
        print(f"{name}是inner中的参数")
        fn()    #func() 执行被修饰的函数
    return inner

def func():
    print("这是被装饰函数")

print(outer(func))   #内层函数地址
outer(func)('panda')        #调用内层函数





def outer(fn):    #外层函数,fn是形参

    def inner(name):   #内函数
        print(f"{name}是inner中的参数")
        fn(name)    #func() 执行被修饰的函数
    return inner

def func(name):
    print("这是被装饰函数")

print(outer(func))   #内层函数地址
outer(func)('panda')   #调用内层函数

3.6.2语法糖

def outer(fn):    #外层函数,fn是形参

    def inner(name):   #内函数
        print(f"{name}是inner中的参数")
        fn(name)    #func() 执行被修饰的函数
    return inner

@outer
def func(name):
    print("这是被装饰函数")

func('panda')

3.7被装饰函数有可变参数*args ,**kwargs

def outer(fn):    #外层函数,fn是形参

    def inner(*args,**kwargs):   #内函数
        print("登录")
        fn(*args,**kwargs)    #func() 执行被修饰的函数
    return inner

def func(*args,**kwargs):
    print(args)
    print(kwargs)

print(outer(func))   #内层函数地址
ot = outer(func)          #调用外层函数
ot('panda',friend='monkey',name='bear')       #登录    ('panda',)       {'friend': 'monkey', 'name': 'bear'}

*args:接收元组的形式,**kwargs:接收字典的形式

3.8多个装饰器

多个装饰器的装饰过程,离函数最近的装饰器先装饰,然后外面的装饰器再进行装饰,由内到外的装饰过程

def deco1(fn):
    def inner():
        return "lucky "+fn()+" day"
    return inner
def deco2(fn):
    def inner():
        return "good "+fn()+" study"
    return inner

@deco1
@deco2
def test():
    return "学python"
print(test())  #lucky good 学python study day

@deco2
def test():
    return "学python"
print(test())  #good 学python study

@deco2
@deco1
def test():
    return "学python"
print(test())  #good lucky 学python day study
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值