说装饰器之前先带大家了解一下闭包
1.闭包
闭包:简而言之就是将数据封装在一个包(区域)中,使用时再去里面取。(本质上 闭包是基于函数嵌套搞出来一个中特殊嵌套)
闭包应用场景1:封装数据防止污染全局,不需要全局使用,只需要在局部用到。
name = "shuai"
def f1():
print(name, age)
def f2():
print(name, age)
def f3():
print(name, age)
def f4():
pass
def func(age):
name = "shuai"
def f1():
print(name, age)
def f2():
print(name, age)
def f3():
print(name, age)
f1()
f2()
f3()
func(123)
闭包应用场景2:封装数据封到一个包里,使用时在取。
def task(arg):
def inner():
print(arg)
return inner
v1 = task(11)
v2 = task(22)
v3 = task(33)
v1()
v2()
v3()
def task(arg):
def inner():
print(arg)
return inner
inner_func_list = []
for val in [11,22,33]:
inner_func_list.append( task(val) )
inner_func_list[0]() # 11
inner_func_list[1]() # 22
inner_func_list[2]() # 33
""" 基于多线程去下载视频 """
from concurrent.futures.thread import ThreadPoolExecutor
import requests
def download_video(url):
res = requests.get(
url=url,
headers={
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
}
)
return res.content
def outer(file_name):
def write_file(response):
content = response.result()
with open(file_name, mode='wb') as file_object:
file_object.write(content)
return write_file
POOL = ThreadPoolExecutor(10)
video_dict = [
("东北F4模仿秀.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"),
("卡特扣篮.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"),
("罗斯mvp.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg")
]
for item in video_dict:
future = POOL.submit(download_video, url=item[1])
future.add_done_callback(outer(item[0]))
POOL.shutdown()
2.装饰器
给你一个函数,在不修改函数源码的前提下,实现在函数执行前和执行后分别输入 "before" 和 "after"。
def func():
print("我是func函数")
value = (a,b,c)
return value
result = func()
print(result)
大部分的新手小白的实现思路都是在执行前和执行后直接加上print
def func():
print("before")
print("我是func函数")
value = (a,b,c)
print("after")
return value
result = func()
只有一个还好如果有一百个难道要手写一百个吗?接下来就用到装饰器
def outer(origin):
def inner():
print("before")
origin()
print("after")
return inner
@outer # outer(func)
def func():
print("我是func函数")
value = (1, 2, 3)
return value
result = func()
原型就相当于
def outer(origin):
def inner():
print("before")
origin()
print("after")
return inner
def func():
print("我是func函数")
value = (1, 2, 3)
return value
result = outer(func)
result()
重要补充:functools
你会发现装饰器实际上就是将原函数更改为其他的函数,然后再此函数中再去调用原函数。
其实,一般情况下大家不用functools也可以实现装饰器的基本功能,但后期在项目开发时,不加functools会出错(内部会读取__name__
,且__name__
重名的话就报错),所以在此大家就要规范起来自己的写法。
import functools
def outer(origin):
@functools.wraps(origin)
def inner(*args, **kwargs):
print("before")
res = origin(*args, **kwargs) # 执行原函数
print("after")
return res
return inner
@outer
def func(*args, **kwargs):
print("我是func函数")
value = (1, 2, 3)
return value
result = func(1, a=2)
总结
-
函数可以定义在全局、也可以定义另外一个函数中(函数的嵌套)
-
学会分析函数执行的步骤(内存中作用域的管理)
-
闭包,基于函数的嵌套,可以将数据封装到一个包中,以后再去调用。
-
装饰器
-
实现原理:基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时再在内层函数中执行闭包中的原函数。
-
实现效果:可以在不改变原函数内部代码 和 调用方式的前提下,实现在函数执行和执行扩展功能。
-
适用场景:多个函数系统统一在 执行前后自定义一些功能。
-
装饰器示例
import functools def auth(func): @functools.wraps(func) def inner(*args, **kwargs): """巴拉巴拉""" res = func(*args, **kwargs) # 执行原函数 return res return inner @auth def handler(): pass handler() print(handler.__name__) # handler
-