一、闭包函数
闭包是指在一个函数中定义了另外一个函数,内函数运用了外函数作用域的名字,并且外函数的返回值是内函数的引用,这样就构成了一个闭包函数。
def callFunc():
n = 1
def show():
print('show: ', n)
return show
s = callFunc()
s()
去掉了全局变量的使用,将show函数封装在callFunc函数的内部,使外部不可见,不能使用show函数,隐藏了实现细节。
程序在执行的时候,callFunc返回了内部定义的show函数,并且在show函数内部使用了外部函数的变量。
在show函数返回时,保存了当前的执行环境,也就是会在show函数中使用外部变量n。
n只是callFunc函数中的局部变量,当这个函数执行结束时,n自然而然就会被释放。
但是因为callFunc函数中返回了一个show函数,show函数还在外部执行,所以程序还会将show函数所需的执行环境保存下来
二、装饰器
装饰器是个什么东东呢?看字面意思好像是装饰什么东东的工具,其实你猜出大概意思了,装饰器本身就是一个函数,这个函数以闭包的形式定义使用 @装饰器函数名 形式来装饰,在不改源代码的情况下,让一个程序增加功能来进行装饰。
比如在一个项目中,有很多函数,由于项目越来越大,功能越来越多,导致程序越来越慢,其中一个功能函数功能,实现一百万次累加。
def my_count()
s = 0
for i in range(1000001):
s += i
print('sum:',s)
现在要确定函数的运行时间,这个要怎么搞???如何能应用到所有函数上?
解决方法:
import time
def count_time(func):
def wrapper(): #wrapper 装饰
start = time.time()
func()
end = time.time()
print('共计执行:%s 秒'%(end - start)) # 使用%d显示,取整后是0秒,因为不到一秒
return wrapper
@count_time # 这实际就相当于解决方法3中的 my_count = count_tiem(my_count)
def my_count():
s = 0
for i in range(10000001):
s += i
print('sum : ', s)
my_count()
这样实现的好处是定义好了闭包函数后,只需要通过@xxx的装饰器语法,将@xxx加到要装饰的函数前
多层装饰器:
import time
user_dic = {'is_login':None}
def outter(func):
def get_time(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print('func run time:%s'%(end-start))
return res
return get_time
def login_auth2(data_source,x,t):
def login_auth(func):
def inner(*args, **kwargs):
if user_dic['is_login']:
res = func(*args, **kwargs)
return res
else:
if data_source == 'file':
username = input('please input your username:')
password = input('please input your password:')
if username == 'jason' and password == '123':
user_dic['is_login'] = True
res = func(*args, **kwargs)
return res
else:
print('username or password error')
elif data_source == 'MySQL':
print('from MySQL')
elif data_source == 'ldap':
print('ldap')
else:
print('暂无该数据来源')
return inner
return login_auth
@login_auth2('file',1,2)
# 这一步相当于
# res = login_auth2('file',1,2) # 这里的res就是login_auth2()的返回值login_auth
# @res
@outter
def index():
time.sleep(1)
print('index')
return 'index'
index()
# 装饰器在装饰的时候,顺序从下往上
# 装饰器在执行的时候,顺序从上往下
# 这里就实现了给index函数增加了两个功能:计时和认证
# 这里的认证函数是三层嵌套的,最外层函数的作用就是给里层函数传参
装饰器模板:
无参装饰器
from functools import wraps
def outter(func):
@wraps(func)
def inner(*args, **kwargs): # * **在形参中使用
# 执行被装饰函数之前你可以做的操作
res = func(*args, **kwargs) # * **在实参中使用
# 执行被装饰函数之后你可以做到操作
return res
return inner
@outter
def index(username, *args, **kwargs):
"""index注释"""
pass
print(index)
有参装饰器
def wrappers(data):
# data = 'file'
def outter(func):
def inner(*args,**kwargs):
if data == 'file':
# 执行被装饰函数之前你可以做的操作
res = func(*args,**kwargs) # * **在实参中使用
# 执行被装饰函数之后你可以做到操作
return res
return inner
return outter