了解闭包之前我们要先知道什么是函数式编程,什么是调用函数,什么是引用函数。
# 函数式编程:把函数作为函数的参数以及返回值的变成方式
# def work1():
# print('这是被引用的函数')
# #调用函数
# work1()
# #引用函数
# w = work1 #地址指针指向这个地址
#
# print(id(work1))
# print(id(w))
def wrapper(): #外层
print('start')
def inner(): #内层
print('inner')
print('end')
return inner #外层返回内层函数名
# # 1:
wrapper() #只运行了外层
# 2:
# inner = wrapper() #运行了外层和内层
# inner()
对调用、引用函数有了一定了解后,就可以接触闭包概念了
# 闭包是由函数及其相关的引用环境组合而成的实体
# (即:闭包=函数+引用环境)
# (想想Erlang的外层函数传入一个参数a, 内层函数依旧传入一个参数b, 内层函数使用a和b, 最后返回内层函数)
def line(a,b):
def line_obj(x):
nonlocal a # global适用于函数内部修改全局变量的值 nonlocal适用于嵌套函数中内部函数修改外部变量的值
a += 1
return a*x+b #返回函数对值的操作
return line_obj #返回内部定义的函数名,但不运行
line1 = line(1,1) #将line1的指针指向line的地址,这部操作实际上是引用line里定义的函数line_obj的函数名
result = line1(2) #实质上传参并运行line_obj
print(result)
闭包的简单应用:求一个平均数
'''用闭包求平均数'''
def A(a,b):
def B():
nonlocal a,b
c = (a+b)/2
return c
return B
a=A(1,3)
print(a())
装饰器是闭包的应用,下面是一个简单的装饰器
def one(func):
print('1')
def two():
print('2')
func()
return two
# @ 是装饰器的语法糖
@one #等价于 demo = one ( demo )
def demo():
print('3')
demo()
下面是一个简单的多层装饰器
# 装饰器避免冗余代码
def w1(func):
def inner():
print('w1 inner')
func()
return inner
def w2(func):
def inner():
print('w2 inner')
func()
return inner
# @ 是装饰器的语法糖
# 多个装饰器的调用顺序是自下往上,但是运行时的执行顺序是自上往下!!!
@w2 # f2 = w2(f2)
@w1 # f1 = w1 (f1)
def f1():
print('f1')
f1()
装饰器工厂就是生产装饰器的函数,下面是一个简单的装饰器工厂函数:
# 根据参数不同,生产不同的装饰器
def factory(arg=None): #工厂函数
def timefun(func): #装饰器
def inner():
if arg:
print('有')
else:
print('没')
return func()
return inner
return timefun
@factory(1) #这里的()一定要有
def f():
print('f')
f()