python基础三_03_闭包_装饰器_递归函数

python基础三_03_闭包_装饰器_递归

导读:
本文主要记录自己学习python3基础中闭包、装饰器和递归的要点知识和例子;仅供自己梳理。搞清楚函数的作用域是理解闭包,装饰器的前提。

一、闭包

1.什么是闭包?

(1).闭包的定义
·闭包函数必须有内嵌函数;
·闭包函数必须返回内嵌函数;
·内嵌函数可以引用该嵌套函数上一级namespace(命名空间)中的变量;
(2).闭包的好处
·使代码变得简洁;
·提高代码的拓展性;

2.为什么要用闭包?

闭包能够实现一个封闭的作用域

3.怎么用闭包?

(1).定义一个闭包函数
对于初学者,就算理解不了闭包的实质,但是这种写法是固定的,记下来就行。
# 定义
def outer():
    # 内嵌函数
    def inner():
        print('我是inner')
    # 返回内嵌函数。python里变量都是指针,返回函数其实就是返回了一个内存地址
    return inner	# 是返回函数,不是调用函数,切忌写成inner()

# 调用
new_Func_Name = outer()
new_Func_Name()
# 这两步调用的是内嵌函数inner,类似于:outer()()
# print(func)
# <function outer.<locals>.inner at 0x00000209DE974048>
# 可以看到func就是inner,所以func的调用就是inner的调用。func() === inner() 
(2).理解闭包
闭包能够实现一个封闭的作用域,内嵌函数inner可以使用外部函数的变量。说白了,闭包,闭包,闭的就是作用域,变量。
例一:内嵌函数使用外部函数的变量
def outera():
    num = 20
    def innera(num_in):
        print('我是inner,num_in is {}'.format(num_in))
        return num + num_in
    return innera

funa = outera()
# 调用
print(funa(40))
print(funa(50))
print(funa(1))

怎么样?有点明白什么是闭包了吗?

例:还可以在进行传参
def outerb(num):
    def innerb(num_in):
        print('我是inner,num_in is {}'.format(num_in))
        return num + num_in
    return innerb

funb = outerb(20)
#
print(funb(2))
例:还可以这样
def outerc(num):
    c = 100
    def innerc(num_in):
        print('我是inner,num_in is {}'.format(num_in))
        return num + num_in + c
    return innerc

func = outerc(20)
#
print(func(2))

二、装饰器

如果理解了闭包,那么装饰器就很好理解了,前面说的闭包就是它的前身。

1.装饰器的定义

装饰器用来在原有的函数上增添新的代码需求,装饰器是程序开发中经常会用到的一个功能。

2.应用场景

当我们已经写好一个函数时,项目也已经上线了,突然客户想要增添一个需求,让这个函数处理的更加细致,这个就可以用到装饰器了;
淘宝登录验证。在使用淘宝购物,

3.执行顺序:

先返回内嵌函数–>有参数直接传参给内嵌函数–>执行内嵌函数

4.结合典例理解装饰器

场景:线上代码如下,在不改变源码的情况下,要求增添一个新功能,输出:‘I come from china’。要求分别使用闭包和装饰器来实现
def func1():
    print('this is ydxq')
def func2():
    print('this is bjl')
#
func1()
func2()
需求的输出结果如下:

在这里插入图片描述

法一:闭包实现
# 源代码
def func1():
    print('this is ydxq')
    
# 增加闭包函数
def outer(func):
    def inner():
        func()
        print('I come from china')
    return inner

# f1 = outer(func1)
# f1()
# 由于python是动态类型语言,那我们干脆直接重新赋值一下func1,说白了就是把这个'f1'改成'func1'
func1 = outer(func1)
func1()    # 这样是不是实现了咱们添加功能的需求?秀吧?
法二:装饰器实现

装饰器其实就是闭包更秀一点的写法,叫 ‘@语法糖’,采用装饰器的写法,感觉代码更加整洁。

# 先写一个闭包
def outer1(func):
    def inner1():
        func()
        print('I come from china')
    return inner1

# 然后在原来的函数上面,写'@+闭包函数名'
@outer1    # 这个意思就是:func1 = outer(func1)
def func1():
    print('this is bjl')
