一.可迭代对象
可迭代对象是指实现了 __iter__() 方法的对象。__iter__() 方法返回一个迭代器对象。常见的可迭代对象包摆列表、元组、字符串、字典和集合等。
- s = "world"
- s1 = [1, 2, 3, 4, 5]
- s2 = (1, 2, 3, 4, 5)
- s3 = {"name": "猫"}
- s4 = {1, 2, 3, 4, 5}
- print(isinstance(s, Iterable), isinstance(s1, Iterable), isinstance(s2, Iterable), isinstance(s3, Iterable), isinstance(s4, Iterable))
- # 结果:True True True True True
复制代码 分析:在这段代码中,我们使用了 isinstance() 函数来查抄差别的对象是否是可迭代对象,返回结果均为True,阐明列表、元组、字符串、字典和集合都是可迭代对象
二.迭代器
迭代器是指实现了 __iter__() 和 __next__() 方法的对象。__next__() 方法返回下一个元素,假如没有更多元素则抛出 StopIteration 异常。
类 MyDatas 的迭代器实现
- class MyDatas:
- def __init__(self, n):
- """
- 初始化方法,创建一个包含从1到n的整数列表,并初始化当前索引为0
- :param n: 整数,表示列表的最大值
- """
- self.datas = [i for i in range(1, n + 1)] # 创建包含从1到n的整数列表
- self.current_index = 0 # 初始化当前索引为0
- def __iter__(self):
- """
- 返回迭代器对象自身
- :return: 返回self,即当前对象
- """
- return self
- def __next__(self):
- """
- 返回下一个元素,如果当前索引超出列表范围,抛出IndexError异常
- :return: 返回当前元素
- """
- if self.current_index >= len(self.datas): # 检查当前索引是否超出列表范围
- raise IndexError # 抛出IndexError异常
- else:
- current = self.datas[self.current_index] # 获取当前元素
- self.current_index += 1 # 将当前索引加1
- return current # 返回当前元素
- # 假设md是一个MyDatas对象,例如 md = MyDatas(5)
- while True:
- try:
- for s in md: # 尝试遍历md对象
- print(s) # 打印当前元素
- except IndexError as e: # 捕获IndexError异常
- print("超出范围", e) # 打印错误信息
- break # 退出循环
复制代码 分析:
__init__ 方法
初始化一个包含从1到n的整数列表 self.datas。
初始化当前索引 self.current_index 为0。
__iter__ 方法
返回迭代器对象自身,即 self。这使得 MyDatas 实例可以被用作迭代器。
__next__ 方法
查抄当前索引是否超出列表范围,假如超出则抛出 IndexError 异常。
否则,返回当前元素并将当前索引加1。
- while True:
- try:
- for s in md: # 尝试遍历md对象
- print(s) # 打印当前元素
- except IndexError as e: # 捕获IndexError异常
- print("超出范围", e) # 打印错误信息
- break # 退出循环
复制代码 分析:
while True 循环不断尝试遍历 md 对象。
for s in md 使用 for 循环遍历 md 对象,这会调用 md 的 __iter__() 方法获取迭代器,并调用 __next__() 方法获取下一个元素。
假如 __next__() 方法抛出 IndexError 异常,捕获该异常并打印错误信息,然退却出循环。
总结:
迭代器:实现了 __iter__() 和 __next__() 方法的对象。
自定义迭代器:通过定义类并实现 __iter__() 和 __next__() 方法来创建自定义迭代器。
迭代器的使用:通过 for 循环或其他迭代方式使用迭代器,自动调用 __iter__() 和 __next__() 方法。
异常处理:在迭代过程中处理可能抛出的异常(如 IndexError)。
三.生成器
生成器是Python中一种特殊的迭代器,它使用 yield 关键字来产生值。生成器函数在调用时返回一个生成器对象,每次调用 next() 时,生成器函数会从前次 yield 的位置继续执行,直到遇到下一个 yield 或函数竣事。
生成器的基本概念
生成器函数使用 yield 关键字来产生值,而不是 return。每次调用 next() 时,生成器函数会从前次 yield 的位置继续执行,直到遇到下一个 yield 或函数竣事。
生成器函数
- def my_generator():
- yield 1
- yield 2
- yield 3
- gen = my_generator()
- for item in gen:
- print(item)
复制代码 分析:在这个例子中,my_generator 是一个生成器函数,它使用 yield 关键字来产生值。调用 my_generator() 返回一个生成器对象 gen,我们可以使用 for 循环来遍历它。
生成器表达式
- gen = (x for x in range(1, 4))
- for item in gen:
- print(item)
复制代码 分析:(x for x in range(1, 4)) 是一个生成器表达式,它返回一个生成器对象 gen,我们可以使用 for 循环来遍历它。
上风
结合 sys.getsizeof() 函数,我们可以更直观地理解生成器在内存使用上的上风。sys.getsizeof() 函数用于获取对象的内存占用大小(以字节为单元)。
- # 创建一个包含100万个整数的列表
- list_data = [i for i in range(1000000)]
- # 创建一个生成器表达式,生成100万个整数
- gen_data = (i for i in range(1000000))
- # 打印列表和生成器的内存占用大小
- print(list_data.__sizeof__())
- print(gen_data.__sizeof__())
- # 结果:8448712 176
复制代码 分析:通过比较列表和生成器的内存占用大小,我们可以直观地看到生成器在处理大数据集时的内存上风。生成器非常适合处理大数据集,因为它不会一次性将全部数据加载到内存中,从而节省内存资源。
四.装饰器
装饰器是一种用于修改函数或方法行为的高阶函数。装饰器本质上是一个返回函数的函数,它可以在不修改原函数代码的情况下,增加额外的功能。
- # 装饰器
- def cost_time(f):
- def calc():
- start = time.time()
- f()
- print(f"{f.__name__}的时间开销是{time.time() - start}")
- return calc
- data = [random.randint(1, 10000) for i in range(10000)]
- datas = data.copy()
- @cost_time
- def my_sort1():
- data.sort()
- print(data)
- # my_sort1 = cost_time(my_sort1)
- my_sort1()
- @cost_time
- def my_sort2():
- new_datas = sorted(datas, reverse=False)
- print(new_datas)
- # my_sort2 = cost_time(my_sort2)
- my_sort2()
复制代码 装饰器 cost_time
- def cost_time(f):
- def calc():
- start = time.time()
- f()
- print(f"{f.__name__}的时间开销是{time.time() - start}")
- return calc
复制代码 cost_time 是一个装饰器函数,它接受一个函数 f 作为参数。
在 cost_time 内部定义了一个嵌套函数 calc,这个函数用于测量 f 的执行时间。
start = time.time():纪录函数开始执行的时间。
f():调用原函数 f。
print(f"{f.__name__}的时间开销是{time.time() - start}"):打印函数 f 的名称和执行时间。
cost_time 返回嵌套函数 calc,如许当装饰器应用到一个函数时,实际上是返回了一个新的函数 calc,这个函数包含了原函数 f 的调用和时间测量逻辑
函数 my_sort1 和 my_sort2
- @cost_time
- def my_sort1():
- data.sort()
- print(data)
- # my_sort1 = cost_time(my_sort1)
- my_sort1()
- @cost_time
- def my_sort2():
- new_datas = sorted(datas, reverse=False)
- print(new_datas)
- # my_sort2 = cost_time(my_sort2)
- my_sort2()
复制代码 my_sort1 和 my_sort2 是两个用于排序的函数。
@cost_time 语法是装饰器的应用,相当于 my_sort1 = cost_time(my_sort1) 和 my_sort2 = cost_time(my_sort2)。
这表示在调用 my_sort1 和 my_sort2 时,实际上是调用了 cost_time 返回的 calc 函数。
my_sort1 使用 list.sort() 方法对 data 进行原地排序。
my_sort2 使用 sorted() 函数对 datas 进行排序,并返回一个新的排序后的列表 new_datas。
总结
装饰器 cost_time 用于测量函数执行的时间开销。
my_sort1 和 my_sort2 分别使用差别的排序方法对数据进行排序。
通过装饰器,我们可以在不修改原函数代码的情况下,增加时间测量的功能。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |