首页 / PYTHON / Python闭包和装饰器
Python闭包和装饰器
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Python闭包和装饰器,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3914字,纯文字阅读大概需要6分钟。
内容图文
闭包
- 闭包
在嵌套函数中引用了自由变量的函数。这个自由变量就是外层嵌套函数中的变量(非全局变量)
- 闭包必须满足三个条件
1. 必须是嵌套函数
2. 内层嵌套函数必须引用了外层嵌套函数的变量
3. 外层嵌套函数的返回值是内层嵌套函数
- 作用
嵌套函数的内层函数可以使用外层函数的变量,即使外层函数返回了,或者被删除了。内层函数依然可以使用外层函数的那个变量。
- 示例
# encoding:utf-8
# 判断闭包的方法closure,若果是None就不是闭包,如果有cell元素就是闭包
def func1():
num1 = 10
def func2():
pass
print("func2:", func2.__closure__)
return func2
print(func1())
# output: func2: None, 因为内层嵌套函数必须引用了外层嵌套函数的变量
def func1():
num1 = 10
def func2():
print(num1)
return num1
print("func2:", func2.__closure__)
return func2
func1()
# output func2: (<cell at 0x0000024E3EE70EB8: int object at 0x000000005B6A6D40>,)
# 闭包,fn使用了变量y并且外层函数make_power的返回值是fn(内层嵌套函数)
# 这个闭包可以实现x的y次方
def make_power(y):
# 自由变量就是y,当函数make_power返回后,fn依旧可以使用y的值
def fn(x):
return x * y
return fn
res = make_power(10)
print(res(2))
#output:20
装饰器函数
- 概述
简单来说,装饰器本质上就是闭包函数。一般就是传入一个函数或类,在不修改原来的函数以及其调用方式的前提下为原来的函数增加新的功能。通常的做法是,在装饰器函数的内层函数中调用被装饰的函数然后在被装饰的函数调用前面或者后面加上我们要执行的代码,达到扩展其功能的目的。比较常用的场景就是日志插入,事务处理。其实装饰器函数本质上就是函数名和函数地址的重新绑定。被装饰的函数虽然看起来和原来的函数名字是一样的,但是其在内存中已经修改了绑定关系,它已经绑定到我们装饰器函数的内层函数。
-
一个初始的函数
如果想要记录函数的执行时间,最原始的做法是入侵到原来的函数中进行修改
import time
# 计算一个函数的运行的时间,最暴力的方法
def func():
startTime = time.time()
print("hello")
time.sleep(1)
print("world")
endTime = time.time()
seconds = endTime - startTime
print("函数运行了{}秒".format(seconds))
if __name__ == '__main__':
func()
- 如果不想入侵到原来的代码,可以将函数作为参数传入到一个具有计时功能的函数中
import time
#不改变原函数的代码的情况下统计函数执行所需的时间
def myfunc():
print("hello")
time.sleep(1)
print("world")
#不改变原来的函数功能,但是每次都要执行该函数
def deco(func):
startTime = time.time()
# 运行函数
func()
endTime = time.time()
seconds = endTime - startTime
print("func()执行了{}秒".format(seconds))
if __name__ == '__main__':
f = myfunc;
#这里要统计时间的时候,每次都要调用deco()函数
deco(f)
这样有一个问题就是每次都要调用deco()函数来实现计时
- 使用装饰器,既不改变原来函数的功能,又不需要重复调用deco()函数
import time
def deco(func):
def wrapper():
startTime = time.time()
# 运行函数
func()
endTime = time.time()
seconds = endTime - startTime
print("func()执行了{}秒".format(seconds))
return wrapper
@deco
def func1():
print("hello")
time.sleep(1)
print("world")
if __name__ == '__main__':
func1()
这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数func()就在返回函数wrapper()的内部执行。然后在函数func()前面加上@deco,func()函数就相当于被注入了计时功能,现在只要调用func(),它就已经变身为“新的功能更多”的函数了。所以这里装饰器就像一个注入符号:有了它,拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。
目前存在一个问题,装饰器可能也会被其他类型得函数调用,函数传参可能会不一样,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
-
装饰器的固定格式(接收任意的参数)
# 标注固定格式
def deco(func):
def inner(*args,**kwargs):
'''执行函数之前要做的'''
re = func(*args,**kwargs)
'''执行函数之后要做的'''
return re
return inner
- 示例
import time
def timer(func):
def inner(*args,**kwargs):
startTime = time.time()
# 运行函数
re = func(*args, **kwargs)
endTime = time.time()
seconds = endTime - startTime
print("func()执行了{}秒".format(seconds))
'''执行函数之后要做的'''
return re
return inner
@timer
def func(a, b, c):
time.sleep(1)
return a, b, c
@timer
def func1(num):
res = []
for i in range(num):
res.append(i)
return res
print(func(1,2,3))
#output:func()执行了1.000331163406372秒
(1, 2, 3)
print(func1(3))
#output:
func()执行了0.0秒
[0, 1, 2]
内容总结
以上是互联网集市为您收集整理的Python闭包和装饰器全部内容,希望文章能够帮你解决Python闭包和装饰器所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。