【Python查漏补缺(一)】闭包和装饰器
闭包的构成条件:
在函数嵌套(函数里面再定义函数)的前提下
外部函数返回了内部函数
简单闭包
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
==> comment = check(comment)
使用装饰器添加登陆验证功能
def check(fn):
print("装饰函数执行了")
def inner():
print("请登陆....")
fn()
return inner
使用装饰器对函数执行时间进行统计
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 # 外部函数返回了内部函数
带有不定长参数的装饰器
*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
通用装饰器
# 通用装饰器
def logging(fn): # 2,将函数sum_num 作为参数传递
def inner(*args, **kwargs):
print("--正在努力计算--")
result = fn(*args, **kwargs) # fn = sum_num, fn = subtraction
return result
return inner
# 使用语法糖装饰函数