Python迭代器与生成器研究记录
Python迭代器与生成器研究记录
前言
迭代器肯定是可迭代对象,但是可迭代对象不一定是迭代器,生成器一定是迭代器,但是迭代器不一定是生成器
生成器是特殊的迭代器,所以生成器一定是迭代器,迭代器一定是可迭代对象
我们平常接触最多的对象中,字符串,字典,列表,集合,元组和open打开的文件对象等都是可迭代的对象因为他们都有__iter__()方法,可以遍历
需要注意的是,我们平常接触最多的对象中,字符串,字典,列表,集合,元组等都不是迭代器因为他们都没有__next__()方法,但是open打开的文件对象却是一个迭代器对象
可迭代对象
1.只要内部有__iter__()方法的对象就是可迭代对象如 字符串,字典,列表集合,元组,包括open打开的文件对象也都是可迭代对象
2.或者可以这样说,只要可以转换成迭代器的对象就是可迭代对象
这些都是可迭代对象
test_list = [1, 3, 4, 7]
test_list.__iter__()
test_str = "test_str"
test_str.__iter__()
test_dict = {"1":12}
test_dict.__iter__()
test_set = {"1", "4", "898"}
test_set.__iter__()
with open("file_path", "r") as file_obj:
file_obj.__iter__()
可迭代对象调用__iter__()方法会返回一个迭代器,代码如下
test_list = [1, 3, 4, 7]
print(test_list.__iter__())
print(type(test_list.__iter__()))
# 可迭代对象调用__iter__()方法返回的就是一个迭代器
# <list_iterator object at 0x000001CEB3AD5518>
# <class 'list_iterator'>
迭代器
迭代器就是有__iter__()方法和__next()__方法的对象,所以迭代器肯定是可迭代对象,但是可迭代对象不一定是迭代器
迭代器对象调用__next__()方法每次会拿到迭代器里面的一个值并返回,直到全部拿完会报错StopIteration
迭代器对象调用__iter__()方法返回的是迭代器本身(和没调用一样),可迭代但是非迭代器的对象调用__iter__()方法也是返回的是基于这个对象的迭代器
需要注意的是,我们平常接触最多的对象中,字符串,字典,列表,集合,元组等都不是迭代器因为他们都没有__next__()方法,但是open打开的文件对象却是一个迭代器对象
# 迭代器的一个特征就是有__next__()方法
test_list = [1, 3, 4, 7]
# 可迭代对象调用__iter__()方法返回的就是一个迭代器
list_iterator_obj = test_list.__iter__()
# 迭代器调用_next__()方法每次就会拿出这个迭代器里面的一个值,直到全部拿完会报错
for i in range(5):
print(list_iterator_obj.__next__())
# 1
# 3
# 4
# 7
# Traceback (most recent call last):
# File "C:/Users/xxx/Desktop/python_test_dir/test_4.py", line 10, in <module>
# print(list_iterator_obj.__next__())
# StopIteration
迭代器对象调用__iter__()方法返回的是他自己,和没调用一样
# 迭代器的特征就是有__next__()方法
test_list = [1, 3, 4, 7]
# 可迭代对象调用__iter__()方法返回的就是一个迭代器
list_iterator_obj = test_list.__iter__()
# 迭代器对象调用__iter__()方法返回的是他自己,和没调用一样
list_iterator_obj2 = list_iterator_obj.__iter__()
print(list_iterator_obj2 is list_iterator_obj) # True
print(list_iterator_obj.__next__()) # 1
print(list_iterator_obj.__next__()) # 3
# 注意这里会返回此迭代器对象直接理解为是 list_iterator_obj = list_iterator_obj (因为是返回自己,所以里面剩余的值状态也是一样的)
list_iterator_obj = list_iterator_obj.__iter__()
print(list_iterator_obj.__next__()) # 4
print(list_iterator_obj.__next__()) # 7
for 循环遍历的本质可以理解成
1,每次调用此对象的__iter__()方法返回这个对象的迭代器版本
2,调用第一步返回的此迭代器版本的__next__()方法拿出里面的一个值
3,循环执行第二步直到所有元素拿完for 循环捕获结束时抛出的StopIteration异常并结束
生成器
生成器可以理解为自己定义的一个迭代器,可以自定义一个生成器,生成器定义有两种方法
1.函数yield关键字返回,含有yield关键字的函数会返回一个生成器对象,对此对象调用__next__()方法会执行此函数对应的yield关键字之前的代码并且返回yield关键字字后的返回值然后截止,下次调用__next__()方法又可以在上次的基础上继续执行
2.生成器表达式(我们以为的"元组推导式"就是生成器表达式,需要注意元组因为是不可变的所以元组没有推导式,类似元组推导式的形式其实是生成器表达式)
函数yield关键字生成器
def test():
print("第一次执行")
yield 1
print("第二次执行")
yield 2
print("第三次执行")
yield 3
print("第四次执行")
yield 4
print("最后一次执行")
# test函数返回一个生成器对象
generator_obj = test()
print(generator_obj) # <generator object test at 0x000001B393528C00>
print(generator_obj.__next__())
# 第一次执行
# 1
print(generator_obj.__next__())
# 第二次执行
# 2
print(generator_obj.__next__())
# 第三次执行
# 3
print(generator_obj.__next__())
# 第四次执行
# 4
print(generator_obj.__next__())
# 最后一次执行
# Traceback (most recent call last):
# File "C:/Users/xxx/Desktop/python_test_dir/test_4.py", line 51, in <module>
# print(generator_obj.__next__())
# StopIteration
生成器表达式
test_list = [10, 20, 30, 40]
generator_obj = (i for i in test_list)
print(generator_obj) # <generator object <genexpr> at 0x0000029852C98C00>
print(generator_obj.__next__()) # 10
print(generator_obj.__next__()) # 20
print(generator_obj.__next__()) # 30
print(generator_obj.__next__()) # 40
```bash
# obj.__next__()方法 等价于next(obj)
# obj.__iter__()方法 等价于iter(obj)
test_list = [10, 20, 30, 40]
generator_obj = (i for i in test_list)
print(generator_obj) # <generator object <genexpr> at 0x0000029852C98C00>
print(generator_obj.__next__()) # 10
print(generator_obj.__iter__()) # <generator object <genexpr> at 0x0000029852C98C00>
print(next(generator_obj)) # 20
print(iter(generator_obj)) # <generator object <genexpr> at 0x0000029852C98C00>
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!