随着项目越来越大, 功能越来越多, 使用python特性的地方也越来越多,随着对python特性的使用, 对这些概念的理解也越来越深, 因此写此文打卡
文章目录
- 迭代器
- 生成器
- 装饰器
- 上下文管理器
迭代器
背景: 序列中元素的迭代操作十分频繁, 而python中大部分的数据结构都是序列, 因此python提供了额外的工具来使迭代操作简单、高效; 这种工具就是迭代器
迭代器相关概念
迭代: 重复相同的动作
可迭代:实现了__iter__()方法的对象都是可迭代的。通过isinstance()
可判断一个对象是否可迭代, 如case 1.1isinstance(owef(), collections.Iterable)
判断是否可迭代1
2
3
4
5
6
7
8
9import collections
class owef:
def __iter__(self):
pass
print(isinstance(owef(), collections.Iterable))
# Ans: True
迭代器:
- python2: 实现了next()方法且可以无参数调用的对象是迭代器
- python3: 实现了__next__()方法且可无参数调用的对象是一个迭代器
反向迭代器: 实现了__reversed__方法的迭代器称为反向迭代器
迭代协议: 同时实现__iter__()、__next__()方法的对象实现了迭代协议, 可被for循环调用
内置类型迭代器
- 文件迭代器
迭代器的优点
快速, 迭代器在python中是以C语言运行的速度来运行的, 而普通的for、while循环均为python运行速度来运行, 理论上来说迭代器的运行速度更快但是也不尽然, 在是实际环境中需要通过计时操作判断哪一种方式更加快速;
可被for循环调用的对象必须实现迭代协议, for循环时, 先调用被循环对象的iter方法获取一个可迭代的对象, 然后可迭代的对象不停调用next()方法来获取新的数据
生成器
生成器是封装后的迭代器, 比迭代器功能强大。
生成器相关概念
生成器: 含有yield的函数或对象被称为生成器
生成器的函数
__del__()
、__getattribute__(self, name, /)
、__iter__(self, /)
、__next__(self, /)
、__repr__(self, /)
、close()
、send(arg)
、throw()
- 调用生成器时, 生成器将返回一个迭代器
- 可通过生成器的
sned(arg)
方法与生成器通信, 协程便是利用此方法实现; 当外部调用生成器的send(arg)方法时, 将唤醒生成器, 生成器内部通过arg = yield r
的形式接收外部发送的数据并存入局部变量arg中, 然后调用内部迭代器的next方法返回一个数据, 然后睡眠。 - 创建迭代器的最佳方案是使用生成器创建
装饰器
上下文管理器
上下文管理器主要用来处理加载需要释放的资源的问题。
概念的理解
case 1: python中的上下文1
2
3
4
5a = 2
print(a)
b = 3
print(b)
python是解释型语言, 代码是从上向下逐条运行的, 在case 1中, print(a)
的上下文分别是该条语句上下的哪些代码;
case 2: 语句附近的上下文1
2
3
4
5
6
7
8f_user = open("user.txt")
f_pass = open("passwd.txt")
for u in f_user:
for p in f_pass:
print(u.strip(), p.strip())
f_user.close()
f_pass.close()
上下文管理器中的上下文: 当通过文件对象读取文件时, 需要先创建文件文件对象, 读取之后需要关闭文件对象; 这些代码在python中可以放在文件对象读取数据的上下, 如:case 2; 也可以放在遥远的上下, 如: case 3; 这些都可以叫做文件对象读取文件的上下文, 上下文管理器中的上下文就是特指这种需要先创建对象, 使用完对象之后需要进行资源释放和回收的上下文环境。
case 3: 遥远的上下文1
2
3
4
5
6
7
8
9
10
11
12
13f_user = open("user.txt")
f_pass = open("passwd.txt")
...好多语句
for u in f_user:
for p in f_pass:
print(u, p)
...好多语句
f_user.close()
f_pass.close()
case 4: 上下文协议1
2
3
4
5
6
7
8
9
10
11
12# 上下文管理器
class Contextor:
def __enter__(self):
print("welcome to contextor")
def __exit__(self, exc_type, exc_val, exc_tb):
print("goodbye.")
contextor = Contextor()
# 调用上下文管理器
with contextor as c:
print("i use a contextor.")
上下文协议:实现了enter()、exit()方法的对象, 实现了上下文协议, with语句调用的对象必须实现上下文协议。
with与上下文管理器
with语句用于上下文管理器的调用, 旨在简化”上下文管理”的重复代码; 可以使用with的语句的对象都是上下文管理器对象, 均实现了上下文管理协议.
case 5: with与上下文管理器1
2
3
4
5
6
7
8
9with open("file1.txt") as f:
print(f.readlines())
'''
with语句的执行过程分为四步:
1. 执行with后的语句获得一个匿名对象lambda_f;
2. 调用lambda_f的__enter__()方法, 返回一个文件操作对象lambda_file并赋值给f;
3. 执行pring(f.readlines())
4. 调用f的__exit__()方法关闭文件操作对象
'''
通过with语句调用open()方法时, open("file1.txt")
会返回一个匿名对象, 记为lambda_f; with语句调用lambda_f的__enter__()
方法, 该方法将返回一个新的对象lambda_file并赋值给as声明的变量f;
case 6: with与自建上下文管理器1
2
3
4
5
6
7
8
9
10class Contextor:
def __enter__(self):
print("welcome to contextor")
def __exit__(self, exc_type, exc_val, exc_tb):
print("goodbye.")
contextor = Contextor()
with contextor as c:
print("i use a contextor.")
通过case 6的结果, 我们将更了解with与上下文管理器之间的运行原理, 结果如下: