推荐文章:
Liunx系列:
2、Linux进阶命令 任务编程系列:
前端技术:
数据库技术:
闭包
1、闭包的介绍
前面学习了函数,知道了当函数调用完,函数内定义的变量都销毁了,但是我们有时候需要保存函数内的这个变量,每次在这个变量的基础上完成一系列的操作,比如:每次在这个变量的基础上和其它数字进行求和计算,那应该如何操作呢
其实可以使用闭包来解决这个需求
闭包的定义:
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。
2、闭包的构成条件
通过闭包的定义,我们可以得知闭包的形成条件:
3、简单闭包的示例代码
# -*- codeing = utf-8 -*-
# @Time : 2021/12/16 9:34 下午
# @Author : 李明辉
# @File : ithui_闭包.py
# @Software : PyCharm
# 闭包的作用:可以保存外变量的函数
# 闭包的形成条件
# 1、函数嵌套
# 2、内部函数使用了外部函数的变量或参数
# 3、外部函数返回了内部函数
# 1、函数嵌套
def func_out():
# 外部函数
num1 = 10
def func_inner(num2):
# 内部函数
# 2、内部函数必须使用外部函数的变量
result = num1 + num2
print("结果:", result)
# 3、外部函数要返回内部函数
return func_inner
# 获取闭包对象
# 这个new_func就是闭包
new_func = func_out()
# 执行闭包
new_func(1)
运行结果:
闭包执行结果的说明:
通过上面的输出结果可以看出闭包保存了外部函数内的变量num1,每次执行闭包都是在num1 = 1 基础上进行计算。
4、闭包的作用
注意点:
5、小结
# 外部函数
def test1(a):
b = 10
# 内部函数
def test2():
# 内部函数使用了外部函数的变量或者参数
print(a, b)
# 返回内部函数, 这里返回的内部函数就是闭包实例
return test2
闭包的使用
1、案例
需求:根据配置信息使用闭包实现不同人的对话信息,例如对话:
张三:到北京了吗?李四:已经到了,放心
2、实现步骤说明
3、功能代码的实现
# -*- codeing = utf-8 -*-
# @Time : 2021/12/16 9:57 下午
# @Author : 李明辉
# @File : ithui_闭包的使用.py
# @Software : PyCharm
# 外部函数接收姓名参数
def config_name(name):
# 内部函数保存外部函数的参数,并且完成睡觉显示的组成
def inner(msg):
print(name + ":" + msg)
# 外部函数要返回内部函数
return inner
# 创建tom闭包实例
tom = config_name("tom")
# 创建jerry闭包实例
jerry = config_name("jerry")
tom("哥们过来一下!")
jerry("兄弟我来了!")
运行结果:
闭包案例说明:
5、小结
修改闭包内使用的外部变量
1、修改闭包内使用的外部变量
修改闭包内使用的外部变量的错误示例:
# -*- codeing = utf-8 -*-
# @Time : 2021/12/16 10:07 下午
# @Author : 李明辉
# @File : ithui_修改闭包内使用的外部函数变量.py
# @Software : PyCharm
def func_out():
num1 = 10
def func_inner():
# 在闭包内修改外部函数的变量
num1 = 20
result = num1 + 10
print(result)
print("修改前的外部变量", num1)
func_inner()
print("修改后的外部变量", num1)
return func_inner
new_func = func_out()
new_func()
执行结果:
正确方式:
# -*- codeing = utf-8 -*-
# @Time : 2021/12/16 10:07 下午
# @Author : 李明辉
# @File : ithui_修改闭包内使用的外部函数变量.py
# @Software : PyCharm
def func_out():
num1 = 10
def func_inner():
# 在闭包内修改外部函数的变量
nonlocal num1
num1 = 20
result = num1 + 10
print(result)
print("修改前的外部变量", num1)
func_inner()
print("修改后的外部变量", num1)
return func_inner
new_func = func_out()
new_func()
执行结果:
2、小结
装饰器
1、装饰器的定义
就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数
装饰器的功能特点:
2、装饰器的示例代码
# 添加一个登录验证的功能
def check(fn):
def inner():
print("请先登录....")
fn()
return inner
def comment():
print("发表评论")
# 使用装饰器来装饰函数
comment = check(comment)
comment()
# 装饰器的基本雏形
# def decorator(fn): # fn:目标函数.
# def inner():
# '''执行函数之前'''
# fn() # 执行被装饰的函数
# '''执行函数之后'''
# return inner
代码说明:
执行结果:
请先登录....
发表评论
3、装饰器的语法糖写法
如果有多个函数都需要添加登录验证的功能,每次都需要写func=check(func)这样代码对已有函数进行装饰,这种做法还是比较麻烦
Python给我们提供了一个装饰函数更加简单的写法,那就是语法糖,语法糖的书写格式是:@装饰器名字,通过语法糖的方式也可以完成对已有函数的装饰
# 添加一个登录验证的功能
def check(fn):
print("装饰器函数执行了")
def inner():
print("请先登录....")
fn()
return inner
# 使用语法糖方式来装饰函数
@check
def comment():
print("发表评论")
comment()
说明:
执行结果:
请先登录....
发表评论
4、小结
# 装饰器
# def decorator(fn): # fn:被装饰的目标函数.
# def inner():
# '''执行函数之前'''
# fn() # 执行被装饰的目标函数
# '''执行函数之后'''
# return inner
装饰器的使用
1、装饰器的使用场景
2、装饰器实现已有函数执行时间的统计
# -*- codeing = utf-8 -*-
# @Time : 2021/12/16 10:59 下午
# @Author : 李明辉
# @File : ithui_装饰器的使用.py
# @Software : PyCharm
import time
def decorator(func):
def inner():
# 内部函数对已有函数进行装饰
begin = time.time()
func()
end = time.time()
print("函数所执行话费的时间%f" % (end - begin))
return inner
@decorator
def work():
for i in range(10000):
print(i)
work()
执行结果:
2、小结
通过上面的示例代码可以得知装饰器的作用:
通用装饰器的使用
1、装饰带有参数的函数
# 添加输出日志的功能
def logging(fn):
def inner(num1, num2):
print("--正在努力计算--")
fn(num1, num2)
return inner
# 使用装饰器装饰函数
@logging
def sum_num(a, b):
result = a + b
print(result)
sum_num(1, 2)
运行结果:
--正在努力计算--
3
2、装饰带有返回值的函数
# 添加输出日志的功能
def logging(fn):
def inner(num1, num2):
print("--正在努力计算--")
result = fn(num1, num2)
return result
return inner
# 使用装饰器装饰函数
@logging
def sum_num(a, b):
result = a + b
return result
result = sum_num(1, 2)
print(result)
运行结果:
--正在努力计算--
3
3、装饰带有不定长参数的函数
# 添加输出日志的功能
def logging(fn):
def inner(*args, **kwargs):
print("--正在努力计算--")
fn(*args, **kwargs)
return inner
# 使用语法糖装饰函数
@logging
def sum_num(*args, **kwargs):
result = 0
for value in args:
result += value
for value in kwargs.values():
result += value
print(result)
sum_num(1, 2, a=10)
运行结果:
--正在努力计算--
13
说明:
4、通用装饰器
# 添加输出日志的功能
def logging(fn):
def inner(*args, **kwargs):
print("--正在努力计算--")
result = fn(*args, **kwargs)
return result
return inner
# 使用语法糖装饰函数
@logging
def sum_num(*args, **kwargs):
result = 0
for value in args:
result += value
for value in kwargs.values():
result += value
return result
@logging
def subtraction(a, b):
result = a - b
print(result)
result = sum_num(1, 2, a=10)
print(result)
subtraction(4, 2)
运行结果:
--正在努力计算--
13
--正在努力计算--
2
5、小结
# 通用装饰器
def logging(fn):
def inner(*args, **kwargs):
print("--正在努力计算--")
result = fn(*args, **kwargs)
return result
return inner
多个装饰器的使用
1、多个装饰器的使用示例代码
# -*- codeing = utf-8 -*-
# @Time : 2021/12/17 8:54 下午
# @Author : 李明辉
# @File : ithui_多个装饰器的使用.py
# @Software : PyCharm
def make_div(func):
def inner(*args, **kwargs):
result = "<div>" + func(*args, **kwargs) + "</div>"
return result
return inner
def make_p(func):
def inner(*args, **kwargs):
result = "<p>" + func(*args, **kwargs) + "</p>"
return result
return inner
@make_p
@make_div
def content():
return "人生苦短,我用python"
result = content()
print(result)
运行结果:
<p><div>人生苦短,我用python</div></p>
代码说明:
2、小结
带有参数的装饰器
1、带有参数的装饰器介绍
带有参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数,语法格式:@装饰器(参数,...)
错误写法:
def decorator(fn, flag):
def inner(num1, num2):
if flag == "+":
print("--正在努力加法计算--")
elif flag == "-":
print("--正在努力减法计算--")
result = fn(num1, num2)
return result
return inner
@decorator('+')
def add(a, b):
result = a + b
return result
result = add(1, 3)
print(result)
执行结果:
Traceback (most recent call last):
File "/home/python/Desktop/test/hho.py", line 12, in <module>
@decorator('+')
TypeError: decorator() missing 1 required positional argument: 'flag'
代码说明:
正确写法:
在装饰器外面再包裹上一个函数,让最外面的函数接收参数,返回的是装饰器,因为@符号后面必须是装饰器实例
# -*- codeing = utf-8 -*-
# @Time : 2021/12/17 9:13 下午
# @Author : 李明辉
# @File : ithui_带有参数的装饰器.py
# @Software : PyCharm
def logging(flag):
def decorator(func):
def inner(num1, num2):
if flag == '+':
print("努力进行加法中")
if flag == '-':
print("努力进行减法中")
result = func(num1, num2)
return result
return inner
return decorator
@logging('+')
def add(a, b):
result = a + b
return result
@logging('-')
def sub(a, b):
result = a - b
return result
add_result = add(1, 2)
print(add_result)
sub_result = sub(1, 2)
print(sub_result)
运行结果:
努力进行加法中
3
努力进行减法中
-1
2、小结
类装饰器的使用
1、类装饰器的介绍
装饰器还有一种特殊的用法就是类装饰器,就是通过定义一个类来装饰函数
类装饰器示例代码:
# -*- codeing = utf-8 -*-
# @Time : 2021/12/17 9:22 下午
# @Author : 李明辉
# @File : ithui_类装饰器.py
# @Software : PyCharm
class Check(object):
def __init__(self, fn):
# 初始化操作在此完成
self.__fn = fn
# 实现__call__方法,表示对象是一个可调用对象,可以像调用函数一样进行调用。
def __call__(self, *args, **kwargs):
# 添加装饰功能
print("请先登陆...")
self.__fn()
@Check
def comment():
print("发表评论")
comment()
执行结果:
请先登陆...
发表评论
说明:
2、小结
END