闭包
闭包是一种函数,从形式上来说是函数内部定义(嵌套)函数,实现函数的扩展。在开发过程中,考虑到兼容性和耦合度问题,如果想在原有的函数基础上添加东西而又不改动原有函数的结构,通常会使用闭包。但闭包的功能还不只是这个。实际上,闭包会保留定义函数时存在的自由变量的绑定,这样在调用函数时,虽然定义作用域不可用了,但是仍然可以使用那些绑定的变量。简单来说,普通函数在调用完后,函数内部的变量就释放了(因为直接调用的函数没有绑定在某一个对象上,Cpython解析器就会把它回收了),而闭包内部的变量仍然保存着。
满足闭包的条件
条件一:函数中嵌套函数
条件二:外层函数返回内层嵌套函数名
条件三:内层嵌套函数有引用外层的一个非全局变量
举例:
def func(num):
def count_book():
print(num) # num是传进来的参数,也是非全局变量
print("这个是计算买书方式的函数")
return count_book
res = func(1999) # 将1999存入了res.__closure__中
res() # 打印1999 这个是计算买书方式的函数
作用:实现数据的锁定,提高稳定性
装饰器
在上面的过程中其实我们已经完成了一个装饰器的定义和应用,只是现在的语法并不是按照整个的装饰器来写的,装饰器只要在上面的基础稍加改动一点点就可以了。
def func(fuck):
def count_book():
fuck() # 调用fuck,此处相当于调用buy()函数
print("这个是计算买书方式的函数")
return count_book
@func # 相当于func(buy),也就是将buy传给func
def buy():
print("呵呵")
输出为:
呵呵
这个是计算买书方式的函数
参数的传递
def add(func):
def fun(a, b):
print('相乘', a * b)
print('相除', a / b)
func(a, b)
return fun
@add
def add_num(a, b):
print('相加', a + b)
add_num(8, 9)
输出为:
相乘 72
相除 0.8888888888888888
相加 17
一个简单的登录校验
# file.txt文件里是一个字典,有user,pwd,token这些键
with open('file.txt') as f:
users = eval(f.read())
def login_check(func):
def ado():
if not users['token']: # token不存在就需要登录
print("登录账号")
username = input("账号:")
password = input("密码:")
# 登录校验
if users["user"] == username and users["pwd"] == password:
users['token'] = True
func() # 调用被装饰的函数
else:
func() # token为True则直接调用函数
return ado
@login_check
def index():
print("首页")
@login_check
def page1():
print("页面1")
@login_check
def page2():
print("页面2")
if __name__ == '__main__':
index()
page1()
page2()
装饰类
def add(func):
def fun(*args):
new_name = 'xiaohong'
new_age = args[1] + 1
return func(new_age, new_name) # 返回一个对象,装饰一个类必须在这里加return
return fun
@add # MyClass = add(MyClass)
class MyClass:
def __init__(self, name, age):
self.name = name
self.age = age
print(name, age)
m = MyClass('Xiaoming', 18)
print('m的值', m)
输出为:
19 xiaohong
m的值 <__main__.myclass object at>