闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。
def outter():
x = 1
def inner():
print(x) # x = 1
return inner
f = outter() # f = inner
def f2():
x = 2
f() # f() = inner()
f2()
1
方式一:使用参数的形式
def func(x):
print(x)
func(1)
1
方式二:包给函数
def outter(x):
def inner():
print(x)
return inner
f = outter(1) # f = inner ,x = 1
print(f)
f()
<function outter.<locals>.inner at 0x0000017E2A641048>
1
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。
应用领域:延迟计算(原来我们是传参,现在我们是包起来)、爬虫领域。
import requests
def outter(url):
def get():
respond = requests.get(url)
print(f'done:{url}')
return get
baidu = outter('http://www.baidu.com') # baidu = get
baidu() # baidu() = get()
taobao = outter('http://www.taobao.com') # taobao = get
taobao()
done:http://www.baidu.com
done:http://www.taobao.com
器指的是工具,而程序中的函数就是具备某一功能的工具,所以装饰器指的是为被装饰器对象添加额外功能。
注意:
如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方发法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能是开放的。
装饰器的实现必须遵循两大原则:
装饰器就是在遵循以上两个原则的前提下为被装饰对象添加新功能。
# 改变调用方式
import time
def index():
print('welcome to index')
time.sleep(1)
def time_count(func):
start = time.time()
func() # index()
end = time.time()
print(f'{func} time is {end - start}')
time_count(index) # 改变了index的调用方式
welcome to index
<function index at 0x0000017E2A84BD90> time is 1.0003917217254639
# 包给函数—外包
import time
def index():
print('welcome to index')
time.sleep(1)
def time_count(func):
def wrapper():
start = time.time()
func() # index()
end = time.time()
print(f'{func} time is {end - start}')
return wrapper
print(index) # <function index at 0x0000017E2A781B70>
print('*'*20)
index = time_count(index) # index = wrapper
index() # index() = wrapper()
print('*'*20)
print(index) # 地址与第一个打印不同
# <function time_count.<locals>.wrapper at 0x0000017E2A8A00D0>
<function index at 0x0000017E2A781B70>
********************
welcome to index
<function index at 0x0000017E2A781B70> time is 1.0003859996795654
********************
<function time_count.<locals>.wrapper at 0x0000017E2A8A00D0>
import time
def index():
print('welcome to index')
time.sleep(1)
return "I'm index"
def time_count(func):
def wrapper():
start = time.time()
res = func() # res = index() = "I'm index"
end = time.time()
print(f'{func} time is {end - start}')
return res
return wrapper
print(index())
print('*'*20)
index = time_count(index)
res = index()
print(res)
welcome to index
I'm index
********************
welcome to index
<function index at 0x0000017E2A8858C8> time is 1.0053789615631104
I'm index
import time
def home(name):
print(f'welcome {name} to home page')
time.sleep(1)
return name
def time_count(func):
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
end = time.time()
print(f'{func} time is {end - start}')
return res
return wrapper
home = time_count(home) # home = wrapper
res = home('william') res = wrapper('william')
print(res)
welcome william to home page
<function home at 0x0000017E2A8856A8> time is 1.0003857612609863
william
在被装饰的函数上方,单独写一行@装饰器名
# 上方函数用语法糖
import time
def time_count(func):
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
end = time.time()
print(f'{func} time is {end - start}')
return res
return wrapper
@time_count
def home(name):
print(f'welcome {name} to home page')
time.sleep(1)
return name
@time_count
def index():
print('welcome to index')
time.sleep(1)
return "I'm index"
print(index())
print('*'*20)
print(home('william'))
welcome to index
<function index at 0x0000017E2A885E18> time is 1.0003869533538818
I'm index
********************
welcome william to home page
<function home at 0x0000017E2A885D90> time is 1.0013864040374756
william
def deco(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
无参装饰器只套了两层,下面是三层装饰器—有参装饰器。这个参数是装饰器的参数。
# 登陆注册(判断信息来源,'file'可以,其他不行)
is_login_dict = {'username':None}
def auth(origin):
def login(func):
def wrapper(*args,**kwargs):
if origin == 'file':
print('from file')
if not is_login_dict.get('username'):
username = input('please enter your username>>>').strip()
print('login successfully')
res = func(*args,**kwargs)
is_login_dict['username'] = username
return res
else:
res = func(*args,**kwargs)
return res
else:
print('illegal original')
return wrapper
return login
@auth('file')
def shopping():
print('from shopping')
@auth('mongodb')
def withdraw():
print('from withdraw')
@auth('file')
def paying():
print('from paying')
shopping() # 需要输入用户名
print('*'*20)
withdraw() #来源错误
print('*'*20)
paying() # 无需再次输入用户名
from file
please enter your username>>>william
login successfully
from shopping
********************
illegal original
********************
from file
from paying
原文:https://www.cnblogs.com/WilliamKong94/p/10961928.html