1. 可迭代(Iterable)
可迭代 是指一个对象可以返回一个迭代器的对象。也就是说,它实现了 __iter__()
方法或 __getitem__()
方法。常见的可迭代对象有列表、元组、字符串、字典和集合。
from collections.abc import Iterable
i = 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 和 Iterator
class MyDatas:
def __init__(self, n):
# 初始化数据列表,从 1 到 n
self.datas = [i for i in range(1, n + 1)]
self.current_index = 0 # 当前索引,初始化为 0
def __iter__(self):
# 返回自身,因为它既是可迭代对象也是迭代器
return self
def __next__(self):
# 如果当前索引超出数据列表的长度,抛出 StopIteration 异常,表示迭代结束
if self.current_index >= len(self.datas):
raise StopIteration
else:
# 返回当前索引的数据,并将当前索引加 1
current = self.datas[self.current_index]
self.current_index += 1
return current
md = 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 1
yield 2
yield 3
yield 10
yield 20
yield 30
return 100 # 生成器结束时返回的值
r = my_datas() # 创建生成器对象 r
print(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 进行降序排序,并生成新列表 datas3
print(datas3) # 打印排序后的新列表
# 调用装饰后的 my_sort1 函数,计算其执行时间并打印排序结果
my_sort1()
# 调用装饰后的 my_sort2 函数,计算其执行时间并打印排序结果
my_sort2()