闭包的构成条件:
在函数嵌套(函数里面再定义函数)的前提下
内部函数使用了外部函数的变量(还包括外部函数的参数)
外部函数返回了内部函数
简单闭包
def fun_out(num1):
# 定义外部函数
def fun_inner(num2):
# 内部函数使用了外部函数的变量
result = num2 + num1
print("结果是: ", result)
# 外部函数返回了内部函数,这里返回的内部函数就是闭包
return fun_inner
f = fun_out(1) # 创建闭包实例
f(2)
f(3)
-
当返回的内部函数使用了外部函数的变量就形成了闭包
-
闭包可以对外部函数的变量进行保存
闭包的作用
*闭包的作用: 闭包不仅可以保存外部函数的变量还可以提高代码的可重用性(不需要再手动定义额外的功能函数*
def config_name(name): # 定义外部函数
# 内部函数使用了外部函数的变量
def say_info(info):
print(name + ":" + info)
return say_info
tom = config_name("Tom")
tom("你好!")
tom("你好,在吗?")
jerry = config_name("jerry")
jerry("不在,不和你玩!")
装饰器的功能特点:
-
不修改已有函数的源代码
-
不修改已有函数的调用方式
-
给已有函数增加额外的功能
def check(fn):
# 追加一个登陆验证的功能
def inner():
print("请先登陆!")
fn()
return inner
def comment():
print("发表评论!")
comment = check(comment)
comment()
-
闭包函数有且只有一个参数,必须是函数类型,这样定义的函数才是装饰器。
-
写代码要遵循开放封闭原则,它规定已经实现的功能代码不允许被修改,但可以被扩展。
装饰器的语法糖写法
如果有多个函数都需要添加登录验证的功能,每次都需要编写func = check(func)这样代码对已有函数进行装饰,这种做法还是比较麻烦。
Python给提供了一个装饰函数更加简单的写法,那就是语法糖,语法糖的书写格式是: @装饰器名字,通过语法糖的方式也可以完成对已有函数的装饰
糖写法演示
@check
def comment():
print("发表评论")
@check
==> comment = check(comment)
使用装饰器添加登陆验证功能
def check(fn):
print("装饰函数执行了")
def inner():
print("请登陆....")
fn()
return inner
@check # @check 等价于 comment = check(comment)
def comment(): # 装饰器的执行时间是加载模块时立即执行。
print("发表评论!")
comment() # 调用函数
使用装饰器对函数执行时间进行统计
import time
def get_time(func):
# 定义函数的嵌套,
def inner():
begin_time = time.time()
func() # 内部函数使用了外部函数的变量包括参数
end_tiem = time.time()
print("函数执行花费了:%f" % (end_tiem-begin_time))
print("测试:",end_tiem-begin_time)
return inner # 外部函数返回了内部函数
@get_time # 等价于test = get_tiem(test)
def test():
for i in range(10000000):
i += 1
print(i)
test()
带有不定长参数的装饰器
*args和**kwargs都是可变长度参数的方式
*args:用于传递不定数量的位置参数,它会将所有的位置参数打包成一个元组(tuple)。
**kwargs:用于传递不定数量的关键字参数,它会将所有的关键字参数打包成一个字典(dictionary)。
def logging(fun): # 这里fun = sum_num
# *args和**kwargs都是可变长度参数的方式,它们之间的区别如下:
#
# *args:用于传递不定数量的位置参数,它会将所有的位置参数打包成一个元组(tuple)。
#
# **kwargs:用于传递不定数量的关键字参数,它会将所有的关键字参数打包成一个字典(dictionary)。
def inner(*args, **kwargs):
print("--正在努力计算--")
fun(*args, **kwargs) # 调用sum_num
return inner
@logging # 这里sum_num = logging(sum_num)
# 执行到这里就有 sum_num = inner
def sum_num(*args, **kwargs):
result = 0
for vaules in args: # args元组形式
result += vaules
for vaules in kwargs.values(): # kwargs将所有参数转化为字典类型的数据
result += vaules
print(result)
sum_num(1, 2, a=10)
通用装饰器
# 通用装饰器标签:闭包,查漏,函数,Python,sum,num,result,print,def From: https://www.cnblogs.com/liam-sliversucks/p/17467906.html
def logging(fn): # 2,将函数sum_num 作为参数传递
def inner(*args, **kwargs):
print("--正在努力计算--")
result = fn(*args, **kwargs) # fn = sum_num, fn = subtraction
return result
return inner
# 使用语法糖装饰函数
@logging # 1 这里sum_num = logging(sum_num) -- 之后sum_num = inner,调用sum_num相当于调用inner
def sum_num(*args, **kwargs):
result = 0
for value in args:
result += value
for value in kwargs.values():
result += value
return result
@logging # 3,这里subtraction = logging(subtraction) 之后subtraction = inner,调用subtraction相当于调用inner
def subtraction(a, b):
result = a - b
print(result)
result = sum_num(1, 2, a=10) # 调用sum_num 函数即调用inner函数,其中fun()为sum_num()本体
print(result)
subtraction(4, 2)