提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
在Python中,可迭代(Iterable)、迭代器(Iterator)、生成器(Generator)和装饰器(Decorator)是几个非常重要的概念,它们在编程中扮演着不同的角色,但是它们之间又有一定的联系。
在这告诉大家一句话:迭代器属于可迭代对象,而生成器是特殊的迭代器。
一、可迭代(Iterable)是什么?
可迭代对象是指那些能够返回自身迭代器的对象。在Python中,几乎所有的集合类型(如列表、元组、字典、集合、字符串等)都是可迭代的。迭代是访问集合元素的一种方式,它不需要了解集合的内部结构。
可迭代对象实现了__iter__()方法,该方法返回一个迭代器对象。
s = 'asd' # 字符串
l = [1, 2, 2] # 列表
t = (1, 2, 3) # 元组
d = {'name': '12'} # 字典
set0 = {1, 2, 3} # 集合
type_list = [s, l, t, d, set0]
for e in type_list:
print(isinstance(e, Iterable)) # 返回的结果都为True
二、迭代器(Iterator)是什么?
迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器实现了两个方法:iter()和__next__()。iter()方法返回迭代器对象本身,而__next__()方法返回容器的下一个元素。当没有更多元素时,next()方法会抛出一个StopIteration异常,表示迭代完成。
from collections.abc import Iterator
lst = [1, 2, 3]
it = iter(lst) # it是迭代器
print(isinstance(it, Iterator)) # True
print(next(it)) # 输出 1
print(next(it)) # 输出 2
三、生成器(Generator)是什么?
生成器是一种特殊的迭代器,它使用yield关键字来简化迭代器的创建。生成器函数在每次调用next()方法或迭代时,都会执行到yield表达式处,然后暂停执行,返回yield表达式的值作为迭代器的下一个值。当生成器函数执行完毕或遇到return语句时,迭代将结束。
生成器提供了一种简单的方式来创建迭代器,而无需定义__iter__()和__next__()方法。
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
print(next(gen)) # 输出 1
print(next(gen)) # 输出 2
四、装饰器(Decorator)是什么?
装饰器是Python中一个非常强大的功能,它允许用户在不修改原有函数定义的情况下,增加函数功能。本质上,装饰器是一个函数,它接受一个函数作为参数并返回一个新函数。
装饰器的使用通常是通过@语法来实现的,这使得装饰器的使用非常简洁。装饰器可以用于日志记录、性能测试、事务处理、权限校验等多种场景。
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 输出:
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.
自定义迭代器
class MyData:
def __init__(self, datas):
self.datas = [e for e in datas]
self.index_num = 0
def __iter__(self):
return self
def __next__(self):
if self.index_num == len(self.datas):
raise IndexError # 超出索引异常
else:
current = self.datas[self.index_num]
self.index_num += 1
return current
my_data = MyData('asdqw')
while True:
try:
print(next(my_data))
except IndexError:
print('超出索引')
break