上周回顾
可变长参数
*
*形参:接收多余的位置实参
*实参(可迭代数据类型):打散可迭代数据类型
**
**形参:接收多余的关键字实参
**实参:打散字典,当作关键字实参传参
def f1(*args,**kwargs)
函数对象
- 引用
- 作为容器类元素
- 作为函数返回值
- 作为函数参数
函数嵌套
def f1():
def f2():
pass
f2() # 报错
名称空间和作用域
- 内置名称空间:内置方法
- 全局名称空间:除了内置和局部就是全局
- 局部名称空间:函数内部的变量和函数
执行顺序:内置 --》 全局 --》 局部
搜索顺序:从当前开始 局部 --》 全局 --》 内置
全局作用作用域和局部作用域没有半毛钱关系
局部作用域1和局部作用域2没有半毛钱关系
今日所学
闭包函数
闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。
两种为函数传参的方式
方式一: 使用参数的形式
方式二:包给函数
闭包函数的应用
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得该函数无论在何处调用,优先使用自己外层包裹的作用域
应用领域:延迟计算(原来是传参,现在是包起来)、爬虫领域
# 闭包函数把闭包函数内部的变量 + 闭包函数内部的函数 这两者包裹在一起 然后通过返回值的形式返回出来
# 闭包函数至少也得符合函数嵌套
# def f1(url): # f1 就是闭包函数
# def f2():
# print(url)
# pass
#
# return f2
#
#
# res = f1(1)
# res()
装饰器
无参装饰器
什么是装饰器
器指的是工具,而程序中的函数就是具备某一功能的工具,所以装饰器指的是为被装饰器对象添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能。
需要注意的是:
- 装饰器本身其实是可以任意可调用的对象
- 被装饰的对象也可以是任意可调用的对象
为什么要用装饰器
如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。
装饰器的实现必须遵循两大原则:
- 不修改被装饰对象的源代码
- 不修改被装饰对象的调用方式
装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。
装饰器语法糖
在被装饰函数正上方,并且是单独一行写上@装饰器名
装饰器模板
def deco(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
有参装饰器
三层装饰器。
登录装饰器
# 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
@login_deco # index = login_deco(index)
def index(x, y):
print('index')
print('x,y', x, y)
return 123
res = index(10, 20)
# 二层装饰器:
# 1. 用来装饰函数的,它本质是函数
# 2. 不改变函数源代码
# 3. 不改变函数调用方式
# # 装饰器模板,如果装饰器真的不懂,记住模板
# def deco(func):
# def wrapper(*args, **kwargs):
# # 要加什么功能就加上去
# res = func(*args, **kwargs)
#
# return res
#
# return wrapper
三层装饰器
username_list = []
def sanceng(role):
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(f'{role}_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
return login_deco
@sanceng('admin')
def index(x, y):
print('index')
print('x,y', x, y)
return 123
res = index(10, 20)
# 要记住装饰器的用途+装饰器的模板(多练);要了解装饰器至少要看3篇以上相关博客;要灵活运用至少5篇;要达到熟悉百度至少看10篇装饰器相关的博客
# 人生路上一定会遇到跨不过去的坎,但是绕道就行了(绕过去没有关系)
# 装饰器别人帮你写好了,你只要会在适当的情境下@一下
# 1万行 只能看得懂,无法自己实现 --》 不会看答案
# 5万行才能真正理解 了解的是框架
# 10万行 细节决定成
# 10万行以上就是天赋
# 李开复:计算机本科生毕业要求,就一点:代码量超过10w行
# 代码越敲越多 --》 冷门知识点(别人写好的方法)你也会逐渐用到 --》 你会的知识点越来越熟悉
# 快速成型上线,从来不管速度 5-6月 ---》 优化sql
# 看不懂跳过,
# 《编写高质量Python代码的59个有效方法》:偏门玩意,也没记得几个,都内化了。
# 《改善Python程序的91个建议》:偏门玩意,也没记得几个,都内化了。
# 精通python --》 谐音法
# 从一期留到六期
# 国庆节--》学习--》争取弯道(别人放松的时候,你紧张)超车
迭代器引入
可迭代对象:含有 __ iter __ 方法的就叫做可迭代对象
迭代器:含有 __ iter __ 和 __ next __ 方法的就叫做迭代器
生成器:含有yield关键字的函数就叫做生成器