闭包定义

在函数嵌套(函数里面再定义函数)的前提下,内部函数使用了外部函数的变量或参数,并且外部函数返回了内部函数。于是将这个使用外部函数变量或参数的内部函数称为闭包

  • 可以保存外部函数内的变量

参数和变量

  1. # coding=utf-8
  2. def func_out(): # 定义一个外部函数
  3. num1 = 10 # 外部函数变量
  4. def func_inner(num2): # 定义一个内部函数
  5. result = num1 + num2 # 内部函数使用外部函数的变量,可以将外部函数变量暂时保存
  6. print(result)
  7. return func_inner # 外部函数返回内部函数
  8. result = func_out() # 结果是内部函数 result = func_inner
  9. result(1) # 函数调用,因为返回的是函数
  10. ----------------------------------------------------------------------------------------------
  11. >>> 11
  1. # coding=utf-8
  2. def conf_name(name):
  3. def inner(msg):
  4. print(name + ':' + msg) # 内部函数调用外部函数参数
  5. return inner
  6. kuma = conf_name('kuma')
  7. jerry = conf_name('jerry')
  8. kuma('小姐姐过来玩呀')
  9. jerry('滚犊子')
  10. --------------------------------------
  11. >>> kuma:小姐姐过来玩呀
  12. >>> jerry:滚犊子

修改外部变量

  1. # coding=utf-8
  2. def func_out():
  3. num1 = 10
  4. def func_inner():
  5. nonlocal num1 # 闭包中使用关键字 nonlocal 声明全局变量
  6. num1 = 20
  7. result = num1 + 10
  8. print(result)
  9. return func_inner
  10. result = func_out()
  11. result()
  12. ----------------------------------
  13. >>> 30

装饰器

就是给已有函数增加额外功能的函数,本质就是一个闭包函数

  • 不能修改已有函数的源代码
  • 不修改已有函数的调用方式
  • 给已有函数增加额外的功能
  • @装饰器名字,完成对已有函数的装饰 (装饰器的语法糖写法) ```python

    coding=utf-8

def decorator(func): def inner(): func() # 内部函数使用外部有且仅有一个并且是函数类型的参数 print(‘恭喜您登录成功’) return inner

@decorator # 要写在已有函数前(后面不能写其他代码),相当于 comment = decorator(comment)

def comment(): print(‘请您输入密码’)

comment = decorator(comment) # 如果不写语法糖写法

comment()

请您输入密码 恭喜您登录成功 ```

被装饰函数有参数

  1. # coding=utf-8
  2. def decorate(func):
  3. def inner(a, b):
  4. print('正在执行运算') # 对已有函数进行装饰
  5. func(a, b)
  6. return inner
  7. @decorate # 等价于 add_num = decorate(add_num)
  8. def add_num(num1, num2):
  9. result = num1 + num2
  10. print(result)
  11. add_num(1, 2)

内部函数的类型和被装饰的函数的类型是保持一致的

被装饰函数有返回值

  1. # coding=utf-8
  2. def decorate(func):
  3. def inner(a, b):
  4. print('正在执行运算')
  5. num = func(a, b)
  6. return num # 内部函数的类型和被装饰的函数的类型是保持一致的,即被装饰函数有返回值内部函数也要有
  7. return inner
  8. @decorate
  9. def add_num(num1, num2):
  10. result = num1 + num2
  11. return result
  12. result = add_num(1, 2)
  13. print(result)

被装饰函数有缺省参数

  1. # coding=utf-8
  2. def decorate(func):
  3. def inner(*args, **kwargs):
  4. print('正在执行运算')
  5. num = func(*args, **kwargs)
  6. return num
  7. return inner
  8. @decorate
  9. def add_num(*args, **kwargs):
  10. result = 0
  11. for i in args:
  12. result += i
  13. for i in kwargs.values():
  14. result += i
  15. return result
  16. result = add_num(1, 2, age=20)
  17. print(result)

多装饰器

  1. # coding-utf-8
  2. def make_p(func):
  3. def inner():
  4. result = '<p>' + func() + '</p>'
  5. return result
  6. return inner
  7. def make_div(func):
  8. def inner():
  9. result = '<div>' + func() + '</div>'
  10. return result
  11. return inner
  12. @make_div
  13. @make_p
  14. def content():
  15. return 'happy kuma'
  16. result = content()
  17. print(result)

由内到外的装饰过程,即 make_div(make_p(content))

装饰器带有参数

  1. # coding=utf-8
  2. def return_decorate(flag):
  3. def decorate(func):
  4. def inner(a, b):
  5. if flag == "+":
  6. print('正在执行加法运算')
  7. else:
  8. print('正在执行减法运算')
  9. func(a, b)
  10. return inner
  11. return decorate
  12. @return_decorate("+")
  13. def add_num(a, b):
  14. result = a + b
  15. print(result)
  16. add_num(1, 2)
  17. @return_decorate("-")
  18. def add_num(a, b):
  19. result = a - b
  20. print(result)
  21. add_num(1, 2)

区别

闭包一定是装饰器,但装饰器不一定是闭包的原因:如果外部函数的参数有且只有一个。并且是函数类型在内部函数使用,那么这个闭包函数就是装饰器。