# 调用
func1()

可以return

def outer2(func):
    def inner2(name):
        print(name)
        data = func()
        print('I come from china')
        return data+name
    return inner2


@outer2
def func2():
    print('func4 this is bjl')
    return 'coll '
# 调用
print(func2('ydxq'))

当然,我们也可以传参

def outer3(func):
    def inner3(name):
        # name的作用域只有inner3里面这块
        print(name)
        func()
        print('I come from china')
    return inner3

@outer3    # 这个意思就是:func1 = outer(func1)
def func3():
    print('this is bjl')

func3('ydxq')

可以这样

def outer4(func):
    def inner4(name):
        # name的作用域只有inner3里面这块
        print(name)
        func(name)
        print('I come from china')
    return inner4

@outer4    # 这个意思就是:func1 = outer(func1)
def func4(name):
    print('func4 this is bjl, {}'.format(name))

func4('YDXQ')

甚至可以这样

def outer5(func):
    def inner5(name,*args,**kwsrgs):
        data = func(*args,**kwsrgs)
        print('I come from china')
        return data + name
    return inner5

@outer5    # 这个意思就是:func1 = outer(func1)
def func5(name,*args,**kwsrgs):
    print('this is bjl')
    print(name,*args,**kwsrgs)
    return 'coll'

#func5('WSD')
print(func5('WSD',1,2,3,4,{'a':'1','b':'2','c':'3'}))

三、递归函数(不是重点)

1.递归函数简介

(1).函数的内部可以调用其他函数
def func1():
    print('func1')
    
def func2():
    print('func2')

# main函数用于控制函数调用顺序,约定俗称的名字还有:run()、work()等
def main():
    func2()
    func1()

main()

在这里插入图片描述

(2).既然在函数当中能够调用其他函数,那在函数中调用自己可以吗?可以的
如果一个函数在内部调用自身,这个函数就是递归函数,递归会形成一个深度循环!

在这里插入图片描述

2、示例

例一:阶乘
法一:for 循环,广度循环
num = int(input('>>>'))
result = 1
for i in range(1,num+1):
    result *= i

print(result)

在这里插入图片描述

法二:while循环,深度循环
i = 1
result = 1
num = int(input('>>>'))

while i < num+1:
    result = result * i
    i += 1

print(result)

在这里插入图片描述

法三:递归函数:注意递归出口的设置
num = int(input('>>>'))
def test(n):
    # 递归出口,如果没有递归出口就会造成栈溢出的情况
    if n == 1:
        return 1
    else:
        return n * test(n-1)

result = test(num)
print(result)

在这里插入图片描述

注意递归出口的设置
num = int(input('>>>'))
def test(n):
        return n * test(n-1)

result = test(num)
print(result)

在这里插入图片描述

例二:斐波那契数列
法一:普通while循环,动态类型语言,序列解包赋值
def feibo(n):
    a,b = 0,1
    c = []
    while n > 0:
        c.append(b)
        a,b = b,a+b
        n -= 1
    print(c)
    
feibo(5)

在这里插入图片描述

法二:递归函数
n = 5
def feibo(n):
    # 两个条件控制递归出口
    if n <= 1:
        return n
    if n == 2:
        return 1
    return feibo(n - 1) + feibo( n - 2)

res = [feibo(i) for i in range(1,n+1)]
print(res)

在这里插入图片描述

解决栈溢出-----尾递归

return 后面没有表达式 就是尾递归。但是python目前解决不了,所以不建议使用,知道就行。

四、总结与参考链接

1.总结

(1).想要真正理解闭包装饰器,首先要理解函数的作用域。因为闭包就是一个封闭包裹了它所能使用的作用域的函数。
(2).这部分的内容对初学者来说确实不好理解,比如我(小声比比)。所以建议大家多从这三个方向思考:是什么?为什么?怎么用?希望能帮助你理清思路。另外本人也是新手上路,如果有不足和错误的地方希望您能批评指正。

2.参考链接:

作用域和闭包

python中闭包详解

为什么要使用闭包和如何使用闭包

什么是闭包?为什么使用闭包?闭包的缺点?

递归参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值