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目前解决不了,所以不建议使用,知道就行。