1. 可迭代(Iterable)
可迭代 是指一个对象可以返回一个迭代器的对象。也就是说,它实现了 __iter__()
方法或 __getitem__()
方法。常见的可迭代对象有列表、元组、字符串、字典和集合。
from collections.abc import Iterablei = 100
s = "hello"
l = [1, 2, 3]
t = (1, 2, 3)
d = {"name": "qiku"}
set0 = {1, 2, 3}print(isinstance(i, Iterable), # False, 整数不可迭代isinstance(s, Iterable), # True, 字符串可迭代isinstance(l, Iterable), # True, 列表可迭代isinstance(t, Iterable), # True, 元组可迭代isinstance(d, Iterable), # True, 字典可迭代(迭代的是键)isinstance(set0, Iterable) # True, 集合可迭代
)
2. 迭代器(Iterator)
迭代器 是一个对象,它实现了 __iter__()
和 __next__()
方法(在 Python 3 中,__next__()
方法被称为 __next__()
)。迭代器可以用于遍历序列中的元素,每次调用 __next__()
方法时,它返回序列中的下一个元素。迭代器在遍历完所有元素后会抛出 StopIteration
异常。
from collections.abc import Iterable, Iterator # 从 collections.abc 模块导入 Iterable 和 Iteratorclass MyDatas:def __init__(self, n):# 初始化数据列表,从 1 到 nself.datas = [i for i in range(1, n + 1)]self.current_index = 0 # 当前索引,初始化为 0def __iter__(self):# 返回自身,因为它既是可迭代对象也是迭代器return selfdef __next__(self):# 如果当前索引超出数据列表的长度,抛出 StopIteration 异常,表示迭代结束if self.current_index >= len(self.datas):raise StopIterationelse:# 返回当前索引的数据,并将当前索引加 1current = self.datas[self.current_index]self.current_index += 1return currentmd = MyDatas(5) # 创建一个包含 1 到 5 的 MyDatas 实例# 打印 md 是否是 Iterable 和 Iterator
print(isinstance(md, Iterable), isinstance(md, Iterator))# 遍历 MyDatas 实例中的所有数据
for d in md:print(d)
3. 生成器(Generator)
生成器 是一种特殊类型的迭代器,使用函数和 yield
关键字来创建。生成器函数可以像普通函数一样定义,但它们使用 yield
来返回值,而不是 return
。每次调用生成器的 __next__()
方法时,它会从上次 yield
语句处继续执行,直到遇到下一个 yield
语句或函数结束。
# 定义一个列表 l0,并打印其内存大小
l0 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
print(l0.__sizeof__()) # 打印 l0 列表在内存中占用的字节数
print(l0[15]) # 打印列表中索引为 15 的元素# 定义一个生成器表达式 t0,并打印其内存大小
t0 = (i for i in range(1, 1000000000))
print(t0.__sizeof__()) # 打印生成器 t0 在内存中占用的字节数
print(isinstance(t0, Iterable), isinstance(t0, Iterator), isinstance(t0, Generator))
# 打印 t0 是否是 Iterable、Iterator 和 Generator 类型
print(next(t0), next(t0)) # 打印生成器 t0 的前两个值# 定义一个生成器函数 my_datas
def my_datas():yield 1yield 2yield 3yield 10yield 20yield 30return 100 # 生成器结束时返回的值r = my_datas() # 创建生成器对象 rprint(type(r)) # 打印生成器对象 r 的类型# 使用 while 循环遍历生成器 r 的所有值
while True:try:print(next(r)) # 打印生成器 r 的下一个值except StopIteration as e: # 捕捉 StopIteration 异常,表示生成器已结束print("取完了", e) # 打印生成器结束时返回的值break # 退出循环
生成器在内存中占用的字节数通常是固定的,比如在上述例子中是 184 字节。即使列表的元素数量增加,生成器的内存占用也不会显著增加。相比之下,当列表中的元素数量增加时,其内存占用量会显著增长。这是因为列表需要为每个元素分配额外的内存来存储数据。而生成器只在需要时生成数据,因而在处理大量数据时,生成器通常比列表更加节省内存。
4. 装饰器(Decorator)不改变函数原有实现给函数添加新功能
装饰器 是一种用于修改或扩展函数或方法行为的设计模式。装饰器是一个函数,它接受一个函数作为参数,并返回一个新的函数。它们常用于日志记录、权限检查、缓存等。
import time
import random# 定义一个装饰器函数 cost_time,用于计算函数执行时间
def cost_time(f):# 定义内部函数 calc,计算并打印被装饰函数的执行时间def calc():start = time.time() # 记录开始时间f() # 调用被装饰的函数print(f"函数{f.__name__}开销:{time.time() - start}") # 计算并打印执行时间return calc # 返回内部函数 calc# 生成一个包含 10000 个随机整数的列表 datas
datas = [random.randint(0, 10000) for i in range(10000)]
# 创建 datas 的副本 datas2
datas2 = datas.copy()# 使用 cost_time 装饰器装饰 my_sort1 函数
@cost_time
def my_sort1():datas.sort(reverse=True) # 对列表 datas 进行降序排序print(datas) # 打印排序后的列表# 使用 cost_time 装饰器装饰 my_sort2 函数
@cost_time
def my_sort2():datas3 = sorted(datas2, reverse=True) # 对列表 datas2 进行降序排序,并生成新列表 datas3print(datas3) # 打印排序后的新列表# 调用装饰后的 my_sort1 函数,计算其执行时间并打印排序结果
my_sort1()# 调用装饰后的 my_sort2 函数,计算其执行时间并打印排序结果
my_sort2()