标签:创建 加载 一点 闭包函数 strong 基础上 语法 执行时间 计算
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。
构成条件:
# 定义一个外部函数
def func_out(num1):
# 定义一个内部函数
def func_inner(num2):
# 内部函数使用了外部函数的变量(num1)
result = num1 + num2
print("结果是:", result)
# 外部函数返回了内部函数,这里返回的内部函数就是闭包
return func_inner
# 创建闭包实例
f = func_out(1)
# 执行闭包
f(2)
f(3)
# 执行结果
# 结果是: 3
# 结果是: 4
通过上面的输出结果可以看出闭包保存了外部函数内的变量num1,每次执行闭包都是在num1 = 1 基础上进行计算。
闭包的作用:闭包可以保存外部函数内的变量,不会随着外部函数调用完而销毁。
注意:由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。
判断函数是否是闭包函数:输出的__closure__有cell元素 :是闭包函数
def func():
name = 'eva'
def inner():
print(name)
print(inner.__closure__) # (<cell at 0x0000028DD6FD0E58: str object at 0x0000028DD70D1F48>,)
return inner
f = func()
f()
name = 'egon'
def func2():
def inner():
print(name)
print(inner.__closure__) # 结果为None,不是闭包函数,闭包函数是对外包作用域的引用,而非全局作用域
return inner
f2 = func2()
f2()
错误示例:
# 定义一个外部函数
def func_out(num1):
# 定义一个内部函数
def func_inner(num2):
# 这里本意想要修改外部num1的值,实际上是在内部函数定义了一个局部变量num1
num1 = 10
# 内部函数使用了外部函数的变量(num1)
result = num1 + num2
print("结果是:", result)
print(num1)
func_inner(1)
print(num1)
# 外部函数返回了内部函数,这里返回的内部函数就是闭包
return func_inner
# 创建闭包实例
f = func_out(1)
# 执行闭包
f(2)
正确的示例:
# 定义一个外部函数
def func_out(num1):
# 定义一个内部函数
def func_inner(num2):
# 这里本意想要修改外部num1的值,实际上是在内部函数定义了一个局部变量num1
nonlocal num1 # 告诉解释器,此处使用的是 外部变量a
# 修改外部变量num1
num1 += 10
# 内部函数使用了外部函数的变量(num1)
result = num1 + num2
print("结果是:", result)
print(num1)
func_inner(1)
print(num1)
# 外部函数返回了内部函数,这里返回的内部函数就是闭包
return func_inner
# 创建闭包实例
f = func_out(1)
# 执行闭包
f(2)
def wrapper():
money = 1000
def func():
name = 'eva'
def inner():
print(name, money)
return inner
return func
f = wrapper()
i = f()
i()
就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数。
装饰器函数的特点:
# 登录验证
def check(fn):
def inner():
print("登录。。。")
fn()
return inner
def comment():
print("aa")
# 使用装饰器来装饰函数
comment = check(comment)
comment()
装饰器的基本雏形:
def wrapper(fn): # fn:目标函数.
def inner():
'''执行函数之前'''
fn() # 执行被装饰的函数
'''执行函数之后'''
return inner
说明:
Python给提供了一个装饰函数更加简单的写法,那就是语法糖,语法糖的书写格式是: @装饰器名字,通过语法糖的方式也可以完成对已有函数的装饰。
import time
def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner
@timer #==> func1 = timer(func1)
def func1():
print('in func1')
func1()
说明:
# 添加输出日志的功能
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)
import time
# 计算执行时间
def timer(func):
def inner(*args, **kwargs):
start = time.time()
re = func(*args, **kwargs)
print(time.time() - start)
return re
return inner
# 使用语法糖装饰函数
@timer # ==> func1 = timer(func1)
def func1(a, b):
print('in func1', a, b)
# 使用语法糖装饰函数
@timer # ==> func2 = timer(func2)
def func2(a):
print('in func2 and get a:%s'%(a))
return 'fun2 over'
func1('aaaaaa', 'bbbbbb')
print(func2('aaaaaa'))
import time
def timer(func):
def inner(*args, **kwargs):
start = time.time()
re = func(*args, **kwargs)
print(time.time() - start)
return re
return inner
@timer # ==> func2 = timer(func2)
def func2(a):
print('in func2 and get a:%s' % a)
return 'fun2 over'
func2('aaaaaa')
print(func2('aaaaaa'))
上面的装饰器已经非常完美了,但是正常我们情况下查看函数的一些信息的方法在此处都会失效
def index():
'''这是一个主页信息'''
print('from index')
print(index.__doc__) # 查看函数注释的方法
print(index.__name__) # 查看函数名的方法
为了不让他们失效,我们还要在装饰器上加上一点来完善它:
from functools import wraps
def deco(func):
@wraps(func) # 加在最内层函数正上方
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@deco
def index():
'''哈哈哈哈'''
print('from index')
print(index.__doc__) # 哈哈哈哈
print(index.__name__) # index
def make_div(func):
"""对被装饰的函数的返回值 div标签"""
def inner(*args, **kwargs):
return "<div>" + func() + "</div>"
return inner
def make_p(func):
"""对被装饰的函数的返回值 p标签"""
def inner(*args, **kwargs):
return "<p>" + func() + "</p>"
return inner
# 装饰过程: 1 content = make_p(content) 2 content = make_div(content)
# content = make_div(make_p(content))
@make_div
@make_p
def content():
return "人生苦短"
result = content()
print(result)
多个装饰器可以对函数进行多个功能的装饰,装饰顺序是由内到外的进行装饰.
带有参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数,语法格式: @装饰器(参数,...)
# 添加输出日志的功能
def logging(flag):
def decorator(fn):
def inner(num1, num2):
if flag == "+":
print("--正在努力加法计算--")
elif flag == "-":
print("--正在努力减法计算--")
result = fn(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
result = add(1, 2)
print(result)
result = sub(1, 2)
print(result)
标签:创建 加载 一点 闭包函数 strong 基础上 语法 执行时间 计算
原文地址:https://www.cnblogs.com/fengyuhao/p/11697852.html