一、闭包
在Python中,闭包(Closure)是一种特殊的对象,它由一个函数以及创建该函数时其词法环境(即函数外部的变量)组成。闭包允许一个函数访问其词法作用域以外的变量。
闭包有三个特性:
1、外部函数嵌套内部函数
2、外部函数返回内部函数的函数名
3、内部函数可以调用外部函数的变量
def fun1():
dates = []
def fun2():
# 可以访问datas
dates.append("hello")
print(dates)
return fun2
# fun1()返回fan2()的函数名
print(fun1())
r = fun1()
# r()等同于调用fun2()
r()
二、装饰器
装饰器的作用在于不改变函数的语句块给函数增加新的功能。
下面是一个未简化的装饰器
# 使用列表推导式生成一个长10000的列表
datas = [random.randint(1, 10000) for i in range(10000)]
# 使用闭包创造装饰器
def time_cost(f):
def calc():
start = time.time()
# 将传入的函数名进行函数调用
f()
# f.__name__获取f的函数名
print(f"函数{f.__name__}花费{time.time() - start}")
# 外部函数返回内部函数的函数名
return calc
# 需要添加功能的函数my_fun1()
def my_fun1():
# 将列表进行升序排序
datas.sort()
print(datas)
# 将需要添加功能的函数名传入装饰器,返回装饰好功能的函数名
r = time_cost(my_fun1)
# 调用装饰后的函数
r()
# r理论上可以使用任意名,所以为了增加代码可读性,
# 将r改为传入的函数名my_fun1
通过python'@'可以将上述代码进行简化
datas = [random.randint(1, 10000) for i in range(10000)]
# 使用闭包创造装饰器
def time_cost(f):
def calc():
start = time.time()
# 将传入的函数名进行函数调用
f()
# f.__name__获取f的函数名
print(f"函数{f.__name__}花费{time.time() - start}")
# 外部函数返回内部函数的函数名
return calc
# 使用@将函数名传入装饰器,
# 并将返回的函数名改为传入的函数fun1
# 实现函数功能的添加
@time_cost
def fun1():
datas.sort()
print(datas)
三、装饰器案例
装饰器添加权限检测
user = None
# 装饰
def login_required(f):
def check():
# 非空就直接调用函数
if user:
f()
else:
# 对没登录的用户进行登录处理
while True:
username = input("请输入用户名")
password = input("请输入密码")
if username == "admin" and password == "123456":
f()
break
else:
print("用户名或密码错误")
return check
def index():
print("我是首页")
@login_required
def center():
print("我是个人中心")
@login_required
def cart():
print("我是购物车")