闭包函数,装饰器,写一个登录装饰器 (二层和三成装饰器)
1.闭包函数
闭包:闭就是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。
当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的其他变量,如果返回的这个函数在外部被执行了,就产生了闭包;
闭包的作用及好处:
闭包给访问外部函数定义的内部变量创造了条件,也将关于函数的一切封闭到了函数内部,减少了全局变量,这就是闭包的好处及真实意义,其实就是缓存了数据,变相的延长了作用域;
什么是闭包函数:
在一个内嵌套函数中,对在外部的函数变量进行引用,那么内嵌套函数就是闭包。
定义在外部函数内但由内部函数引用的变量为自由变量,当作返回值。
def f1():
def f2():
print('from f2')
return f2
f2 = f1()
f2() #from f2
闭包函数的用法:
def wb_family():
father = "王健林"
def wbf_hobby():
print("先定一个小目标,赚它一个亿,这是爸爸{}说的".format(father)) # 条件1:内函数使用外函数的局部变量
return wbf_hobby # 条件2:外函数返回了内函数
func = wb_family()
print(func) # 这是打印函数 wb_family() 返回的 wbf_hobby函数名
func()
1.1 两种为函数传参的方式
为函数传参的方式一:使用参数的形式
def f1(url):
print(url)
f1(2)
f1(2)
为函数传参的方式及应用二:包给函数
def f1(url): # f1就叫做闭包函数
def spider():
print(url)
return spider # 函数对象
taobao = f1('www.taobao.com')
taobao() # www.taobao.com
tapbao()
列二:
def outer():
x = 0
def inner():
nonlocal x
x +=1
print(x)
return inner
click_func = outer()
click_func() # inner()
click_func()
click_func()
x = 100 # 在函数内部调用,起到封装作用,相对安全外部改变不了内部变量
click_func()
闭包函数:闭包函数把 闭包函数内部的变量 + 闭包函数内部的函数 这两者包裹在一起 然后通过返回值的形式返回出来
闭包函数至少也得符合函数嵌套
# def f1(url): #1 #3 url:1
# def f2(): # 4 url:{int}1 #8 url={int}1
# print(url) # 9 url:{int}1
# pass # 10
#
# return f2 #5 url = {url}1
#
#
# res = f1(1) #2 #6
# res() #1 #7 #11
2. 装饰器
装饰器:装饰(新增加了一个额外的功能) 器(工具) --》 函数
装饰器本质就是一个给函数增加功能的函数。
装饰器:给函数给函数 增加功能的 函数,增加功能时需要注意以下两点:
装饰器注意点:
- 不改变原函数的源代码
- 不改变原函数的调用方式
2.1装饰器
- 装饰器本身是函数,只不过它用来装饰 被装饰的函数
- 装饰器装饰函数 不改变被装饰函数源代码
- 装饰器装饰函数 不改变被装饰函数的调用方式
列:
# time_count装饰器:对被装饰函数计时
def time_count(func): # func才是真正的index
"""装饰器"""
def wrapper(*args,**kwargs): # (10, 20) # *args和**kwargs接收了所有的参数
start = time.time()
res = func(*args,**kwargs) # index() # *(10,20) # *args和**kwargs打散参数传给真正的index
end = time.time()
print(end - start)
return res
return wrapper
index = time_count(index) # index == wrapper
res = index(10,20,320) # wrapper()
print(res)
3.题:写一个登录装饰器 (二层和三成装饰器)
# username_list = []
#
#
# def index(x, y):
# print('index')
# print('x,y', x, y)
#
# return 123
#
#
# def login_deco(func):
# def wrapper(*args, **kwargs):
#
# if username_list:
# print('已经登录,请勿重复登录')
# res = func(*args, **kwargs)
# return res
#
# username_inp = input('请输入用户名:')
# pwd_inp = input('请输入密码:')
#
# with open('user_info.txt', 'r', encoding='utf8') as fr:
# for user_info in fr:
# username, pwd = user_info.strip().split(':')
# if username_inp == username and pwd_inp == pwd:
# print('登录成功')
# username_list.append(username)
#
# res = func(*args, **kwargs)
# return res
#
# else:
# print('登录失败')
#
# return wrapper
#
#
# index = login_deco(index)
# index(10, 20)
# index(10,20)
# python装饰器语法糖(就是让代码更简洁)
username_list = []
def login_deco(func):
def wrapper(*args, **kwargs):
if username_list:
print('已经登录,请勿重复登录')
res = func(*args, **kwargs)
return res
username_inp = input('请输入用户名:')
pwd_inp = input('请输入密码:')
with open('user_info.txt', 'r', encoding='utf8') as fr:
for user_info in fr:
username, pwd = user_info.strip().split(':')
if username_inp == username and pwd_inp == pwd:
print('登录成功')
username_list.append(username)
res = func(*args, **kwargs)
return res
else:
print('登录失败')
return wrapper
二层装饰器:
- 用来装饰函数的,它本质是函数
- 不改变函数源代码
- 不改变函数调用方式
# # 装饰器模板,如果装饰器真的不懂,记住模板
# def deco(func):
# def wrapper(*args, **kwargs)
三层装饰器:
def sanceng()
def login_deco()
def wrapper(*args, **kwargs)
4.余先了解 迭代器引用(就是一层层更新)
类型:# 整型
浮点型
字符串
列表
元组
字典
集合